[mutter] wayland/xdg-shell: Add support for explicit popup repositioning
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] wayland/xdg-shell: Add support for explicit popup repositioning
- Date: Sat, 29 Feb 2020 21:09:18 +0000 (UTC)
commit f97804f4f469753806a51dec02ca9042a515609d
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Fri Feb 14 11:13:24 2020 +0100
wayland/xdg-shell: Add support for explicit popup repositioning
This commit completes the implementation of `xdg_wm_base` version 3,
which introduces support for synchronized implicit and explicit popup
repositioning.
Explicit repositioning works by the client providing a new
`xdg_positioner` object via a new request `xdg_popup.reposition`. If the
repositioning is done in combination with the parent itself being
reconfigured, the to be committed state of the parent is provided by the
client via the `xdg_positioner` object, using
`xdg_positioner.set__parent_configure`.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/705
src/wayland/meta-wayland-versions.h | 2 +-
src/wayland/meta-wayland-xdg-shell.c | 126 +++++++++++++++++++++++++++++++++++
src/wayland/meta-window-wayland.c | 17 +++++
src/wayland/meta-window-wayland.h | 4 ++
4 files changed, 148 insertions(+), 1 deletion(-)
---
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index f5dc10484..2d6ce5ace 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -37,7 +37,7 @@
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
#define META_WL_COMPOSITOR_VERSION 4
#define META_WL_DATA_DEVICE_MANAGER_VERSION 3
-#define META_XDG_WM_BASE_VERSION 2
+#define META_XDG_WM_BASE_VERSION 3
#define META_ZXDG_SHELL_V6_VERSION 1
#define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 5
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
index 3aad9fe5b..fefed4596 100644
--- a/src/wayland/meta-wayland-xdg-shell.c
+++ b/src/wayland/meta-wayland-xdg-shell.c
@@ -68,6 +68,13 @@ typedef struct _MetaWaylandXdgPositioner
int32_t offset_y;
gboolean is_reactive;
+
+ gboolean has_parent_size;
+ int32_t parent_width;
+ int32_t parent_height;
+
+ gboolean acked_parent_configure;
+ uint32_t parent_configure_serial;
} MetaWaylandXdgPositioner;
typedef struct _MetaWaylandXdgSurfaceConstructor
@@ -112,6 +119,9 @@ struct _MetaWaylandXdgPopup
MetaWaylandSurface *parent_surface;
gulong parent_surface_unmapped_handler_id;
+ uint32_t pending_reposition_token;
+ gboolean pending_repositioned;
+
MetaWaylandPopup *popup;
gboolean dismissed_by_client;
@@ -153,6 +163,10 @@ static void
meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface,
MetaWaylandWindowConfiguration *configuration);
+static void
+scale_placement_rule (MetaPlacementRule *placement_rule,
+ MetaWaylandSurface *surface);
+
static MetaWaylandSurface *
surface_from_xdg_surface_resource (struct wl_resource *resource)
{
@@ -566,9 +580,45 @@ xdg_popup_grab (struct wl_client *client,
xdg_popup->setup.grab_serial = serial;
}
+static void
+xdg_popup_reposition (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *positioner_resource,
+ uint32_t token)
+{
+ MetaWaylandXdgPopup *xdg_popup =
+ META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource));
+ MetaWaylandSurfaceRole *surface_role =
+ META_WAYLAND_SURFACE_ROLE (xdg_popup);
+ MetaWaylandSurface *surface =
+ meta_wayland_surface_role_get_surface (surface_role);
+ MetaWindow *window;
+ MetaWindow *parent_window;
+ MetaWaylandXdgPositioner *xdg_positioner;
+ MetaPlacementRule placement_rule;
+
+ window = meta_wayland_surface_get_window (surface);
+ if (!window)
+ return;
+
+ parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface);
+
+ xdg_positioner = wl_resource_get_user_data (positioner_resource);
+ placement_rule = meta_wayland_xdg_positioner_to_placement (xdg_positioner,
+ parent_window);
+
+ xdg_popup->pending_reposition_token = token;
+ xdg_popup->pending_repositioned = TRUE;
+
+ scale_placement_rule (&placement_rule, surface);
+
+ meta_window_update_placement_rule (window, &placement_rule);
+}
+
static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
xdg_popup_destroy,
xdg_popup_grab,
+ xdg_popup_reposition,
};
static void
@@ -1150,6 +1200,12 @@ meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface,
geometry_scale = meta_window_wayland_get_geometry_scale (parent_window);
x = configuration->rel_x / geometry_scale;
y = configuration->rel_y / geometry_scale;
+ if (xdg_popup->pending_repositioned)
+ {
+ xdg_popup_send_repositioned (xdg_popup->resource,
+ xdg_popup->pending_reposition_token);
+ xdg_popup->pending_repositioned = FALSE;
+ }
xdg_popup_send_configure (xdg_popup->resource,
x, y,
configuration->width, configuration->height);
@@ -1905,6 +1961,50 @@ meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_position
meta_window_get_frame_rect (parent_window, &parent_rect);
+ if (xdg_positioner->acked_parent_configure)
+ {
+ MetaWindowWayland *parent_wl_window = META_WINDOW_WAYLAND (parent_window);
+ uint32_t serial;
+ MetaWaylandWindowConfiguration *configuration;
+
+ serial = xdg_positioner->parent_configure_serial;
+ configuration = meta_window_wayland_peek_configuration (parent_wl_window,
+ serial);
+
+ if (configuration)
+ {
+ if (configuration->flags & META_MOVE_RESIZE_STATE_CHANGED)
+ {
+ if (configuration->has_position)
+ {
+ parent_rect.x = configuration->x;
+ parent_rect.y = configuration->y;
+ }
+ if (configuration->has_size)
+ {
+ parent_rect.width = configuration->width;
+ parent_rect.height = configuration->height;
+ }
+ }
+ else if (xdg_positioner->has_parent_size)
+ {
+ meta_rectangle_resize_with_gravity (&parent_rect,
+ &parent_rect,
+ configuration->gravity,
+ xdg_positioner->parent_width,
+ xdg_positioner->parent_height);
+ }
+ }
+ }
+ else if (xdg_positioner->has_parent_size)
+ {
+ meta_rectangle_resize_with_gravity (&parent_rect,
+ &parent_rect,
+ META_GRAVITY_SOUTH_EAST,
+ xdg_positioner->parent_width,
+ xdg_positioner->parent_height);
+ }
+
return (MetaPlacementRule) {
.anchor_rect = xdg_positioner->anchor_rect,
.gravity = positioner_gravity_to_placement_gravity (xdg_positioner->gravity),
@@ -2050,6 +2150,30 @@ xdg_positioner_set_reactive (struct wl_client *client,
positioner->is_reactive = TRUE;
}
+static void
+xdg_positioner_set_parent_size (struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t parent_width,
+ int32_t parent_height)
+{
+ MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
+
+ positioner->has_parent_size = TRUE;
+ positioner->parent_width = parent_width;
+ positioner->parent_height = parent_height;
+}
+
+static void
+xdg_positioner_set_parent_configure (struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t serial)
+{
+ MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
+
+ positioner->acked_parent_configure = TRUE;
+ positioner->parent_configure_serial = serial;
+}
+
static const struct xdg_positioner_interface meta_wayland_xdg_positioner_interface = {
xdg_positioner_destroy,
xdg_positioner_set_size,
@@ -2059,6 +2183,8 @@ static const struct xdg_positioner_interface meta_wayland_xdg_positioner_interfa
xdg_positioner_set_constraint_adjustment,
xdg_positioner_set_offset,
xdg_positioner_set_reactive,
+ xdg_positioner_set_parent_size,
+ xdg_positioner_set_parent_configure,
};
static void
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index 80be4b7a3..9864d2fd4 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -800,6 +800,23 @@ meta_window_wayland_new (MetaDisplay *display,
return window;
}
+MetaWaylandWindowConfiguration *
+meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window,
+ uint32_t serial)
+{
+ GList *l;
+
+ for (l = wl_window->pending_configurations; l; l = l->next)
+ {
+ MetaWaylandWindowConfiguration *configuration = l->data;
+
+ if (configuration->serial == serial)
+ return configuration;
+ }
+
+ return NULL;
+}
+
static MetaWaylandWindowConfiguration *
acquire_acked_configuration (MetaWindowWayland *wl_window,
MetaWaylandSurfaceState *pending)
diff --git a/src/wayland/meta-window-wayland.h b/src/wayland/meta-window-wayland.h
index 22824a6ae..db152daaa 100644
--- a/src/wayland/meta-window-wayland.h
+++ b/src/wayland/meta-window-wayland.h
@@ -56,6 +56,10 @@ void meta_window_place_with_placement_rule (MetaWindow *window,
void meta_window_update_placement_rule (MetaWindow *window,
MetaPlacementRule *placement_rule);
+MetaWaylandWindowConfiguration *
+ meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window,
+ uint32_t serial);
+
void meta_window_wayland_set_min_size (MetaWindow *window,
int width,
int height);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]