summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <mdaenzer@redhat.com>2022-11-01 17:30:00 +0100
committerMichel Dänzer <michel@daenzer.net>2022-12-01 12:41:32 +0100
commitb7599fb766832d0ed14b91414672ecf15582198a (patch)
tree1e8ae70ecdc9d1a6215449e1e7c8622887c6c26d
parent6c3879766decb27c1e1f09845daff0a307494ed0 (diff)
downloadmutter-b7599fb766832d0ed14b91414672ecf15582198a.tar.gz
wayland/xdg-shell: Defer meta_wayland_xdg_positioner_to_placement call
From xdg_surface_constructor_get_popup / xdg_popup_reposition (called during Wayland protocol processing) to finish_popup_setup / meta_wayland_xdg_popup_apply_state (called when the popup state is applied). This makes sure that the parent window frame rectangle is up to date in meta_wayland_xdg_positioner_to_placement. v2: * Use meta_wayland_surface_state_new () in meta_wayland_transaction_add_xdg_popup_reposition. v3: * Move xdg_popup_repositioned handling to meta_wayland_xdg_popup_apply_state. v4: * Do not steal pending->xdg_positioner in meta_wayland_xdg_popup_apply_state, fixes leaking the corresponding memory. * Drop MetaWaylandSurfaceState::xdg_popup_repositioned, just use ::xdg_positioner. v5: * Reformat meta_wayland_xdg_positioner_to_placement calls to stay within 80 columns. (Jonas Ådahl) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
-rw-r--r--src/wayland/meta-wayland-surface.c10
-rw-r--r--src/wayland/meta-wayland-surface.h4
-rw-r--r--src/wayland/meta-wayland-transaction.c21
-rw-r--r--src/wayland/meta-wayland-transaction.h5
-rw-r--r--src/wayland/meta-wayland-types.h2
-rw-r--r--src/wayland/meta-wayland-xdg-shell.c66
6 files changed, 80 insertions, 28 deletions
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 7beb0ab60..c235ead1c 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -502,6 +502,8 @@ meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state)
state->subsurface_placement_ops = NULL;
wl_list_init (&state->presentation_feedback_list);
+
+ state->xdg_popup_reposition_token = 0;
}
static void
@@ -527,6 +529,7 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state)
g_clear_pointer (&state->buffer_damage, cairo_region_destroy);
g_clear_pointer (&state->input_region, cairo_region_destroy);
g_clear_pointer (&state->opaque_region, cairo_region_destroy);
+ g_clear_pointer (&state->xdg_positioner, g_free);
if (state->buffer)
g_clear_signal_handler (&state->buffer_destroy_handler_id, state->buffer);
@@ -675,6 +678,13 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from,
wl_list_insert_list (&to->presentation_feedback_list,
&from->presentation_feedback_list);
wl_list_init (&from->presentation_feedback_list);
+
+ if (from->xdg_positioner)
+ {
+ g_clear_pointer (&to->xdg_positioner, g_free);
+ to->xdg_positioner = g_steal_pointer (&from->xdg_positioner);
+ to->xdg_popup_reposition_token = from->xdg_popup_reposition_token;
+ }
}
static void
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 307038a2c..7edddf647 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -133,6 +133,10 @@ struct _MetaWaylandSurfaceState
struct {
gboolean surface_size_changed;
} derived;
+
+ /* xdg_popup */
+ MetaWaylandXdgPositioner *xdg_positioner;
+ uint32_t xdg_popup_reposition_token;
};
struct _MetaWaylandDragDestFuncs
diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c
index cc77ea663..6bf0376e9 100644
--- a/src/wayland/meta-wayland-transaction.c
+++ b/src/wayland/meta-wayland-transaction.c
@@ -386,6 +386,27 @@ meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *transa
entry->has_sub_pos = TRUE;
}
+void
+meta_wayland_transaction_add_xdg_popup_reposition (MetaWaylandTransaction *transaction,
+ MetaWaylandSurface *surface,
+ void *xdg_positioner,
+ uint32_t token)
+{
+ MetaWaylandTransactionEntry *entry;
+ MetaWaylandSurfaceState *state;
+
+ entry = meta_wayland_transaction_ensure_entry (transaction, surface);
+
+ if (entry->state)
+ g_clear_pointer (&entry->state->xdg_positioner, g_free);
+ else
+ entry->state = meta_wayland_surface_state_new ();
+
+ state = entry->state;
+ state->xdg_positioner = xdg_positioner;
+ state->xdg_popup_reposition_token = token;
+}
+
static void
meta_wayland_transaction_entry_merge_into (MetaWaylandTransactionEntry *from,
MetaWaylandTransactionEntry *to)
diff --git a/src/wayland/meta-wayland-transaction.h b/src/wayland/meta-wayland-transaction.h
index a42300f8e..98c662001 100644
--- a/src/wayland/meta-wayland-transaction.h
+++ b/src/wayland/meta-wayland-transaction.h
@@ -37,6 +37,11 @@ void meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *t
int x,
int y);
+void meta_wayland_transaction_add_xdg_popup_reposition (MetaWaylandTransaction *transaction,
+ MetaWaylandSurface *surface,
+ void *xdg_positioner,
+ uint32_t token);
+
void meta_wayland_transaction_merge_into (MetaWaylandTransaction *from,
MetaWaylandTransaction *to);
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index 97623df7f..8b1c6f007 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -67,6 +67,8 @@ typedef struct _MetaWaylandActivation MetaWaylandActivation;
typedef struct _MetaWaylandDmaBufManager MetaWaylandDmaBufManager;
+typedef struct _MetaWaylandXdgPositioner MetaWaylandXdgPositioner;
+
typedef struct _MetaXWaylandManager MetaXWaylandManager;
#endif
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
index 1c2877d3c..240648222 100644
--- a/src/wayland/meta-wayland-xdg-shell.c
+++ b/src/wayland/meta-wayland-xdg-shell.c
@@ -57,7 +57,7 @@ typedef struct _MetaWaylandXdgShellClient
GList *surface_constructors;
} MetaWaylandXdgShellClient;
-typedef struct _MetaWaylandXdgPositioner
+struct _MetaWaylandXdgPositioner
{
MetaRectangle anchor_rect;
int32_t width;
@@ -76,7 +76,7 @@ typedef struct _MetaWaylandXdgPositioner
gboolean acked_parent_configure;
uint32_t parent_configure_serial;
-} MetaWaylandXdgPositioner;
+};
typedef struct _MetaWaylandXdgSurfaceConstructor
{
@@ -130,11 +130,7 @@ struct _MetaWaylandXdgPopup
struct {
MetaWaylandSurface *parent_surface;
- /*
- * The coordinates/dimensions in the placement rule are in logical pixel
- * coordinate space, i.e. not scaled given what monitor the popup is on.
- */
- MetaPlacementRule placement_rule;
+ MetaWaylandXdgPositioner xdg_positioner;
MetaWaylandSeat *grab_seat;
uint32_t grab_serial;
@@ -623,27 +619,17 @@ xdg_popup_reposition (struct wl_client *client,
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);
+ MetaWaylandTransaction *transaction;
- xdg_popup->pending_reposition_token = token;
- xdg_popup->pending_repositioned = TRUE;
+ xdg_positioner = g_memdup2 (wl_resource_get_user_data (positioner_resource),
+ sizeof (MetaWaylandXdgPositioner));
- scale_placement_rule (&placement_rule, surface);
-
- meta_window_update_placement_rule (window, &placement_rule);
+ transaction = meta_wayland_transaction_new (surface->compositor);
+ meta_wayland_transaction_add_xdg_popup_reposition (transaction, surface,
+ xdg_positioner, token);
+ meta_wayland_transaction_ensure_entry (transaction, xdg_popup->parent_surface);
+ meta_wayland_transaction_commit (transaction);
}
static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
@@ -1080,6 +1066,8 @@ finish_popup_setup (MetaWaylandXdgPopup *xdg_popup)
uint32_t serial;
MetaDisplay *display = meta_get_display ();
MetaWindow *window;
+ MetaWindow *parent_window;
+ MetaPlacementRule placement_rule;
parent_surface = xdg_popup->setup.parent_surface;
seat = xdg_popup->setup.grab_seat;
@@ -1124,7 +1112,11 @@ finish_popup_setup (MetaWaylandXdgPopup *xdg_popup)
window = meta_window_wayland_new (display, surface);
meta_wayland_shell_surface_set_window (shell_surface, window);
- meta_wayland_xdg_popup_place (xdg_popup, &xdg_popup->setup.placement_rule);
+ parent_window = meta_wayland_surface_get_window (parent_surface);
+ placement_rule =
+ meta_wayland_xdg_positioner_to_placement (&xdg_popup->setup.xdg_positioner,
+ parent_window);
+ meta_wayland_xdg_popup_place (xdg_popup, &placement_rule);
if (seat)
{
@@ -1219,6 +1211,25 @@ meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role,
if (xdg_popup->setup.parent_surface)
finish_popup_setup (xdg_popup);
+ if (pending->xdg_positioner)
+ {
+ MetaWindow *window, *parent_window;
+ MetaPlacementRule placement_rule;
+
+ parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface);
+ placement_rule =
+ meta_wayland_xdg_positioner_to_placement (pending->xdg_positioner,
+ parent_window);
+
+ xdg_popup->pending_reposition_token = pending->xdg_popup_reposition_token;
+ xdg_popup->pending_repositioned = TRUE;
+
+ scale_placement_rule (&placement_rule, surface);
+
+ window = meta_wayland_surface_get_window (surface);
+ meta_window_update_placement_rule (window, &placement_rule);
+ }
+
if (!surface->buffer_ref->buffer && xdg_surface_priv->first_buffer_attached)
{
meta_wayland_xdg_surface_reset (xdg_surface);
@@ -2040,8 +2051,7 @@ xdg_surface_constructor_get_popup (struct wl_client *client,
meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface);
xdg_positioner = wl_resource_get_user_data (positioner_resource);
- xdg_popup->setup.placement_rule =
- meta_wayland_xdg_positioner_to_placement (xdg_positioner, parent_window);
+ xdg_popup->setup.xdg_positioner = *xdg_positioner;
xdg_popup->setup.parent_surface = parent_surface;
}