Merge branch 'master' into xwayland-dnd

This commit is contained in:
emersion 2018-04-02 15:57:04 -04:00
commit 8836b4f024
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
80 changed files with 3987 additions and 1491 deletions

View file

@ -8,8 +8,10 @@ lib_wlr_types = static_library(
'wlr_gamma_control.c',
'wlr_idle_inhibit_v1.c',
'wlr_idle.c',
'wlr_idle_inhibit_v1.c',
'wlr_input_device.c',
'wlr_keyboard.c',
'wlr_layer_shell.c',
'wlr_linux_dmabuf.c',
'wlr_list.c',
'wlr_matrix.c',

View file

@ -254,7 +254,7 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev,
}
void wlr_cursor_warp_absolute(struct wlr_cursor *cur,
struct wlr_input_device *dev, double x_mm, double y_mm) {
struct wlr_input_device *dev, double x, double y) {
assert(cur->state->layout);
struct wlr_box *mapping = get_mapping(cur, dev);
@ -262,8 +262,8 @@ void wlr_cursor_warp_absolute(struct wlr_cursor *cur,
mapping = wlr_output_layout_get_box(cur->state->layout, NULL);
}
double x = x_mm > 0 ? mapping->width * x_mm + mapping->x : cur->x;
double y = y_mm > 0 ? mapping->height * y_mm + mapping->y : cur->y;
x = x > 0 ? mapping->width * x + mapping->x : cur->x;
y = y > 0 ? mapping->height * y + mapping->y : cur->y;
wlr_cursor_warp_unchecked(cur, x, y);
}
@ -640,19 +640,15 @@ void wlr_cursor_map_input_to_region(struct wlr_cursor *cur,
}
bool wlr_cursor_absolute_to_layout_coords(struct wlr_cursor *cur,
struct wlr_input_device *device, double x_mm, double y_mm,
double width_mm, double height_mm, double *lx, double *ly) {
if (width_mm <= 0 || height_mm <= 0) {
return false;
}
struct wlr_input_device *device, double x, double y,
double *lx, double *ly) {
struct wlr_box *mapping = get_mapping(cur, device);
if (!mapping) {
mapping = wlr_output_layout_get_box(cur->state->layout, NULL);
}
*lx = x_mm > 0 ? mapping->width * (x_mm / width_mm) + mapping->x : cur->x;
*ly = y_mm > 0 ? mapping->height * (y_mm / height_mm) + mapping->y : cur->y;
*lx = x > 0 ? mapping->width * x + mapping->x : cur->x;
*ly = y > 0 ? mapping->height * y + mapping->y : cur->y;
return true;
}

427
types/wlr_layer_shell.c Normal file
View file

@ -0,0 +1,427 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-server.h>
#include <wlr/types/wlr_layer_shell.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/util/log.h>
#include "util/signal.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
static const char *zwlr_layer_surface_role = "zwlr_layer_surface";
static void resource_handle_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
static const struct zwlr_layer_shell_v1_interface layer_shell_implementation;
static const struct zwlr_layer_surface_v1_interface layer_surface_implementation;
static struct wlr_layer_shell *layer_shell_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwlr_layer_shell_v1_interface,
&layer_shell_implementation));
return wl_resource_get_user_data(resource);
}
static struct wlr_layer_surface *layer_surface_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwlr_layer_surface_v1_interface,
&layer_surface_implementation));
return wl_resource_get_user_data(resource);
}
static void layer_surface_configure_destroy(
struct wlr_layer_surface_configure *configure) {
if (configure == NULL) {
return;
}
wl_list_remove(&configure->link);
free(configure);
}
static void layer_surface_handle_ack_configure(struct wl_client *client,
struct wl_resource *resource, uint32_t serial) {
struct wlr_layer_surface *surface = layer_surface_from_resource(resource);
bool found = false;
struct wlr_layer_surface_configure *configure, *tmp;
wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
if (configure->serial < serial) {
layer_surface_configure_destroy(configure);
} else if (configure->serial == serial) {
found = true;
break;
} else {
break;
}
}
if (!found) {
wl_resource_post_error(resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_SURFACE_STATE,
"wrong configure serial: %u", serial);
return;
}
if (surface->acked_configure) {
layer_surface_configure_destroy(surface->acked_configure);
}
surface->acked_configure = configure;
wl_list_remove(&configure->link);
wl_list_init(&configure->link);
}
static void layer_surface_handle_set_size(struct wl_client *client,
struct wl_resource *resource, uint32_t width, uint32_t height) {
struct wlr_layer_surface *surface = layer_surface_from_resource(resource);
surface->client_pending.desired_width = width;
surface->client_pending.desired_height = height;
}
static void layer_surface_handle_set_anchor(struct wl_client *client,
struct wl_resource *resource, uint32_t anchor) {
const uint32_t max_anchor =
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
if (anchor > max_anchor) {
wl_resource_post_error(resource,
ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_ANCHOR,
"invalid anchor %d", anchor);
}
struct wlr_layer_surface *surface = layer_surface_from_resource(resource);
surface->client_pending.anchor = anchor;
}
static void layer_surface_handle_set_exclusive_zone(struct wl_client *client,
struct wl_resource *resource, int32_t zone) {
struct wlr_layer_surface *surface = layer_surface_from_resource(resource);
surface->client_pending.exclusive_zone = zone;
}
static void layer_surface_handle_set_margin(
struct wl_client *client, struct wl_resource *resource,
int32_t top, int32_t right, int32_t bottom, int32_t left) {
struct wlr_layer_surface *surface = layer_surface_from_resource(resource);
surface->client_pending.margin.top = top;
surface->client_pending.margin.right = right;
surface->client_pending.margin.bottom = bottom;
surface->client_pending.margin.left = left;
}
static void layer_surface_handle_set_keyboard_interactivity(
struct wl_client *client, struct wl_resource *resource,
uint32_t interactive) {
struct wlr_layer_surface *surface = layer_surface_from_resource(resource);
surface->client_pending.keyboard_interactive = !!interactive;
}
static void layer_surface_handle_get_popup(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *popup) {
// TODO
}
static const struct zwlr_layer_surface_v1_interface layer_surface_implementation = {
.destroy = resource_handle_destroy,
.ack_configure = layer_surface_handle_ack_configure,
.set_size = layer_surface_handle_set_size,
.set_anchor = layer_surface_handle_set_anchor,
.set_exclusive_zone = layer_surface_handle_set_exclusive_zone,
.set_margin = layer_surface_handle_set_margin,
.set_keyboard_interactivity = layer_surface_handle_set_keyboard_interactivity,
.get_popup = layer_surface_handle_get_popup,
};
static void layer_surface_unmap(struct wlr_layer_surface *surface) {
// TODO: probably need to ungrab before this event
wlr_signal_emit_safe(&surface->events.unmap, surface);
struct wlr_layer_surface_configure *configure, *tmp;
wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
layer_surface_configure_destroy(configure);
}
surface->configured = surface->mapped = false;
surface->configure_serial = 0;
if (surface->configure_idle) {
wl_event_source_remove(surface->configure_idle);
surface->configure_idle = NULL;
}
surface->configure_next_serial = 0;
}
static void layer_surface_destroy(struct wlr_layer_surface *surface) {
layer_surface_unmap(surface);
wlr_signal_emit_safe(&surface->events.destroy, surface);
wl_resource_set_user_data(surface->resource, NULL);
wl_list_remove(&surface->surface_destroy_listener.link);
wl_list_init(&surface->surface_destroy_listener.link);
wlr_surface_set_role_committed(surface->surface, NULL, NULL);
wl_list_remove(&surface->link);
free(surface);
}
static void layer_surface_resource_destroy(struct wl_resource *resource) {
struct wlr_layer_surface *surface =
layer_surface_from_resource(resource);
if (surface != NULL) {
layer_surface_destroy(surface);
}
}
static bool wlr_layer_surface_state_changed(struct wlr_layer_surface *surface) {
struct wlr_layer_surface_state *state;
if (wl_list_empty(&surface->configure_list)) {
if (surface->acked_configure) {
state = &surface->acked_configure->state;
} else if (!surface->configured) {
return true;
} else {
state = &surface->current;
}
} else {
struct wlr_layer_surface_configure *configure =
wl_container_of(surface->configure_list.prev, configure, link);
state = &configure->state;
}
bool changed = state->actual_width != surface->server_pending.actual_width
|| state->actual_height != surface->server_pending.actual_height;
return changed;
}
void wlr_layer_surface_configure(struct wlr_layer_surface *surface,
uint32_t width, uint32_t height) {
surface->server_pending.actual_width = width;
surface->server_pending.actual_height = height;
if (wlr_layer_surface_state_changed(surface)) {
struct wl_display *display =
wl_client_get_display(wl_resource_get_client(surface->resource));
struct wlr_layer_surface_configure *configure =
calloc(1, sizeof(struct wlr_layer_surface_configure));
if (configure == NULL) {
wl_client_post_no_memory(wl_resource_get_client(surface->resource));
return;
}
surface->configure_next_serial = wl_display_next_serial(display);
wl_list_insert(surface->configure_list.prev, &configure->link);
configure->state.actual_width = width;
configure->state.actual_height = height;
configure->serial = surface->configure_next_serial;
zwlr_layer_surface_v1_send_configure(surface->resource,
configure->serial, configure->state.actual_width,
configure->state.actual_height);
}
}
void wlr_layer_surface_close(struct wlr_layer_surface *surface) {
if (surface->closed) {
return;
}
surface->closed = true;
layer_surface_unmap(surface);
zwlr_layer_surface_v1_send_closed(surface->resource);
}
static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface,
void *role_data) {
struct wlr_layer_surface *surface = role_data;
if (surface->closed) {
// Ignore commits after the compositor has closed it
return;
}
if (surface->acked_configure) {
struct wlr_layer_surface_configure *configure =
surface->acked_configure;
surface->configured = true;
surface->configure_serial = configure->serial;
surface->current.actual_width = configure->state.actual_width;
surface->current.actual_height = configure->state.actual_height;
layer_surface_configure_destroy(configure);
surface->acked_configure = NULL;
}
if (wlr_surface_has_buffer(surface->surface) && !surface->configured) {
wl_resource_post_error(surface->resource,
ZWLR_LAYER_SHELL_V1_ERROR_ALREADY_CONSTRUCTED,
"layer_surface has never been configured");
return;
}
surface->current.anchor = surface->client_pending.anchor;
surface->current.exclusive_zone = surface->client_pending.exclusive_zone;
surface->current.margin = surface->client_pending.margin;
surface->current.keyboard_interactive =
surface->client_pending.keyboard_interactive;
surface->current.desired_width = surface->client_pending.desired_width;
surface->current.desired_height = surface->client_pending.desired_height;
if (!surface->added) {
surface->added = true;
wlr_signal_emit_safe(&surface->shell->events.new_surface,
surface);
}
if (surface->configured && wlr_surface_has_buffer(surface->surface) &&
!surface->mapped) {
surface->mapped = true;
wlr_signal_emit_safe(&surface->events.map, surface);
}
if (surface->configured && !wlr_surface_has_buffer(surface->surface) &&
surface->mapped) {
layer_surface_unmap(surface);
}
}
static void handle_wlr_surface_destroyed(struct wl_listener *listener,
void *data) {
struct wlr_layer_surface *layer_surface =
wl_container_of(listener, layer_surface, surface_destroy_listener);
layer_surface_destroy(layer_surface);
}
static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client,
struct wl_resource *client_resource, uint32_t id,
struct wl_resource *surface_resource,
struct wl_resource *output_resource,
uint32_t layer, const char *namespace) {
struct wlr_layer_shell *shell =
layer_shell_from_resource(client_resource);
struct wlr_surface *wlr_surface =
wlr_surface_from_resource(surface_resource);
if (wlr_surface_set_role(wlr_surface, zwlr_layer_surface_role,
client_resource, ZWLR_LAYER_SHELL_V1_ERROR_ROLE)) {
return;
}
struct wlr_layer_surface *surface =
calloc(1, sizeof(struct wlr_layer_surface));
if (surface == NULL) {
wl_client_post_no_memory(wl_client);
return;
}
surface->shell = shell;
surface->surface = wlr_surface;
surface->output = wlr_output_from_resource(output_resource);
surface->resource = wl_resource_create(wl_client,
&zwlr_layer_surface_v1_interface,
wl_resource_get_version(client_resource),
id);
surface->namespace = strdup(namespace);
surface->layer = layer;
if (surface->resource == NULL || surface->namespace == NULL) {
free(surface);
wl_client_post_no_memory(wl_client);
return;
}
if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
wl_resource_post_error(surface->resource,
ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER,
"Invalid layer %d", layer);
free(surface);
return;
}
wl_list_init(&surface->configure_list);
wl_signal_init(&surface->events.destroy);
wl_signal_add(&surface->surface->events.destroy,
&surface->surface_destroy_listener);
surface->surface_destroy_listener.notify = handle_wlr_surface_destroyed;
wl_signal_init(&surface->events.map);
wl_signal_init(&surface->events.unmap);
wlr_surface_set_role_committed(surface->surface,
handle_wlr_surface_committed, surface);
wlr_log(L_DEBUG, "new layer_surface %p (res %p)",
surface, surface->resource);
wl_resource_set_implementation(surface->resource,
&layer_surface_implementation, surface, layer_surface_resource_destroy);
wl_list_insert(&shell->surfaces, &surface->link);
}
static const struct zwlr_layer_shell_v1_interface layer_shell_implementation = {
.get_layer_surface = layer_shell_handle_get_layer_surface,
};
static void client_handle_destroy(struct wl_resource *resource) {
struct wl_client *client = wl_resource_get_client(resource);
struct wlr_layer_shell *shell = layer_shell_from_resource(resource);
struct wlr_layer_surface *surface, *tmp = NULL;
wl_list_for_each_safe(surface, tmp, &shell->surfaces, link) {
if (wl_resource_get_client(surface->resource) == client) {
layer_surface_destroy(surface);
}
}
wl_list_remove(wl_resource_get_link(resource));
}
static void layer_shell_bind(struct wl_client *wl_client, void *data,
uint32_t version, uint32_t id) {
struct wlr_layer_shell *layer_shell = data;
assert(wl_client && layer_shell);
struct wl_resource *resource = wl_resource_create(
wl_client, &zwlr_layer_shell_v1_interface, version, id);
if (resource == NULL) {
wl_client_post_no_memory(wl_client);
return;
}
wl_resource_set_implementation(resource,
&layer_shell_implementation, layer_shell, client_handle_destroy);
wl_list_insert(&layer_shell->client_resources,
wl_resource_get_link(resource));
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_layer_shell *layer_shell =
wl_container_of(listener, layer_shell, display_destroy);
wlr_layer_shell_destroy(layer_shell);
}
struct wlr_layer_shell *wlr_layer_shell_create(struct wl_display *display) {
struct wlr_layer_shell *layer_shell =
calloc(1, sizeof(struct wlr_layer_shell));
if (!layer_shell) {
return NULL;
}
wl_list_init(&layer_shell->client_resources);
wl_list_init(&layer_shell->surfaces);
struct wl_global *wl_global = wl_global_create(display,
&zwlr_layer_shell_v1_interface, 1, layer_shell, layer_shell_bind);
if (!wl_global) {
free(layer_shell);
return NULL;
}
layer_shell->wl_global = wl_global;
wl_signal_init(&layer_shell->events.new_surface);
layer_shell->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &layer_shell->display_destroy);
return layer_shell;
}
void wlr_layer_shell_destroy(struct wlr_layer_shell *layer_shell) {
if (!layer_shell) {
return;
}
struct wl_resource *client, *tmp;
wl_resource_for_each_safe(client, tmp, &layer_shell->client_resources) {
wl_resource_destroy(client);
}
wl_list_remove(&layer_shell->display_destroy.link);
wl_global_destroy(layer_shell->wl_global);
free(layer_shell);
}

View file

@ -19,11 +19,6 @@ static const struct wl_buffer_interface wl_buffer_impl = {
wl_buffer_destroy,
};
bool wlr_dmabuf_buffer_has_inverted_y(struct wlr_dmabuf_buffer *dmabuf) {
return dmabuf->attributes.flags
& ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT;
}
bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) {
if (!wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
&wl_buffer_impl)) {

View file

@ -731,15 +731,11 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
return true;
}
if (cursor->texture == NULL) {
cursor->texture = wlr_render_texture_create(renderer);
if (cursor->texture == NULL) {
return false;
}
}
wlr_texture_destroy(cursor->texture);
return wlr_texture_upload_pixels(cursor->texture, WL_SHM_FORMAT_ARGB8888,
cursor->texture = wlr_texture_from_pixels(renderer, WL_SHM_FORMAT_ARGB8888,
stride, width, height, pixels);
return cursor->texture != NULL;
}
static void output_cursor_commit(struct wlr_output_cursor *cursor) {
@ -901,9 +897,7 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
}
cursor->output->hardware_cursor = NULL;
}
if (cursor->texture != NULL) {
wlr_texture_destroy(cursor->texture);
}
wlr_texture_destroy(cursor->texture);
wl_list_remove(&cursor->link);
free(cursor);
}

View file

@ -191,7 +191,7 @@ static struct wlr_output_layout_output *wlr_output_layout_output_create(
}
void wlr_output_layout_add(struct wlr_output_layout *layout,
struct wlr_output *output, int x, int y) {
struct wlr_output *output, int lx, int ly) {
struct wlr_output_layout_output *l_output =
wlr_output_layout_get(layout, output);
if (!l_output) {
@ -201,8 +201,8 @@ void wlr_output_layout_add(struct wlr_output_layout *layout,
return;
}
}
l_output->x = x;
l_output->y = y;
l_output->x = lx;
l_output->y = ly;
l_output->state->auto_configured = false;
wlr_output_layout_reconfigure(layout);
wlr_output_create_global(output);
@ -221,19 +221,19 @@ struct wlr_output_layout_output *wlr_output_layout_get(
}
bool wlr_output_layout_contains_point(struct wlr_output_layout *layout,
struct wlr_output *reference, int x, int y) {
struct wlr_output *reference, int lx, int ly) {
if (reference) {
struct wlr_output_layout_output *l_output =
wlr_output_layout_get(layout, reference);
struct wlr_box *box = wlr_output_layout_output_get_box(l_output);
return wlr_box_contains_point(box, x, y);
return wlr_box_contains_point(box, lx, ly);
} else {
return !!wlr_output_layout_output_at(layout, x, y);
return !!wlr_output_layout_output_at(layout, lx, ly);
}
}
bool wlr_output_layout_intersects(struct wlr_output_layout *layout,
struct wlr_output *reference, const struct wlr_box *target_box) {
struct wlr_output *reference, const struct wlr_box *target_lbox) {
struct wlr_box out_box;
if (reference == NULL) {
@ -241,7 +241,7 @@ bool wlr_output_layout_intersects(struct wlr_output_layout *layout,
wl_list_for_each(l_output, &layout->outputs, link) {
struct wlr_box *output_box =
wlr_output_layout_output_get_box(l_output);
if (wlr_box_intersection(output_box, target_box, &out_box)) {
if (wlr_box_intersection(output_box, target_lbox, &out_box)) {
return true;
}
}
@ -254,16 +254,16 @@ bool wlr_output_layout_intersects(struct wlr_output_layout *layout,
}
struct wlr_box *output_box = wlr_output_layout_output_get_box(l_output);
return wlr_box_intersection(output_box, target_box, &out_box);
return wlr_box_intersection(output_box, target_lbox, &out_box);
}
}
struct wlr_output *wlr_output_layout_output_at(struct wlr_output_layout *layout,
double x, double y) {
double lx, double ly) {
struct wlr_output_layout_output *l_output;
wl_list_for_each(l_output, &layout->outputs, link) {
struct wlr_box *box = wlr_output_layout_output_get_box(l_output);
if (wlr_box_contains_point(box, x, y)) {
if (wlr_box_contains_point(box, lx, ly)) {
return l_output->output;
}
}
@ -271,12 +271,12 @@ struct wlr_output *wlr_output_layout_output_at(struct wlr_output_layout *layout,
}
void wlr_output_layout_move(struct wlr_output_layout *layout,
struct wlr_output *output, int x, int y) {
struct wlr_output *output, int lx, int ly) {
struct wlr_output_layout_output *l_output =
wlr_output_layout_get(layout, output);
if (l_output) {
l_output->x = x;
l_output->y = y;
l_output->x = lx;
l_output->y = ly;
l_output->state->auto_configured = false;
wlr_output_layout_reconfigure(layout);
} else {
@ -295,24 +295,28 @@ void wlr_output_layout_remove(struct wlr_output_layout *layout,
}
void wlr_output_layout_output_coords(struct wlr_output_layout *layout,
struct wlr_output *reference, double *x, double *y) {
struct wlr_output *reference, double *lx, double *ly) {
assert(layout && reference);
double src_x = *x;
double src_y = *y;
double src_x = *lx;
double src_y = *ly;
struct wlr_output_layout_output *l_output;
wl_list_for_each(l_output, &layout->outputs, link) {
if (l_output->output == reference) {
*x = src_x - (double)l_output->x;
*y = src_y - (double)l_output->y;
*lx = src_x - (double)l_output->x;
*ly = src_y - (double)l_output->y;
return;
}
}
}
void wlr_output_layout_closest_point(struct wlr_output_layout *layout,
struct wlr_output *reference, double x, double y, double *dest_x,
double *dest_y) {
struct wlr_output *reference, double lx, double ly, double *dest_lx,
double *dest_ly) {
if (dest_lx == NULL && dest_ly == NULL) {
return;
}
double min_x = DBL_MAX, min_y = DBL_MAX, min_distance = DBL_MAX;
struct wlr_output_layout_output *l_output;
wl_list_for_each(l_output, &layout->outputs, link) {
@ -322,11 +326,11 @@ void wlr_output_layout_closest_point(struct wlr_output_layout *layout,
double output_x, output_y, output_distance;
struct wlr_box *box = wlr_output_layout_output_get_box(l_output);
wlr_box_closest_point(box, x, y, &output_x, &output_y);
wlr_box_closest_point(box, lx, ly, &output_x, &output_y);
// calculate squared distance suitable for comparison
output_distance =
(x - output_x) * (x - output_x) + (y - output_y) * (y - output_y);
(lx - output_x) * (lx - output_x) + (ly - output_y) * (ly - output_y);
if (!isfinite(output_distance)) {
output_distance = DBL_MAX;
@ -339,8 +343,12 @@ void wlr_output_layout_closest_point(struct wlr_output_layout *layout,
}
}
*dest_x = min_x;
*dest_y = min_y;
if (dest_lx) {
*dest_lx = min_x;
}
if (dest_ly) {
*dest_ly = min_y;
}
}
struct wlr_box *wlr_output_layout_get_box(
@ -425,7 +433,7 @@ struct wlr_output *wlr_output_layout_get_center_output(
struct wlr_output *wlr_output_layout_adjacent_output(
struct wlr_output_layout *layout, enum wlr_direction direction,
struct wlr_output *reference, double ref_x, double ref_y) {
struct wlr_output *reference, double ref_lx, double ref_ly) {
assert(reference);
struct wlr_box *ref_box = wlr_output_layout_get_box(layout, reference);
@ -460,9 +468,9 @@ struct wlr_output *wlr_output_layout_adjacent_output(
// calculate distance from the given reference point
double x, y;
wlr_output_layout_closest_point(layout, l_output->output,
ref_x, ref_y, &x, &y);
ref_lx, ref_ly, &x, &y);
double distance =
(x - ref_x) * (x - ref_x) + (y - ref_y) * (y - ref_y);
(x - ref_lx) * (x - ref_lx) + (y - ref_ly) * (y - ref_ly);
if (distance < min_distance) {
min_distance = distance;
closest_output = l_output->output;

View file

@ -1258,8 +1258,9 @@ bool wlr_seat_touch_has_grab(struct wlr_seat *seat) {
}
bool wlr_seat_validate_grab_serial(struct wlr_seat *seat, uint32_t serial) {
return serial == seat->pointer_state.grab_serial ||
serial == seat->touch_state.grab_serial;
return true;
//return serial == seat->pointer_state.grab_serial ||
// serial == seat->touch_state.grab_serial;
}
struct wlr_seat_client *wlr_seat_client_from_resource(

View file

@ -155,8 +155,24 @@ static bool wlr_surface_update_size(struct wlr_surface *surface,
int scale = state->scale;
enum wl_output_transform transform = state->transform;
wlr_texture_get_buffer_size(surface->texture, state->buffer,
&state->buffer_width, &state->buffer_height);
struct wl_shm_buffer *buf = wl_shm_buffer_get(state->buffer);
if (buf != NULL) {
state->buffer_width = wl_shm_buffer_get_width(buf);
state->buffer_height = wl_shm_buffer_get_height(buf);
} else if (wlr_renderer_resource_is_wl_drm_buffer(surface->renderer,
state->buffer)) {
wlr_renderer_wl_drm_buffer_get_size(surface->renderer, state->buffer,
&state->buffer_width, &state->buffer_height);
} else if (wlr_dmabuf_resource_is_buffer(state->buffer)) {
struct wlr_dmabuf_buffer *dmabuf =
wlr_dmabuf_buffer_from_buffer_resource(state->buffer);
state->buffer_width = dmabuf->attributes.width;
state->buffer_height = dmabuf->attributes.height;
} else {
wlr_log(L_ERROR, "Unknown buffer handle attached");
state->buffer_width = 0;
state->buffer_height = 0;
}
int width = state->buffer_width / scale;
int height = state->buffer_height / scale;
@ -315,52 +331,66 @@ static void wlr_surface_damage_subsurfaces(struct wlr_subsurface *subsurface) {
}
static void wlr_surface_apply_damage(struct wlr_surface *surface,
bool reupload_buffer) {
if (!surface->current->buffer) {
bool invalid_buffer, bool reupload_buffer) {
struct wl_resource *resource = surface->current->buffer;
if (resource == NULL) {
return;
}
struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer);
if (!buffer) {
if (wlr_renderer_buffer_is_drm(surface->renderer,
surface->current->buffer)) {
wlr_texture_upload_drm(surface->texture, surface->current->buffer);
goto release;
} else if (wlr_dmabuf_resource_is_buffer(surface->current->buffer)) {
wlr_texture_upload_dmabuf(surface->texture, surface->current->buffer);
goto release;
struct wl_shm_buffer *buf = wl_shm_buffer_get(resource);
if (buf != NULL) {
wl_shm_buffer_begin_access(buf);
enum wl_shm_format fmt = wl_shm_buffer_get_format(buf);
int32_t stride = wl_shm_buffer_get_stride(buf);
int32_t width = wl_shm_buffer_get_width(buf);
int32_t height = wl_shm_buffer_get_height(buf);
void *data = wl_shm_buffer_get_data(buf);
if (surface->texture == NULL || reupload_buffer) {
wlr_texture_destroy(surface->texture);
surface->texture = wlr_texture_from_pixels(surface->renderer, fmt,
stride, width, height, data);
} else {
wlr_log(L_INFO, "Unknown buffer handle attached");
return;
}
}
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_copy(&damage, &surface->current->buffer_damage);
pixman_region32_intersect_rect(&damage, &damage, 0, 0,
surface->current->buffer_width,
surface->current->buffer_height);
uint32_t format = wl_shm_buffer_get_format(buffer);
if (reupload_buffer) {
wlr_texture_upload_shm(surface->texture, format, buffer);
} else {
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_copy(&damage, &surface->current->buffer_damage);
pixman_region32_intersect_rect(&damage, &damage, 0, 0,
surface->current->buffer_width, surface->current->buffer_height);
int n;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &n);
for (int i = 0; i < n; ++i) {
pixman_box32_t rect = rects[i];
if (!wlr_texture_update_shm(surface->texture, format,
rect.x1, rect.y1,
rect.x2 - rect.x1,
rect.y2 - rect.y1,
buffer)) {
break;
int n;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &n);
for (int i = 0; i < n; ++i) {
pixman_box32_t *r = &rects[i];
if (!wlr_texture_write_pixels(surface->texture, fmt, stride,
r->x2 - r->x1, r->y2 - r->y1, r->x1, r->y1,
r->x1, r->y1, data)) {
break;
}
}
pixman_region32_fini(&damage);
}
pixman_region32_fini(&damage);
wl_shm_buffer_end_access(buf);
} else if (invalid_buffer || reupload_buffer) {
wlr_texture_destroy(surface->texture);
if (wlr_renderer_resource_is_wl_drm_buffer(surface->renderer, resource)) {
surface->texture =
wlr_texture_from_wl_drm(surface->renderer, resource);
} else if (wlr_dmabuf_resource_is_buffer(resource)) {
struct wlr_dmabuf_buffer *dmabuf =
wlr_dmabuf_buffer_from_buffer_resource(resource);
surface->texture =
wlr_texture_from_dmabuf(surface->renderer, &dmabuf->attributes);
} else {
surface->texture = NULL;
wlr_log(L_ERROR, "Unknown buffer handle attached");
}
}
release:
wlr_surface_state_release_buffer(surface->current);
}
@ -368,19 +398,19 @@ static void wlr_surface_commit_pending(struct wlr_surface *surface) {
int32_t oldw = surface->current->buffer_width;
int32_t oldh = surface->current->buffer_height;
bool null_buffer_commit =
(surface->pending->invalid & WLR_SURFACE_INVALID_BUFFER &&
surface->pending->buffer == NULL);
bool invalid_buffer = surface->pending->invalid & WLR_SURFACE_INVALID_BUFFER;
bool null_buffer_commit = invalid_buffer && surface->pending->buffer == NULL;
wlr_surface_move_state(surface, surface->pending, surface->current);
if (null_buffer_commit) {
surface->texture->valid = false;
wlr_texture_destroy(surface->texture);
surface->texture = NULL;
}
bool reupload_buffer = oldw != surface->current->buffer_width ||
oldh != surface->current->buffer_height;
wlr_surface_apply_damage(surface, reupload_buffer);
wlr_surface_apply_damage(surface, invalid_buffer, reupload_buffer);
// commit subsurface order
struct wlr_subsurface *subsurface;
@ -611,7 +641,6 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
}
wlr_log(L_DEBUG, "New wlr_surface %p (res %p)", surface, res);
surface->renderer = renderer;
surface->texture = wlr_render_texture_create(renderer);
surface->resource = res;
surface->current = wlr_surface_state_create();
@ -628,7 +657,7 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
}
bool wlr_surface_has_buffer(struct wlr_surface *surface) {
return surface->texture && surface->texture->valid;
return surface->texture != NULL;
}
int wlr_surface_set_role(struct wlr_surface *surface, const char *role,
@ -923,3 +952,10 @@ void wlr_surface_set_role_committed(struct wlr_surface *surface,
surface->role_committed = role_committed;
surface->role_data = role_data;
}
bool wlr_surface_point_accepts_input(
struct wlr_surface *surface, double sx, double sy) {
return sx >= 0 && sx <= surface->current->width &&
sy >= 0 && sy <= surface->current->height &&
pixman_region32_contains_point(&surface->current->input, sx, sy, NULL);
}

View file

@ -77,7 +77,7 @@ void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager,
}
struct wlr_xcursor_image *image = xcursor->images[0];
wlr_cursor_set_image(cursor, image->buffer, image->width,
wlr_cursor_set_image(cursor, image->buffer, image->width * 4,
image->width, image->height, image->hotspot_x, image->hotspot_y,
theme->scale);
}

View file

@ -198,16 +198,15 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) {
wlr_signal_emit_safe(&surface->events.unmap, surface);
}
if (surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
wl_resource_set_user_data(surface->toplevel->resource, NULL);
free(surface->toplevel);
surface->toplevel = NULL;
}
if (surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
wl_resource_set_user_data(surface->popup->resource, NULL);
if (surface->popup->seat) {
switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
free(surface->toplevel->title);
surface->toplevel->title = NULL;
free(surface->toplevel->app_id);
surface->toplevel->app_id = NULL;
break;
case WLR_XDG_SURFACE_ROLE_POPUP:
if (surface->popup->seat != NULL) {
struct wlr_xdg_popup_grab *grab =
xdg_shell_popup_grab_from_seat(surface->client->shell,
surface->popup->seat);
@ -222,11 +221,12 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) {
wlr_seat_keyboard_end_grab(grab->seat);
}
}
}
wl_list_remove(&surface->popup->link);
free(surface->popup);
surface->popup = NULL;
surface->popup->seat = NULL;
}
break;
case WLR_XDG_SURFACE_ROLE_NONE:
assert(false && "not reached");
}
struct wlr_xdg_surface_configure *configure, *tmp;
@ -234,13 +234,7 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) {
xdg_surface_configure_destroy(configure);
}
surface->role = WLR_XDG_SURFACE_ROLE_NONE;
free(surface->title);
surface->title = NULL;
free(surface->app_id);
surface->app_id = NULL;
surface->added = surface->configured = surface->mapped = false;
surface->configured = surface->mapped = false;
surface->configure_serial = 0;
if (surface->configure_idle) {
wl_event_source_remove(surface->configure_idle);
@ -253,6 +247,29 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) {
memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
}
static void xdg_toplevel_destroy(struct wlr_xdg_surface *surface) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
xdg_surface_unmap(surface);
wl_resource_set_user_data(surface->toplevel->resource, NULL);
free(surface->toplevel);
surface->toplevel = NULL;
surface->role = WLR_XDG_SURFACE_ROLE_NONE;
}
static void xdg_popup_destroy(struct wlr_xdg_surface *surface) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_POPUP);
xdg_surface_unmap(surface);
wl_resource_set_user_data(surface->popup->resource, NULL);
wl_list_remove(&surface->popup->link);
free(surface->popup);
surface->popup = NULL;
surface->role = WLR_XDG_SURFACE_ROLE_NONE;
}
static void xdg_surface_destroy(struct wlr_xdg_surface *surface) {
if (surface->role != WLR_XDG_SURFACE_ROLE_NONE) {
xdg_surface_unmap(surface);
@ -260,6 +277,18 @@ static void xdg_surface_destroy(struct wlr_xdg_surface *surface) {
wlr_signal_emit_safe(&surface->events.destroy, surface);
switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
xdg_toplevel_destroy(surface);
break;
case WLR_XDG_SURFACE_ROLE_POPUP:
xdg_popup_destroy(surface);
break;
case WLR_XDG_SURFACE_ROLE_NONE:
// This space is intentionally left blank
break;
}
wl_resource_set_user_data(surface->resource, NULL);
wl_list_remove(&surface->link);
wl_list_remove(&surface->surface_destroy_listener.link);
@ -574,7 +603,7 @@ static void xdg_popup_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_popup_resource(resource);
if (surface != NULL) {
xdg_surface_unmap(surface);
xdg_popup_destroy(surface);
}
}
@ -673,8 +702,8 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client,
return;
}
free(surface->title);
surface->title = tmp;
free(surface->toplevel->title);
surface->toplevel->title = tmp;
}
static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
@ -688,8 +717,8 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
return;
}
free(surface->app_id);
surface->app_id = tmp;
free(surface->toplevel->app_id);
surface->toplevel->app_id = tmp;
}
static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
@ -720,7 +749,7 @@ static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
.y = y,
};
wlr_signal_emit_safe(&surface->events.request_show_window_menu, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_show_window_menu, &event);
}
static void xdg_toplevel_handle_move(struct wl_client *client,
@ -749,7 +778,7 @@ static void xdg_toplevel_handle_move(struct wl_client *client,
.serial = serial,
};
wlr_signal_emit_safe(&surface->events.request_move, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_move, &event);
}
static void xdg_toplevel_handle_resize(struct wl_client *client,
@ -779,39 +808,39 @@ static void xdg_toplevel_handle_resize(struct wl_client *client,
.edges = edges,
};
wlr_signal_emit_safe(&surface->events.request_resize, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_resize, &event);
}
static void xdg_toplevel_handle_set_max_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.max_width = width;
surface->toplevel->next.max_height = height;
surface->toplevel->client_pending.max_width = width;
surface->toplevel->client_pending.max_height = height;
}
static void xdg_toplevel_handle_set_min_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.min_width = width;
surface->toplevel->next.min_height = height;
surface->toplevel->client_pending.min_width = width;
surface->toplevel->client_pending.min_height = height;
}
static void xdg_toplevel_handle_set_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.maximized = true;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
surface->toplevel->client_pending.maximized = true;
wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
}
static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.maximized = false;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
surface->toplevel->client_pending.maximized = false;
wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
}
static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
@ -824,7 +853,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
output = wlr_output_from_resource(output_resource);
}
surface->toplevel->next.fullscreen = true;
surface->toplevel->client_pending.fullscreen = true;
struct wlr_xdg_toplevel_set_fullscreen_event event = {
.surface = surface,
@ -832,7 +861,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
.output = output,
};
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event);
}
static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
@ -840,7 +869,7 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.fullscreen = false;
surface->toplevel->client_pending.fullscreen = false;
struct wlr_xdg_toplevel_set_fullscreen_event event = {
.surface = surface,
@ -848,14 +877,14 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
.output = NULL,
};
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event);
}
static void xdg_toplevel_handle_set_minimized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
wlr_signal_emit_safe(&surface->events.request_minimize, surface);
wlr_signal_emit_safe(&surface->toplevel->events.request_minimize, surface);
}
static const struct xdg_toplevel_interface xdg_toplevel_implementation = {
@ -887,7 +916,7 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
if (surface != NULL) {
xdg_surface_unmap(surface);
xdg_toplevel_destroy(surface);
}
}
@ -905,6 +934,12 @@ static void xdg_surface_handle_get_toplevel(struct wl_client *client,
wl_resource_post_no_memory(resource);
return;
}
wl_signal_init(&surface->toplevel->events.request_maximize);
wl_signal_init(&surface->toplevel->events.request_fullscreen);
wl_signal_init(&surface->toplevel->events.request_minimize);
wl_signal_init(&surface->toplevel->events.request_move);
wl_signal_init(&surface->toplevel->events.request_resize);
wl_signal_init(&surface->toplevel->events.request_show_window_menu);
surface->role = WLR_XDG_SURFACE_ROLE_TOPLEVEL;
surface->toplevel->base = surface;
@ -1052,25 +1087,25 @@ static bool wlr_xdg_surface_toplevel_state_compare(
configured.height = configure->toplevel_state->height;
}
if (state->pending.activated != configured.state.activated) {
if (state->server_pending.activated != configured.state.activated) {
return false;
}
if (state->pending.fullscreen != configured.state.fullscreen) {
if (state->server_pending.fullscreen != configured.state.fullscreen) {
return false;
}
if (state->pending.maximized != configured.state.maximized) {
if (state->server_pending.maximized != configured.state.maximized) {
return false;
}
if (state->pending.resizing != configured.state.resizing) {
if (state->server_pending.resizing != configured.state.resizing) {
return false;
}
if (state->pending.width == configured.width &&
state->pending.height == configured.height) {
if (state->server_pending.width == configured.width &&
state->server_pending.height == configured.height) {
return true;
}
if (state->pending.width == 0 && state->pending.height == 0) {
if (state->server_pending.width == 0 && state->server_pending.height == 0) {
return true;
}
@ -1088,12 +1123,12 @@ static void wlr_xdg_toplevel_send_configure(
wl_resource_post_no_memory(surface->toplevel->resource);
return;
}
*configure->toplevel_state = surface->toplevel->pending;
*configure->toplevel_state = surface->toplevel->server_pending;
uint32_t *s;
struct wl_array states;
wl_array_init(&states);
if (surface->toplevel->pending.maximized) {
if (surface->toplevel->server_pending.maximized) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for maximized xdg_toplevel");
@ -1101,7 +1136,7 @@ static void wlr_xdg_toplevel_send_configure(
}
*s = XDG_TOPLEVEL_STATE_MAXIMIZED;
}
if (surface->toplevel->pending.fullscreen) {
if (surface->toplevel->server_pending.fullscreen) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for fullscreen xdg_toplevel");
@ -1109,7 +1144,7 @@ static void wlr_xdg_toplevel_send_configure(
}
*s = XDG_TOPLEVEL_STATE_FULLSCREEN;
}
if (surface->toplevel->pending.resizing) {
if (surface->toplevel->server_pending.resizing) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for resizing xdg_toplevel");
@ -1117,7 +1152,7 @@ static void wlr_xdg_toplevel_send_configure(
}
*s = XDG_TOPLEVEL_STATE_RESIZING;
}
if (surface->toplevel->pending.activated) {
if (surface->toplevel->server_pending.activated) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for activated xdg_toplevel");
@ -1126,8 +1161,8 @@ static void wlr_xdg_toplevel_send_configure(
*s = XDG_TOPLEVEL_STATE_ACTIVATED;
}
uint32_t width = surface->toplevel->pending.width;
uint32_t height = surface->toplevel->pending.height;
uint32_t width = surface->toplevel->server_pending.width;
uint32_t height = surface->toplevel->server_pending.height;
xdg_toplevel_send_configure(surface->toplevel->resource, width, height,
&states);
@ -1235,13 +1270,13 @@ static void wlr_xdg_surface_toplevel_committed(
// update state that doesn't need compositor approval
surface->toplevel->current.max_width =
surface->toplevel->next.max_width;
surface->toplevel->client_pending.max_width;
surface->toplevel->current.min_width =
surface->toplevel->next.min_width;
surface->toplevel->client_pending.min_width;
surface->toplevel->current.max_height =
surface->toplevel->next.max_height;
surface->toplevel->client_pending.max_height;
surface->toplevel->current.min_height =
surface->toplevel->next.min_height;
surface->toplevel->client_pending.min_height;
}
static void wlr_xdg_surface_popup_committed(
@ -1349,12 +1384,6 @@ static void xdg_shell_handle_get_xdg_surface(struct wl_client *wl_client,
wl_list_init(&surface->configure_list);
wl_list_init(&surface->popups);
wl_signal_init(&surface->events.request_maximize);
wl_signal_init(&surface->events.request_fullscreen);
wl_signal_init(&surface->events.request_minimize);
wl_signal_init(&surface->events.request_move);
wl_signal_init(&surface->events.request_resize);
wl_signal_init(&surface->events.request_show_window_menu);
wl_signal_init(&surface->events.destroy);
wl_signal_init(&surface->events.ping_timeout);
wl_signal_init(&surface->events.new_popup);
@ -1532,8 +1561,8 @@ void wlr_xdg_surface_ping(struct wlr_xdg_surface *surface) {
uint32_t wlr_xdg_toplevel_set_size(struct wlr_xdg_surface *surface,
uint32_t width, uint32_t height) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
surface->toplevel->pending.width = width;
surface->toplevel->pending.height = height;
surface->toplevel->server_pending.width = width;
surface->toplevel->server_pending.height = height;
return wlr_xdg_surface_schedule_configure(surface);
}
@ -1541,7 +1570,7 @@ uint32_t wlr_xdg_toplevel_set_size(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_activated(struct wlr_xdg_surface *surface,
bool activated) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
surface->toplevel->pending.activated = activated;
surface->toplevel->server_pending.activated = activated;
return wlr_xdg_surface_schedule_configure(surface);
}
@ -1549,7 +1578,7 @@ uint32_t wlr_xdg_toplevel_set_activated(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_maximized(struct wlr_xdg_surface *surface,
bool maximized) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
surface->toplevel->pending.maximized = maximized;
surface->toplevel->server_pending.maximized = maximized;
return wlr_xdg_surface_schedule_configure(surface);
}
@ -1557,7 +1586,7 @@ uint32_t wlr_xdg_toplevel_set_maximized(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_fullscreen(struct wlr_xdg_surface *surface,
bool fullscreen) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
surface->toplevel->pending.fullscreen = fullscreen;
surface->toplevel->server_pending.fullscreen = fullscreen;
return wlr_xdg_surface_schedule_configure(surface);
}
@ -1565,7 +1594,7 @@ uint32_t wlr_xdg_toplevel_set_fullscreen(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_surface *surface,
bool resizing) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
surface->toplevel->pending.resizing = resizing;
surface->toplevel->server_pending.resizing = resizing;
return wlr_xdg_surface_schedule_configure(surface);
}

View file

@ -16,24 +16,11 @@
static const char *wlr_desktop_xdg_toplevel_role = "xdg_toplevel_v6";
static const char *wlr_desktop_xdg_popup_role = "xdg_popup_v6";
struct wlr_xdg_positioner_v6 {
struct wlr_xdg_positioner_v6_resource {
struct wl_resource *resource;
struct wlr_box anchor_rect;
enum zxdg_positioner_v6_anchor anchor;
enum zxdg_positioner_v6_gravity gravity;
enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment;
struct {
int32_t width, height;
} size;
struct {
int32_t x, y;
} offset;
struct wlr_xdg_positioner_v6 attrs;
};
static void resource_handle_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
@ -110,8 +97,8 @@ static void xdg_keyboard_grab_enter(struct wlr_seat_keyboard_grab *grab,
// keyboard focus should remain on the popup
}
static void xdg_keyboard_grab_key(struct wlr_seat_keyboard_grab *grab, uint32_t time,
uint32_t key, uint32_t state) {
static void xdg_keyboard_grab_key(struct wlr_seat_keyboard_grab *grab,
uint32_t time, uint32_t key, uint32_t state) {
wlr_seat_keyboard_send_key(grab->seat, time, key, state);
}
@ -198,16 +185,15 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
wlr_signal_emit_safe(&surface->events.unmap, surface);
}
if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
wl_resource_set_user_data(surface->toplevel->resource, NULL);
free(surface->toplevel);
surface->toplevel = NULL;
}
if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
wl_resource_set_user_data(surface->popup->resource, NULL);
if (surface->popup->seat) {
switch (surface->role) {
case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL:
free(surface->toplevel->title);
surface->toplevel->title = NULL;
free(surface->toplevel->app_id);
surface->toplevel->app_id = NULL;
break;
case WLR_XDG_SURFACE_V6_ROLE_POPUP:
if (surface->popup->seat != NULL) {
struct wlr_xdg_popup_grab_v6 *grab =
xdg_shell_popup_grab_from_seat(surface->client->shell,
surface->popup->seat);
@ -222,11 +208,12 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
wlr_seat_keyboard_end_grab(grab->seat);
}
}
}
wl_list_remove(&surface->popup->link);
free(surface->popup);
surface->popup = NULL;
surface->popup->seat = NULL;
}
break;
case WLR_XDG_SURFACE_V6_ROLE_NONE:
assert(false && "not reached");
}
struct wlr_xdg_surface_v6_configure *configure, *tmp;
@ -234,13 +221,7 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
xdg_surface_configure_destroy(configure);
}
surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE;
free(surface->title);
surface->title = NULL;
free(surface->app_id);
surface->app_id = NULL;
surface->added = surface->configured = surface->mapped = false;
surface->configured = surface->mapped = false;
surface->configure_serial = 0;
if (surface->configure_idle) {
wl_event_source_remove(surface->configure_idle);
@ -253,6 +234,29 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
}
static void xdg_toplevel_destroy(struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
xdg_surface_unmap(surface);
wl_resource_set_user_data(surface->toplevel->resource, NULL);
free(surface->toplevel);
surface->toplevel = NULL;
surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE;
}
static void xdg_popup_destroy(struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP);
xdg_surface_unmap(surface);
wl_resource_set_user_data(surface->popup->resource, NULL);
wl_list_remove(&surface->popup->link);
free(surface->popup);
surface->popup = NULL;
surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE;
}
static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
if (surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE) {
xdg_surface_unmap(surface);
@ -260,6 +264,18 @@ static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
wlr_signal_emit_safe(&surface->events.destroy, surface);
switch (surface->role) {
case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL:
xdg_toplevel_destroy(surface);
break;
case WLR_XDG_SURFACE_V6_ROLE_POPUP:
xdg_popup_destroy(surface);
break;
case WLR_XDG_SURFACE_V6_ROLE_NONE:
// This space is intentionally left blank
break;
}
wl_resource_set_user_data(surface->resource, NULL);
wl_list_remove(&surface->link);
wl_list_remove(&surface->surface_destroy_listener.link);
@ -271,7 +287,7 @@ static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
static const struct zxdg_positioner_v6_interface
zxdg_positioner_v6_implementation;
static struct wlr_xdg_positioner_v6 *xdg_positioner_from_resource(
static struct wlr_xdg_positioner_v6_resource *xdg_positioner_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zxdg_positioner_v6_interface,
&zxdg_positioner_v6_implementation));
@ -279,14 +295,14 @@ static struct wlr_xdg_positioner_v6 *xdg_positioner_from_resource(
}
static void xdg_positioner_destroy(struct wl_resource *resource) {
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(resource);
free(positioner);
}
static void xdg_positioner_handle_set_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(resource);
if (width < 1 || height < 1) {
@ -296,14 +312,14 @@ static void xdg_positioner_handle_set_size(struct wl_client *client,
return;
}
positioner->size.width = width;
positioner->size.height = height;
positioner->attrs.size.width = width;
positioner->attrs.size.height = height;
}
static void xdg_positioner_handle_set_anchor_rect(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y, int32_t width,
int32_t height) {
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(resource);
if (width < 1 || height < 1) {
@ -313,15 +329,15 @@ static void xdg_positioner_handle_set_anchor_rect(struct wl_client *client,
return;
}
positioner->anchor_rect.x = x;
positioner->anchor_rect.y = y;
positioner->anchor_rect.width = width;
positioner->anchor_rect.height = height;
positioner->attrs.anchor_rect.x = x;
positioner->attrs.anchor_rect.y = y;
positioner->attrs.anchor_rect.width = width;
positioner->attrs.anchor_rect.height = height;
}
static void xdg_positioner_handle_set_anchor(struct wl_client *client,
struct wl_resource *resource, uint32_t anchor) {
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(resource);
if (((anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP ) &&
@ -334,12 +350,12 @@ static void xdg_positioner_handle_set_anchor(struct wl_client *client,
return;
}
positioner->anchor = anchor;
positioner->attrs.anchor = anchor;
}
static void xdg_positioner_handle_set_gravity(struct wl_client *client,
struct wl_resource *resource, uint32_t gravity) {
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(resource);
if (((gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP) &&
@ -352,25 +368,25 @@ static void xdg_positioner_handle_set_gravity(struct wl_client *client,
return;
}
positioner->gravity = gravity;
positioner->attrs.gravity = gravity;
}
static void xdg_positioner_handle_set_constraint_adjustment(
struct wl_client *client, struct wl_resource *resource,
uint32_t constraint_adjustment) {
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(resource);
positioner->constraint_adjustment = constraint_adjustment;
positioner->attrs.constraint_adjustment = constraint_adjustment;
}
static void xdg_positioner_handle_set_offset(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y) {
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(resource);
positioner->offset.x = x;
positioner->offset.y = y;
positioner->attrs.offset.x = x;
positioner->attrs.offset.y = y;
}
static const struct zxdg_positioner_v6_interface
@ -387,8 +403,8 @@ static const struct zxdg_positioner_v6_interface
static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,
struct wl_resource *resource, uint32_t id) {
struct wlr_xdg_positioner_v6 *positioner =
calloc(1, sizeof(struct wlr_xdg_positioner_v6));
struct wlr_xdg_positioner_v6_resource *positioner =
calloc(1, sizeof(struct wlr_xdg_positioner_v6_resource));
if (positioner == NULL) {
wl_client_post_no_memory(wl_client);
return;
@ -409,9 +425,8 @@ static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,
positioner, xdg_positioner_destroy);
}
static struct wlr_box xdg_positioner_get_geometry(
struct wlr_xdg_positioner_v6 *positioner,
struct wlr_xdg_surface_v6 *surface, struct wlr_xdg_surface_v6 *parent) {
struct wlr_box wlr_xdg_positioner_v6_get_geometry(
struct wlr_xdg_positioner_v6 *positioner) {
struct wlr_box geometry = {
.x = positioner->offset.x,
.y = positioner->offset.y,
@ -464,7 +479,6 @@ static struct wlr_box xdg_positioner_get_geometry(
return geometry;
}
static const struct zxdg_popup_v6_interface zxdg_popup_v6_implementation;
static struct wlr_xdg_surface_v6 *xdg_surface_from_xdg_popup_resource(
@ -545,7 +559,7 @@ static void xdg_popup_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_popup_resource(resource);
if (surface != NULL) {
xdg_surface_unmap(surface);
xdg_popup_destroy(surface);
}
}
@ -566,10 +580,11 @@ static void xdg_surface_handle_get_popup(struct wl_client *client,
xdg_surface_from_resource(resource);
struct wlr_xdg_surface_v6 *parent =
xdg_surface_from_resource(parent_resource);
struct wlr_xdg_positioner_v6 *positioner =
struct wlr_xdg_positioner_v6_resource *positioner =
xdg_positioner_from_resource(positioner_resource);
if (positioner->size.width == 0 || positioner->anchor_rect.width == 0) {
if (positioner->attrs.size.width == 0 ||
positioner->attrs.anchor_rect.width == 0) {
wl_resource_post_error(resource,
ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
"positioner object is not complete");
@ -600,7 +615,12 @@ static void xdg_surface_handle_get_popup(struct wl_client *client,
surface->popup->base = surface;
surface->popup->parent = parent;
surface->popup->geometry =
xdg_positioner_get_geometry(positioner, surface, parent);
wlr_xdg_positioner_v6_get_geometry(&positioner->attrs);
// positioner properties
memcpy(&surface->popup->positioner, &positioner->attrs,
sizeof(struct wlr_xdg_positioner_v6));
wl_list_insert(&parent->popups, &surface->popup->link);
wl_resource_set_implementation(surface->popup->resource,
@ -610,7 +630,6 @@ static void xdg_surface_handle_get_popup(struct wl_client *client,
wlr_signal_emit_safe(&parent->events.new_popup, surface->popup);
}
static const struct zxdg_toplevel_v6_interface zxdg_toplevel_v6_implementation;
static struct wlr_xdg_surface_v6 *xdg_surface_from_xdg_toplevel_resource(
@ -643,8 +662,8 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client,
return;
}
free(surface->title);
surface->title = tmp;
free(surface->toplevel->title);
surface->toplevel->title = tmp;
}
static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
@ -657,8 +676,8 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
return;
}
free(surface->app_id);
surface->app_id = tmp;
free(surface->toplevel->app_id);
surface->toplevel->app_id = tmp;
}
static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
@ -689,7 +708,8 @@ static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
.y = y,
};
wlr_signal_emit_safe(&surface->events.request_show_window_menu, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_show_window_menu,
&event);
}
static void xdg_toplevel_handle_move(struct wl_client *client,
@ -718,7 +738,7 @@ static void xdg_toplevel_handle_move(struct wl_client *client,
.serial = serial,
};
wlr_signal_emit_safe(&surface->events.request_move, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_move, &event);
}
static void xdg_toplevel_handle_resize(struct wl_client *client,
@ -748,39 +768,39 @@ static void xdg_toplevel_handle_resize(struct wl_client *client,
.edges = edges,
};
wlr_signal_emit_safe(&surface->events.request_resize, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_resize, &event);
}
static void xdg_toplevel_handle_set_max_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.max_width = width;
surface->toplevel->next.max_height = height;
surface->toplevel->client_pending.max_width = width;
surface->toplevel->client_pending.max_height = height;
}
static void xdg_toplevel_handle_set_min_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.min_width = width;
surface->toplevel->next.min_height = height;
surface->toplevel->client_pending.min_width = width;
surface->toplevel->client_pending.min_height = height;
}
static void xdg_toplevel_handle_set_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.maximized = true;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
surface->toplevel->client_pending.maximized = true;
wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
}
static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.maximized = false;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
surface->toplevel->client_pending.maximized = false;
wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
}
static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
@ -793,7 +813,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
output = wlr_output_from_resource(output_resource);
}
surface->toplevel->next.fullscreen = true;
surface->toplevel->client_pending.fullscreen = true;
struct wlr_xdg_toplevel_v6_set_fullscreen_event event = {
.surface = surface,
@ -801,7 +821,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
.output = output,
};
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event);
}
static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
@ -809,7 +829,7 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
surface->toplevel->next.fullscreen = false;
surface->toplevel->client_pending.fullscreen = false;
struct wlr_xdg_toplevel_v6_set_fullscreen_event event = {
.surface = surface,
@ -817,14 +837,14 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
.output = NULL,
};
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event);
}
static void xdg_toplevel_handle_set_minimized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
wlr_signal_emit_safe(&surface->events.request_minimize, surface);
wlr_signal_emit_safe(&surface->toplevel->events.request_minimize, surface);
}
static const struct zxdg_toplevel_v6_interface
@ -856,7 +876,7 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
if (surface != NULL) {
xdg_surface_unmap(surface);
xdg_toplevel_destroy(surface);
}
}
@ -874,6 +894,12 @@ static void xdg_surface_handle_get_toplevel(struct wl_client *client,
wl_resource_post_no_memory(resource);
return;
}
wl_signal_init(&surface->toplevel->events.request_maximize);
wl_signal_init(&surface->toplevel->events.request_fullscreen);
wl_signal_init(&surface->toplevel->events.request_minimize);
wl_signal_init(&surface->toplevel->events.request_move);
wl_signal_init(&surface->toplevel->events.request_resize);
wl_signal_init(&surface->toplevel->events.request_show_window_menu);
surface->role = WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL;
surface->toplevel->base = surface;
@ -1021,25 +1047,25 @@ static bool wlr_xdg_surface_v6_toplevel_state_compare(
configured.height = configure->toplevel_state->height;
}
if (state->pending.activated != configured.state.activated) {
if (state->server_pending.activated != configured.state.activated) {
return false;
}
if (state->pending.fullscreen != configured.state.fullscreen) {
if (state->server_pending.fullscreen != configured.state.fullscreen) {
return false;
}
if (state->pending.maximized != configured.state.maximized) {
if (state->server_pending.maximized != configured.state.maximized) {
return false;
}
if (state->pending.resizing != configured.state.resizing) {
if (state->server_pending.resizing != configured.state.resizing) {
return false;
}
if (state->pending.width == configured.width &&
state->pending.height == configured.height) {
if (state->server_pending.width == configured.width &&
state->server_pending.height == configured.height) {
return true;
}
if (state->pending.width == 0 && state->pending.height == 0) {
if (state->server_pending.width == 0 && state->server_pending.height == 0) {
return true;
}
@ -1057,46 +1083,50 @@ static void wlr_xdg_toplevel_v6_send_configure(
wl_resource_post_no_memory(surface->toplevel->resource);
return;
}
*configure->toplevel_state = surface->toplevel->pending;
*configure->toplevel_state = surface->toplevel->server_pending;
uint32_t *s;
struct wl_array states;
wl_array_init(&states);
if (surface->toplevel->pending.maximized) {
if (surface->toplevel->server_pending.maximized) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for maximized xdg_toplevel");
wlr_log(L_ERROR,
"Could not allocate state for maximized xdg_toplevel");
goto error_out;
}
*s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
}
if (surface->toplevel->pending.fullscreen) {
if (surface->toplevel->server_pending.fullscreen) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for fullscreen xdg_toplevel");
wlr_log(L_ERROR,
"Could not allocate state for fullscreen xdg_toplevel");
goto error_out;
}
*s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
}
if (surface->toplevel->pending.resizing) {
if (surface->toplevel->server_pending.resizing) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for resizing xdg_toplevel");
wlr_log(L_ERROR,
"Could not allocate state for resizing xdg_toplevel");
goto error_out;
}
*s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
}
if (surface->toplevel->pending.activated) {
if (surface->toplevel->server_pending.activated) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for activated xdg_toplevel");
wlr_log(L_ERROR,
"Could not allocate state for activated xdg_toplevel");
goto error_out;
}
*s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
}
uint32_t width = surface->toplevel->pending.width;
uint32_t height = surface->toplevel->pending.height;
uint32_t width = surface->toplevel->server_pending.width;
uint32_t height = surface->toplevel->server_pending.height;
zxdg_toplevel_v6_send_configure(surface->toplevel->resource, width,
height, &states);
@ -1204,13 +1234,13 @@ static void wlr_xdg_surface_v6_toplevel_committed(
// update state that doesn't need compositor approval
surface->toplevel->current.max_width =
surface->toplevel->next.max_width;
surface->toplevel->client_pending.max_width;
surface->toplevel->current.min_width =
surface->toplevel->next.min_width;
surface->toplevel->client_pending.min_width;
surface->toplevel->current.max_height =
surface->toplevel->next.max_height;
surface->toplevel->client_pending.max_height;
surface->toplevel->current.min_height =
surface->toplevel->next.min_height;
surface->toplevel->client_pending.min_height;
}
static void wlr_xdg_surface_v6_popup_committed(
@ -1318,12 +1348,6 @@ static void xdg_shell_handle_get_xdg_surface(struct wl_client *wl_client,
wl_list_init(&surface->configure_list);
wl_list_init(&surface->popups);
wl_signal_init(&surface->events.request_maximize);
wl_signal_init(&surface->events.request_fullscreen);
wl_signal_init(&surface->events.request_minimize);
wl_signal_init(&surface->events.request_move);
wl_signal_init(&surface->events.request_resize);
wl_signal_init(&surface->events.request_show_window_menu);
wl_signal_init(&surface->events.destroy);
wl_signal_init(&surface->events.ping_timeout);
wl_signal_init(&surface->events.new_popup);
@ -1501,8 +1525,8 @@ void wlr_xdg_surface_v6_ping(struct wlr_xdg_surface_v6 *surface) {
uint32_t wlr_xdg_toplevel_v6_set_size(struct wlr_xdg_surface_v6 *surface,
uint32_t width, uint32_t height) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
surface->toplevel->pending.width = width;
surface->toplevel->pending.height = height;
surface->toplevel->server_pending.width = width;
surface->toplevel->server_pending.height = height;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@ -1510,7 +1534,7 @@ uint32_t wlr_xdg_toplevel_v6_set_size(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_activated(struct wlr_xdg_surface_v6 *surface,
bool activated) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
surface->toplevel->pending.activated = activated;
surface->toplevel->server_pending.activated = activated;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@ -1518,7 +1542,7 @@ uint32_t wlr_xdg_toplevel_v6_set_activated(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_maximized(struct wlr_xdg_surface_v6 *surface,
bool maximized) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
surface->toplevel->pending.maximized = maximized;
surface->toplevel->server_pending.maximized = maximized;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@ -1526,7 +1550,7 @@ uint32_t wlr_xdg_toplevel_v6_set_maximized(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_fullscreen(struct wlr_xdg_surface_v6 *surface,
bool fullscreen) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
surface->toplevel->pending.fullscreen = fullscreen;
surface->toplevel->server_pending.fullscreen = fullscreen;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@ -1534,7 +1558,7 @@ uint32_t wlr_xdg_toplevel_v6_set_fullscreen(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_resizing(struct wlr_xdg_surface_v6 *surface,
bool resizing) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
surface->toplevel->pending.resizing = resizing;
surface->toplevel->server_pending.resizing = resizing;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@ -1609,3 +1633,264 @@ struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at(
return NULL;
}
void wlr_xdg_popup_v6_get_anchor_point(struct wlr_xdg_popup_v6 *popup,
int *root_sx, int *root_sy) {
struct wlr_box rect = popup->positioner.anchor_rect;
enum zxdg_positioner_v6_anchor anchor = popup->positioner.anchor;
int sx = 0, sy = 0;
if (anchor == ZXDG_POSITIONER_V6_ANCHOR_NONE) {
sx = (rect.x + rect.width) / 2;
sy = (rect.y + rect.height) / 2;
} else if (anchor == ZXDG_POSITIONER_V6_ANCHOR_TOP) {
sx = (rect.x + rect.width) / 2;
sy = rect.y;
} else if (anchor == ZXDG_POSITIONER_V6_ANCHOR_BOTTOM) {
sx = (rect.x + rect.width) / 2;
sy = rect.y + rect.height;
} else if (anchor == ZXDG_POSITIONER_V6_ANCHOR_LEFT) {
sx = rect.x;
sy = (rect.y + rect.height) / 2;
} else if (anchor == ZXDG_POSITIONER_V6_ANCHOR_RIGHT) {
sx = rect.x + rect.width;
sy = (rect.y + rect.height) / 2;
} else if (anchor == (ZXDG_POSITIONER_V6_ANCHOR_TOP |
ZXDG_POSITIONER_V6_ANCHOR_LEFT)) {
sx = rect.x;
sy = rect.y;
} else if (anchor == (ZXDG_POSITIONER_V6_ANCHOR_TOP |
ZXDG_POSITIONER_V6_ANCHOR_RIGHT)) {
sx = rect.x + rect.width;
sy = rect.y;
} else if (anchor == (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
ZXDG_POSITIONER_V6_ANCHOR_LEFT)) {
sx = rect.x;
sy = rect.y + rect.height;
} else if (anchor == (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
ZXDG_POSITIONER_V6_ANCHOR_RIGHT)) {
sx = rect.x + rect.width;
sy = rect.y + rect.height;
}
*root_sx = sx;
*root_sy = sy;
}
void wlr_xdg_popup_v6_get_toplevel_coords(struct wlr_xdg_popup_v6 *popup,
int popup_sx, int popup_sy, int *toplevel_sx, int *toplevel_sy) {
struct wlr_xdg_surface_v6 *parent = popup->parent;
while (parent != NULL && parent->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
popup_sx += parent->popup->geometry.x;
popup_sy += parent->popup->geometry.y;
parent = parent->popup->parent;
}
assert(parent);
*toplevel_sx = popup_sx + parent->geometry.x;
*toplevel_sy = popup_sy + parent->geometry.y;
}
static void wlr_xdg_popup_v6_box_constraints(struct wlr_xdg_popup_v6 *popup,
struct wlr_box *toplevel_sx_box, int *offset_x, int *offset_y) {
int popup_width = popup->geometry.width;
int popup_height = popup->geometry.height;
int anchor_sx = 0, anchor_sy = 0;
wlr_xdg_popup_v6_get_anchor_point(popup, &anchor_sx, &anchor_sy);
int popup_sx = 0, popup_sy = 0;
wlr_xdg_popup_v6_get_toplevel_coords(popup, popup->geometry.x,
popup->geometry.y, &popup_sx, &popup_sy);
*offset_x = 0, *offset_y = 0;
if (popup_sx < toplevel_sx_box->x) {
*offset_x = toplevel_sx_box->x - popup_sx;
} else if (popup_sx + popup_width >
toplevel_sx_box->x + toplevel_sx_box->width) {
*offset_x = toplevel_sx_box->x + toplevel_sx_box->width -
(popup_sx + popup_width);
}
if (popup_sy < toplevel_sx_box->y) {
*offset_y = toplevel_sx_box->y - popup_sy;
} else if (popup_sy + popup_height >
toplevel_sx_box->y + toplevel_sx_box->height) {
*offset_y = toplevel_sx_box->y + toplevel_sx_box->height -
(popup_sy + popup_height);
}
}
static bool wlr_xdg_popup_v6_unconstrain_flip(struct wlr_xdg_popup_v6 *popup,
struct wlr_box *toplevel_sx_box) {
int offset_x = 0, offset_y = 0;
wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box,
&offset_x, &offset_y);
if (!offset_x && !offset_y) {
return true;
}
bool flip_x = offset_x &&
(popup->positioner.constraint_adjustment &
ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X);
bool flip_y = offset_y &&
(popup->positioner.constraint_adjustment &
ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y);
if (flip_x) {
wlr_positioner_v6_invert_x(&popup->positioner);
}
if (flip_y) {
wlr_positioner_v6_invert_y(&popup->positioner);
}
popup->geometry =
wlr_xdg_positioner_v6_get_geometry(&popup->positioner);
wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box,
&offset_x, &offset_y);
if (!offset_x && !offset_y) {
// no longer constrained
return true;
}
// revert the positioner back if it didn't fix it and go to the next part
if (flip_x) {
wlr_positioner_v6_invert_x(&popup->positioner);
}
if (flip_y) {
wlr_positioner_v6_invert_y(&popup->positioner);
}
popup->geometry =
wlr_xdg_positioner_v6_get_geometry(&popup->positioner);
return false;
}
static bool wlr_xdg_popup_v6_unconstrain_slide(struct wlr_xdg_popup_v6 *popup,
struct wlr_box *toplevel_sx_box) {
int offset_x = 0, offset_y = 0;
wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box,
&offset_x, &offset_y);
if (!offset_x && !offset_y) {
return true;
}
bool slide_x = offset_x &&
(popup->positioner.constraint_adjustment &
ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X);
bool slide_y = offset_x &&
(popup->positioner.constraint_adjustment &
ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
if (slide_x) {
popup->geometry.x += offset_x;
}
if (slide_y) {
popup->geometry.y += offset_y;
}
int toplevel_x = 0, toplevel_y = 0;
wlr_xdg_popup_v6_get_toplevel_coords(popup, popup->geometry.x,
popup->geometry.y, &toplevel_x, &toplevel_y);
if (slide_x && toplevel_x < toplevel_sx_box->x) {
popup->geometry.x += toplevel_sx_box->x - toplevel_x;
}
if (slide_y && toplevel_y < toplevel_sx_box->y) {
popup->geometry.y += toplevel_sx_box->y - toplevel_y;
}
wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box,
&offset_x, &offset_y);
return !offset_x && !offset_y;
}
static bool wlr_xdg_popup_v6_unconstrain_resize(struct wlr_xdg_popup_v6 *popup,
struct wlr_box *toplevel_sx_box) {
int offset_x, offset_y;
wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box,
&offset_x, &offset_y);
if (!offset_x && !offset_y) {
return true;
}
bool resize_x = offset_x &&
(popup->positioner.constraint_adjustment &
ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X);
bool resize_y = offset_x &&
(popup->positioner.constraint_adjustment &
ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y);
if (resize_x) {
popup->geometry.width -= offset_x;
}
if (resize_y) {
popup->geometry.height -= offset_y;
}
wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box,
&offset_y, &offset_y);
return !offset_x && !offset_y;
}
void wlr_xdg_popup_v6_unconstrain_from_box(struct wlr_xdg_popup_v6 *popup,
struct wlr_box *toplevel_sx_box) {
if (wlr_xdg_popup_v6_unconstrain_flip(popup, toplevel_sx_box)) {
return;
}
if (wlr_xdg_popup_v6_unconstrain_slide(popup, toplevel_sx_box)) {
return;
}
if (wlr_xdg_popup_v6_unconstrain_resize(popup, toplevel_sx_box)) {
return;
}
}
void wlr_positioner_v6_invert_x(struct wlr_xdg_positioner_v6 *positioner) {
if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT) {
positioner->anchor &= ~ZXDG_POSITIONER_V6_ANCHOR_LEFT;
positioner->anchor |= ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
} else if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT) {
positioner->anchor &= ~ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
positioner->anchor |= ZXDG_POSITIONER_V6_ANCHOR_LEFT;
}
if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT) {
positioner->gravity &= ~ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
positioner->gravity |= ZXDG_POSITIONER_V6_GRAVITY_LEFT;
} else if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT) {
positioner->gravity &= ~ZXDG_POSITIONER_V6_GRAVITY_LEFT;
positioner->gravity |= ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
}
}
void wlr_positioner_v6_invert_y(
struct wlr_xdg_positioner_v6 *positioner) {
if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP) {
positioner->anchor &= ~ZXDG_POSITIONER_V6_ANCHOR_TOP;
positioner->anchor |= ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
} else if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM) {
positioner->anchor &= ~ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
positioner->anchor |= ZXDG_POSITIONER_V6_ANCHOR_TOP;
}
if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP) {
positioner->gravity &= ~ZXDG_POSITIONER_V6_GRAVITY_TOP;
positioner->gravity |= ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
} else if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM) {
positioner->gravity &= ~ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
positioner->gravity |= ZXDG_POSITIONER_V6_GRAVITY_TOP;
}
}