mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-11-16 06:59:44 -05:00
Merge branch 'master' into xwayland-dnd
This commit is contained in:
commit
8836b4f024
80 changed files with 3987 additions and 1491 deletions
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
427
types/wlr_layer_shell.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue