diff --git a/src/meson.build b/src/meson.build index db63ed317..fca40d8dc 100644 --- a/src/meson.build +++ b/src/meson.build @@ -565,6 +565,8 @@ if have_wayland 'wayland/meta-wayland-versions.h', 'wayland/meta-wayland-viewporter.c', 'wayland/meta-wayland-viewporter.h', + 'wayland/meta-wayland-window-configuration.c', + 'wayland/meta-wayland-window-configuration.h', 'wayland/meta-wayland-wl-shell.c', 'wayland/meta-wayland-wl-shell.h', 'wayland/meta-wayland-xdg-foreign.c', diff --git a/src/wayland/meta-wayland-legacy-xdg-shell.c b/src/wayland/meta-wayland-legacy-xdg-shell.c index 81a71bba0..f55687445 100644 --- a/src/wayland/meta-wayland-legacy-xdg-shell.c +++ b/src/wayland/meta-wayland-legacy-xdg-shell.c @@ -34,6 +34,7 @@ #include "wayland/meta-wayland-shell-surface.h" #include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-versions.h" +#include "wayland/meta-wayland-window-configuration.h" #include "wayland/meta-wayland.h" #include "wayland/meta-window-wayland.h" @@ -77,7 +78,6 @@ typedef struct _MetaWaylandZxdgSurfaceV6Private { struct wl_resource *resource; MetaWaylandZxdgShellV6Client *shell_client; - MetaWaylandSerial acked_configure_serial; MetaRectangle geometry; guint configure_sent : 1; @@ -143,8 +143,9 @@ meta_wayland_zxdg_surface_v6_get_shell_resource (MetaWaylandZxdgSurfaceV6 *xdg_s static MetaRectangle meta_wayland_zxdg_surface_v6_get_window_geometry (MetaWaylandZxdgSurfaceV6 *xdg_surface); -static uint32_t -meta_wayland_zxdg_surface_v6_send_configure (MetaWaylandZxdgSurfaceV6 *xdg_surface); +static void +meta_wayland_zxdg_surface_v6_send_configure (MetaWaylandZxdgSurfaceV6 *xdg_surface, + MetaWaylandWindowConfiguration *configuration); static MetaWaylandSurface * surface_from_xdg_surface_resource (struct wl_resource *resource) @@ -590,10 +591,8 @@ fill_states (struct wl_array *states, } static void -meta_wayland_zxdg_toplevel_v6_send_configure (MetaWaylandZxdgToplevelV6 *xdg_toplevel, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_zxdg_toplevel_v6_send_configure (MetaWaylandZxdgToplevelV6 *xdg_toplevel, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandZxdgSurfaceV6 *xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); @@ -602,23 +601,17 @@ meta_wayland_zxdg_toplevel_v6_send_configure (MetaWaylandZxdgToplevelV6 *xdg_top MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); struct wl_array states; - uint32_t serial; wl_array_init (&states); fill_states (&states, surface->window); zxdg_toplevel_v6_send_configure (xdg_toplevel->resource, - new_width, new_height, + configuration->width, + configuration->height, &states); wl_array_release (&states); - serial = meta_wayland_zxdg_surface_v6_send_configure (xdg_surface); - - if (sent_serial) - { - sent_serial->set = TRUE; - sent_serial->value = serial; - } + meta_wayland_zxdg_surface_v6_send_configure (xdg_surface, configuration); } static gboolean @@ -684,7 +677,12 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role, if (!xdg_surface_priv->configure_sent) { - meta_wayland_zxdg_toplevel_v6_send_configure (xdg_toplevel, 0, 0, NULL); + MetaWaylandWindowConfiguration *configuration; + + configuration = meta_wayland_window_configuration_new_empty (); + meta_wayland_zxdg_toplevel_v6_send_configure (xdg_toplevel, + configuration); + meta_wayland_window_configuration_free (configuration); return; } @@ -697,18 +695,13 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role, geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry); - if (geometry_changed || meta_window_wayland_has_pending_move_resize (window)) + if (geometry_changed || pending->has_acked_configure_serial) { MetaRectangle window_geometry; - MetaWaylandSerial *acked_configure_serial; window_geometry = meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface); - acked_configure_serial = &xdg_surface_priv->acked_configure_serial; - meta_window_wayland_finish_move_resize (window, - acked_configure_serial, - window_geometry, - pending->dx, pending->dy); + meta_window_wayland_finish_move_resize (window, window_geometry, pending); } else if (pending->dx != 0 || pending->dy != 0) { @@ -741,8 +734,6 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role, } } - - xdg_surface_priv->acked_configure_serial.set = FALSE; } static MetaWaylandSurface * @@ -752,12 +743,8 @@ meta_wayland_zxdg_toplevel_v6_get_toplevel (MetaWaylandSurfaceRole *surface_role } static void -meta_wayland_zxdg_toplevel_v6_configure (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_zxdg_toplevel_v6_configure (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandZxdgToplevelV6 *xdg_toplevel = META_WAYLAND_ZXDG_TOPLEVEL_V6 (shell_surface); @@ -772,9 +759,7 @@ meta_wayland_zxdg_toplevel_v6_configure (MetaWaylandShellSurface *shell_surface, if (!xdg_toplevel->resource) return; - meta_wayland_zxdg_toplevel_v6_send_configure (xdg_toplevel, - new_width, new_height, - sent_serial); + meta_wayland_zxdg_toplevel_v6_send_configure (xdg_toplevel, configuration); } static void @@ -979,7 +964,6 @@ meta_wayland_zxdg_popup_v6_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaRectangle window_geometry; if (xdg_popup->setup.parent_surface) finish_popup_setup (xdg_popup); @@ -998,12 +982,16 @@ meta_wayland_zxdg_popup_v6_commit (MetaWaylandSurfaceRole *surface_role, if (!surface->buffer_ref.buffer) return; - window_geometry = - meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface); - meta_window_wayland_finish_move_resize (surface->window, - NULL, - window_geometry, - pending->dx, pending->dy); + if (pending->has_acked_configure_serial) + { + MetaRectangle window_geometry; + + window_geometry = + meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface); + meta_window_wayland_finish_move_resize (surface->window, + window_geometry, + pending); + } } static MetaWaylandSurface * @@ -1018,12 +1006,8 @@ meta_wayland_zxdg_popup_v6_get_toplevel (MetaWaylandSurfaceRole *surface_role) } static void -meta_wayland_zxdg_popup_v6_configure (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_zxdg_popup_v6_configure (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (shell_surface); @@ -1045,11 +1029,13 @@ meta_wayland_zxdg_popup_v6_configure (MetaWaylandShellSurface *shell_surface, return; geometry_scale = meta_window_wayland_get_geometry_scale (parent_window); - x = (new_x - parent_window->rect.x) / geometry_scale; - y = (new_y - parent_window->rect.y) / geometry_scale; + x = (configuration->x - parent_window->rect.x) / geometry_scale; + y = (configuration->y - parent_window->rect.y) / geometry_scale; + zxdg_popup_v6_send_configure (xdg_popup->resource, - x, y, new_width, new_height); - meta_wayland_zxdg_surface_v6_send_configure (xdg_surface); + x, y, + configuration->width, configuration->height); + meta_wayland_zxdg_surface_v6_send_configure (xdg_surface, configuration); } static void @@ -1208,21 +1194,16 @@ meta_wayland_zxdg_surface_v6_is_assigned (MetaWaylandZxdgSurfaceV6 *xdg_surface) return priv->resource != NULL; } -static uint32_t -meta_wayland_zxdg_surface_v6_send_configure (MetaWaylandZxdgSurfaceV6 *xdg_surface) +static void +meta_wayland_zxdg_surface_v6_send_configure (MetaWaylandZxdgSurfaceV6 *xdg_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandZxdgSurfaceV6Private *priv = meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - struct wl_display *display; - uint32_t serial; - display = wl_client_get_display (wl_resource_get_client (priv->resource)); - serial = wl_display_next_serial (display); - zxdg_surface_v6_send_configure (priv->resource, serial); + zxdg_surface_v6_send_configure (priv->resource, configuration->serial); priv->configure_sent = TRUE; - - return serial; } static void @@ -1307,12 +1288,12 @@ zxdg_surface_v6_ack_configure (struct wl_client *client, struct wl_resource *resource, uint32_t serial) { - MetaWaylandZxdgSurfaceV6 *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); + MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); + MetaWaylandSurfaceState *pending; - priv->acked_configure_serial.set = TRUE; - priv->acked_configure_serial.value = serial; + pending = meta_wayland_surface_get_pending_state (surface); + pending->has_acked_configure_serial = TRUE; + pending->acked_configure_serial = serial; } static const struct zxdg_surface_v6_interface meta_wayland_zxdg_surface_v6_interface = { diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c index f0af47c50..825737bc1 100644 --- a/src/wayland/meta-wayland-shell-surface.c +++ b/src/wayland/meta-wayland-shell-surface.c @@ -100,22 +100,13 @@ meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface, } void -meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandShellSurfaceClass *shell_surface_class = META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface); - shell_surface_class->configure (shell_surface, - new_x, - new_y, - new_width, - new_height, - sent_serial); + shell_surface_class->configure (shell_surface, configuration); } void diff --git a/src/wayland/meta-wayland-shell-surface.h b/src/wayland/meta-wayland-shell-surface.h index bfb77d0b4..d1bbeef65 100644 --- a/src/wayland/meta-wayland-shell-surface.h +++ b/src/wayland/meta-wayland-shell-surface.h @@ -33,12 +33,8 @@ struct _MetaWaylandShellSurfaceClass { MetaWaylandActorSurfaceClass parent_class; - void (*configure) (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial); + void (*configure) (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration); void (*managed) (MetaWaylandShellSurface *shell_surface, MetaWindow *window); void (*ping) (MetaWaylandShellSurface *shell_surface, @@ -46,12 +42,8 @@ struct _MetaWaylandShellSurfaceClass void (*close) (MetaWaylandShellSurface *shell_surface); }; -void meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial); +void meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration); void meta_wayland_shell_surface_ping (MetaWaylandShellSurface *shell_surface, uint32_t serial); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 1f4727ece..ee546ae44 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -426,6 +426,7 @@ meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state) wl_list_init (&state->frame_callback_list); state->has_new_geometry = FALSE; + state->has_acked_configure_serial = FALSE; state->has_new_min_size = FALSE; state->has_new_max_size = FALSE; @@ -511,6 +512,12 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, to->has_new_geometry = TRUE; } + if (from->has_acked_configure_serial) + { + to->acked_configure_serial = from->acked_configure_serial; + to->has_acked_configure_serial = TRUE; + } + if (from->has_new_min_size) { to->new_min_width = from->new_min_width; @@ -1501,22 +1508,15 @@ meta_wayland_shell_init (MetaWaylandCompositor *compositor) } void -meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandShellSurface *shell_surface = META_WAYLAND_SHELL_SURFACE (surface->role); g_signal_emit (surface, surface_signals[SURFACE_CONFIGURE], 0); - meta_wayland_shell_surface_configure (shell_surface, - new_x, new_y, - new_width, new_height, - sent_serial); + meta_wayland_shell_surface_configure (shell_surface, configuration); } void diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 41fe47ca4..4486a3046 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -64,11 +64,6 @@ struct _MetaWaylandSurfaceRoleClass gboolean (*should_cache_state) (MetaWaylandSurfaceRole *surface_role); }; -struct _MetaWaylandSerial { - gboolean set; - uint32_t value; -}; - struct _MetaWaylandSurfaceState { GObject parent; @@ -98,6 +93,9 @@ struct _MetaWaylandSurfaceState MetaRectangle new_geometry; gboolean has_new_geometry; + gboolean has_acked_configure_serial; + uint32_t acked_configure_serial; + /* pending min/max size in window geometry coordinates */ gboolean has_new_min_size; int new_min_width; @@ -254,12 +252,8 @@ void meta_wayland_surface_unref_buffer_use_count (MetaWaylandSurf void meta_wayland_surface_set_window (MetaWaylandSurface *surface, MetaWindow *window); -void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, - int new_x, - int new_y, - int width, - int height, - MetaWaylandSerial *sent_serial); +void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, + MetaWaylandWindowConfiguration *configuration); void meta_wayland_surface_ping (MetaWaylandSurface *surface, guint32 serial); diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h index 6fcc67070..fbdf81292 100644 --- a/src/wayland/meta-wayland-types.h +++ b/src/wayland/meta-wayland-types.h @@ -51,10 +51,11 @@ typedef struct _MetaWaylandBuffer MetaWaylandBuffer; typedef struct _MetaWaylandRegion MetaWaylandRegion; typedef struct _MetaWaylandSurface MetaWaylandSurface; +typedef struct _MetaWaylandSurfaceState MetaWaylandSurfaceState; typedef struct _MetaWaylandOutput MetaWaylandOutput; -typedef struct _MetaWaylandSerial MetaWaylandSerial; +typedef struct _MetaWaylandWindowConfiguration MetaWaylandWindowConfiguration; typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient; diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c new file mode 100644 index 000000000..ca8b1125a --- /dev/null +++ b/src/wayland/meta-wayland-window-configuration.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + +#include "config.h" + +#include "wayland/meta-wayland-window-configuration.h" + +static uint32_t global_serial_counter = 0; + +MetaWaylandWindowConfiguration * +meta_wayland_window_configuration_new (int x, + int y, + int width, + int height) +{ + MetaWaylandWindowConfiguration *configuration; + + configuration = g_new0 (MetaWaylandWindowConfiguration, 1); + *configuration = (MetaWaylandWindowConfiguration) { + .serial = ++global_serial_counter, + + .has_position = TRUE, + .x = x, + .y = y, + + .has_size = TRUE, + .width = width, + .height = height, + }; + + return configuration; +} + +MetaWaylandWindowConfiguration * +meta_wayland_window_configuration_new_empty (void) +{ + MetaWaylandWindowConfiguration *configuration; + + configuration = g_new0 (MetaWaylandWindowConfiguration, 1); + *configuration = (MetaWaylandWindowConfiguration) { + .serial = ++global_serial_counter, + }; + + return configuration; +} + +void +meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration) +{ + g_free (configuration); +} diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h new file mode 100644 index 000000000..69f340c81 --- /dev/null +++ b/src/wayland/meta-wayland-window-configuration.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + +#ifndef META_WAYLAND_WINDOW_CONFIGURATION_H +#define META_WAYLAND_WINDOW_CONFIGURATION_H + +#include +#include + +#include "wayland/meta-wayland-types.h" + +struct _MetaWaylandWindowConfiguration +{ + uint32_t serial; + + gboolean has_position; + int x; + int y; + + gboolean has_size; + int width; + int height; +}; + +MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new (int x, + int y, + int width, + int height); +MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (void); + +void meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration); + +#endif /* META_WAYLAND_WINDOW_CONFIGURATION_H */ diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c index 12d0dee0b..01a0d85a5 100644 --- a/src/wayland/meta-wayland-wl-shell.c +++ b/src/wayland/meta-wayland-wl-shell.c @@ -32,6 +32,7 @@ #include "wayland/meta-wayland-shell-surface.h" #include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-versions.h" +#include "wayland/meta-wayland-window-configuration.h" #include "wayland/meta-wayland.h" #include "wayland/meta-window-wayland.h" @@ -65,6 +66,8 @@ struct _MetaWaylandWlShellSurface int x; int y; + + uint32_t emulated_ack_configure_serial; }; static void @@ -613,9 +616,11 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_shell_surface_calculate_geometry (shell_surface, &geom); } - meta_window_wayland_finish_move_resize (window, - NULL, - geom, pending->dx, pending->dy); + pending->has_acked_configure_serial = TRUE; + pending->acked_configure_serial = + wl_shell_surface->emulated_ack_configure_serial; + + meta_window_wayland_finish_move_resize (window, geom, pending); } static MetaWaylandSurface * @@ -632,12 +637,8 @@ wl_shell_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) } static void -wl_shell_surface_role_configure (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +wl_shell_surface_role_configure (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandWlShellSurface *wl_shell_surface = META_WAYLAND_WL_SHELL_SURFACE (shell_surface); @@ -647,7 +648,9 @@ wl_shell_surface_role_configure (MetaWaylandShellSurface *shell_surface, wl_shell_surface_send_configure (wl_shell_surface->resource, 0, - new_width, new_height); + configuration->width, configuration->height); + + wl_shell_surface->emulated_ack_configure_serial = configuration->serial; } static void diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index 39673fa44..bae0e9eb5 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -34,6 +34,7 @@ #include "wayland/meta-wayland-shell-surface.h" #include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-versions.h" +#include "wayland/meta-wayland-window-configuration.h" #include "wayland/meta-wayland.h" #include "wayland/meta-window-wayland.h" @@ -77,7 +78,6 @@ typedef struct _MetaWaylandXdgSurfacePrivate { struct wl_resource *resource; MetaWaylandXdgShellClient *shell_client; - MetaWaylandSerial acked_configure_serial; MetaRectangle geometry; guint configure_sent : 1; @@ -145,8 +145,9 @@ meta_wayland_xdg_surface_get_wm_base_resource (MetaWaylandXdgSurface *xdg_surfac static MetaRectangle meta_wayland_xdg_surface_get_window_geometry (MetaWaylandXdgSurface *xdg_surface); -static uint32_t -meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface); +static void +meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface, + MetaWaylandWindowConfiguration *configuration); static MetaWaylandSurface * surface_from_xdg_surface_resource (struct wl_resource *resource) @@ -622,30 +623,22 @@ fill_states (MetaWaylandXdgToplevel *xdg_toplevel, } static void -meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel *xdg_toplevel, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel *xdg_toplevel, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel); struct wl_array states; - uint32_t serial; wl_array_init (&states); fill_states (xdg_toplevel, &states); xdg_toplevel_send_configure (xdg_toplevel->resource, - new_width, new_height, + configuration->width, + configuration->height, &states); wl_array_release (&states); - serial = meta_wayland_xdg_surface_send_configure (xdg_surface); - - if (sent_serial) - { - sent_serial->set = TRUE; - sent_serial->value = serial; - } + meta_wayland_xdg_surface_send_configure (xdg_surface, configuration); } static gboolean @@ -720,7 +713,11 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role, if (!xdg_surface_priv->configure_sent) { - meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, 0, 0, NULL); + MetaWaylandWindowConfiguration *configuration; + + configuration = meta_wayland_window_configuration_new_empty (); + meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); + meta_wayland_window_configuration_free (configuration); return; } @@ -729,17 +726,12 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role, geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry); - if (geometry_changed || meta_window_wayland_has_pending_move_resize (window)) + if (geometry_changed || pending->has_acked_configure_serial) { MetaRectangle window_geometry; - MetaWaylandSerial *acked_configure_serial; window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); - acked_configure_serial = &xdg_surface_priv->acked_configure_serial; - meta_window_wayland_finish_move_resize (window, - acked_configure_serial, - window_geometry, - pending->dx, pending->dy); + meta_window_wayland_finish_move_resize (window, window_geometry, pending); } else if (pending->dx != 0 || pending->dy != 0) { @@ -772,8 +764,6 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role, } } - - xdg_surface_priv->acked_configure_serial.set = FALSE; } static MetaWaylandSurface * @@ -806,12 +796,8 @@ meta_wayland_xdg_toplevel_reset (MetaWaylandXdgSurface *xdg_surface) } static void -meta_wayland_xdg_toplevel_configure (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_xdg_toplevel_configure (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandXdgToplevel *xdg_toplevel = META_WAYLAND_XDG_TOPLEVEL (shell_surface); @@ -825,9 +811,7 @@ meta_wayland_xdg_toplevel_configure (MetaWaylandShellSurface *shell_surface, if (!xdg_toplevel->resource) return; - meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, - new_width, new_height, - sent_serial); + meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); } static void @@ -1046,7 +1030,7 @@ meta_wayland_xdg_popup_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaRectangle window_geometry; + MetaWindow *window; if (xdg_popup->setup.parent_surface) finish_popup_setup (xdg_popup); @@ -1071,7 +1055,8 @@ meta_wayland_xdg_popup_commit (MetaWaylandSurfaceRole *surface_role, } /* If the window disappeared the surface is not coming back. */ - if (!surface->window) + window = surface->window; + if (!window) return; if (!pending->newly_attached) @@ -1080,11 +1065,13 @@ meta_wayland_xdg_popup_commit (MetaWaylandSurfaceRole *surface_role, if (!surface->buffer_ref.buffer) return; - window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); - meta_window_wayland_finish_move_resize (surface->window, - NULL, - window_geometry, - pending->dx, pending->dy); + if (pending->has_acked_configure_serial) + { + MetaRectangle window_geometry; + + window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); + meta_window_wayland_finish_move_resize (window, window_geometry, pending); + } } static MetaWaylandSurface * @@ -1116,12 +1103,8 @@ meta_wayland_xdg_popup_reset (MetaWaylandXdgSurface *xdg_surface) } static void -meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface, - int new_x, - int new_y, - int new_width, - int new_height, - MetaWaylandSerial *sent_serial) +meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (shell_surface); MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup); @@ -1141,11 +1124,13 @@ meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface, return; geometry_scale = meta_window_wayland_get_geometry_scale (parent_window); - x = (new_x - parent_window->rect.x) / geometry_scale; - y = (new_y - parent_window->rect.y) / geometry_scale; + x = (configuration->x - parent_window->rect.x) / geometry_scale; + y = (configuration->y - parent_window->rect.y) / geometry_scale; xdg_popup_send_configure (xdg_popup->resource, - x, y, new_width, new_height); - meta_wayland_xdg_surface_send_configure (xdg_surface); + x, y, + configuration->width, configuration->height); + + meta_wayland_xdg_surface_send_configure (xdg_surface, configuration); } static void @@ -1299,21 +1284,16 @@ meta_wayland_xdg_surface_is_assigned (MetaWaylandXdgSurface *xdg_surface) return priv->resource != NULL; } -static uint32_t -meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface) +static void +meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface, + MetaWaylandWindowConfiguration *configuration) { MetaWaylandXdgSurfacePrivate *priv = meta_wayland_xdg_surface_get_instance_private (xdg_surface); - struct wl_display *display; - uint32_t serial; - display = wl_client_get_display (wl_resource_get_client (priv->resource)); - serial = wl_display_next_serial (display); - xdg_surface_send_configure (priv->resource, serial); + xdg_surface_send_configure (priv->resource, configuration->serial); priv->configure_sent = TRUE; - - return serial; } static void @@ -1398,12 +1378,12 @@ xdg_surface_ack_configure (struct wl_client *client, struct wl_resource *resource, uint32_t serial) { - MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); + MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); + MetaWaylandSurfaceState *pending; - priv->acked_configure_serial.set = TRUE; - priv->acked_configure_serial.value = serial; + pending = meta_wayland_surface_get_pending_state (surface); + pending->has_acked_configure_serial = TRUE; + pending->acked_configure_serial = serial; } static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = { diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 180703202..5a73de4c4 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -41,6 +41,7 @@ #include "wayland/meta-wayland-actor-surface.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-surface.h" +#include "wayland/meta-wayland-window-configuration.h" #include "wayland/meta-wayland-xdg-shell.h" struct _MetaWindowWayland @@ -49,11 +50,8 @@ struct _MetaWindowWayland int geometry_scale; - MetaWaylandSerial pending_configure_serial; + GList *pending_configurations; gboolean has_pending_state_change; - gboolean has_pending_move; - int pending_move_x; - int pending_move_y; int last_sent_x; int last_sent_y; @@ -164,6 +162,24 @@ meta_window_wayland_focus (MetaWindow *window, } } +static void +meta_window_wayland_configure (MetaWindowWayland *wl_window, + int x, + int y, + int width, + int height) +{ + MetaWindow *window = META_WINDOW (wl_window); + MetaWaylandWindowConfiguration *configuration; + + configuration = meta_wayland_window_configuration_new (x, y, width, height); + + meta_wayland_surface_configure_notify (window->surface, configuration); + + wl_window->pending_configurations = + g_list_prepend (wl_window->pending_configurations, configuration); +} + static void surface_state_changed (MetaWindow *window) { @@ -173,12 +189,11 @@ surface_state_changed (MetaWindow *window) if (window->unmanaging) return; - meta_wayland_surface_configure_notify (window->surface, - wl_window->last_sent_x, - wl_window->last_sent_y, - wl_window->last_sent_width, - wl_window->last_sent_height, - &wl_window->pending_configure_serial); + meta_window_wayland_configure (wl_window, + wl_window->last_sent_x, + wl_window->last_sent_y, + wl_window->last_sent_width, + wl_window->last_sent_height); } static void @@ -308,12 +323,11 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, constrained_rect.height == 1) return; - meta_wayland_surface_configure_notify (window->surface, - configured_x, - configured_y, - configured_width, - configured_height, - &wl_window->pending_configure_serial); + meta_window_wayland_configure (wl_window, + configured_x, + configured_y, + configured_width, + configured_height); /* We need to wait until the resize completes before we can move */ can_move_now = FALSE; @@ -358,16 +372,6 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, } else { - int new_x = constrained_rect.x; - int new_y = constrained_rect.y; - - if (new_x != window->rect.x || new_y != window->rect.y) - { - wl_window->has_pending_move = TRUE; - wl_window->pending_move_x = new_x; - wl_window->pending_move_y = new_y; - } - wl_window->has_pending_state_change = (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0; } } @@ -650,11 +654,25 @@ meta_window_wayland_unmap (MetaWindow *window) { } +static void +meta_window_wayland_finalize (GObject *object) +{ + MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (object); + + g_list_free_full (wl_window->pending_configurations, + (GDestroyNotify) meta_wayland_window_configuration_free); + + G_OBJECT_CLASS (meta_window_wayland_parent_class)->finalize (object); +} + static void meta_window_wayland_class_init (MetaWindowWaylandClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); MetaWindowClass *window_class = META_WINDOW_CLASS (klass); + object_class->finalize = meta_window_wayland_finalize; + window_class->manage = meta_window_wayland_manage; window_class->unmanage = meta_window_wayland_unmanage; window_class->ping = meta_window_wayland_ping; @@ -713,24 +731,51 @@ meta_window_wayland_new (MetaDisplay *display, return window; } -static gboolean -is_pending_ack_configure (MetaWindowWayland *wl_window, - MetaWaylandSerial *acked_configure_serial) +static MetaWaylandWindowConfiguration * +acquire_acked_configuration (MetaWindowWayland *wl_window, + MetaWaylandSurfaceState *pending) { - if (wl_window->pending_configure_serial.set) - { - /* If we're waiting for a configure and this isn't an ACK for - * any configure, then fizzle it out. */ - if (!acked_configure_serial->set) - return FALSE; + GList *l; - /* If we're waiting for a configure and this isn't an ACK for - * the configure we're waiting for, then fizzle it out. */ - if (acked_configure_serial->value != wl_window->pending_configure_serial.value) - return FALSE; + if (!pending->has_acked_configure_serial) + return NULL; + + for (l = wl_window->pending_configurations; l; l = l->next) + { + MetaWaylandWindowConfiguration *configuration = l->data; + GList *tail; + gboolean is_matching_configuration; + + if (configuration->serial > pending->acked_configure_serial) + continue; + + tail = l; + + if (tail->prev) + { + tail->prev->next = NULL; + tail->prev = NULL; + } + else + { + wl_window->pending_configurations = NULL; + } + + is_matching_configuration = + configuration->serial == pending->acked_configure_serial; + + if (is_matching_configuration) + tail = g_list_delete_link (tail, l); + g_list_free_full (tail, + (GDestroyNotify) meta_wayland_window_configuration_free); + + if (is_matching_configuration) + return configuration; + else + return NULL; } - return TRUE; + return NULL; } int @@ -748,18 +793,17 @@ meta_window_wayland_get_geometry_scale (MetaWindow *window) * Complete a resize operation from a wayland client. */ void -meta_window_wayland_finish_move_resize (MetaWindow *window, - MetaWaylandSerial *acked_configure_serial, - MetaRectangle new_geom, - int dx, - int dy) +meta_window_wayland_finish_move_resize (MetaWindow *window, + MetaRectangle new_geom, + MetaWaylandSurfaceState *pending) { MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + int dx, dy; int geometry_scale; int gravity; MetaRectangle rect; MetaMoveResizeFlags flags; - gboolean pending_ack_configure; + MetaWaylandWindowConfiguration *acked_configuration; /* new_geom is in the logical pixel coordinate space, but MetaWindow wants its * rects to represent what in turn will end up on the stage, i.e. we need to @@ -774,8 +818,8 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, /* The (dx, dy) offset is also in logical pixel coordinate space and needs * to be scaled in the same way as new_geom. */ - dx *= geometry_scale; - dy *= geometry_scale; + dx = pending->dx * geometry_scale; + dy = pending->dy * geometry_scale; /* XXX: Find a better place to store the window geometry offsets. */ window->custom_frame_extents.left = new_geom.x; @@ -783,17 +827,15 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, flags = META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE; - pending_ack_configure = is_pending_ack_configure (wl_window, acked_configure_serial); + acked_configuration = acquire_acked_configuration (wl_window, pending); /* x/y are ignored when we're doing interactive resizing */ if (!meta_grab_op_is_resizing (window->display->grab_op)) { - if (wl_window->has_pending_move && pending_ack_configure) + if (acked_configuration) { - rect.x = wl_window->pending_move_x; - rect.y = wl_window->pending_move_y; - wl_window->has_pending_move = FALSE; - flags |= META_MOVE_RESIZE_MOVE_ACTION; + rect.x = acked_configuration->x; + rect.y = acked_configuration->y; } else { @@ -801,22 +843,19 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, rect.y = window->rect.y; } - if (dx != 0 || dy != 0) - { - rect.x += dx; - rect.y += dy; - flags |= META_MOVE_RESIZE_MOVE_ACTION; - } + rect.x += dx; + rect.y += dy; + + if (rect.x != window->rect.x || rect.y != window->rect.y) + flags |= META_MOVE_RESIZE_MOVE_ACTION; } - if (wl_window->has_pending_state_change && pending_ack_configure) + if (wl_window->has_pending_state_change && acked_configuration) { flags |= META_MOVE_RESIZE_WAYLAND_STATE_CHANGED; wl_window->has_pending_state_change = FALSE; } - wl_window->pending_configure_serial.set = FALSE; - rect.width = new_geom.width; rect.height = new_geom.height; @@ -993,11 +1032,3 @@ meta_window_wayland_get_max_size (MetaWindow *window, scale = 1.0 / (float) meta_window_wayland_get_geometry_scale (window); scale_size (width, height, scale); } - -gboolean -meta_window_wayland_has_pending_move_resize (MetaWindow *window) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - - return wl_window->has_pending_state_change || wl_window->has_pending_move; -} diff --git a/src/wayland/meta-window-wayland.h b/src/wayland/meta-window-wayland.h index e5d06765a..0e18d4fe1 100644 --- a/src/wayland/meta-window-wayland.h +++ b/src/wayland/meta-window-wayland.h @@ -39,11 +39,10 @@ G_DECLARE_FINAL_TYPE (MetaWindowWayland, meta_window_wayland, MetaWindow * meta_window_wayland_new (MetaDisplay *display, MetaWaylandSurface *surface); -void meta_window_wayland_finish_move_resize (MetaWindow *window, - MetaWaylandSerial *acked_configure_serial, - MetaRectangle new_geom, - int dx, - int dy); +void meta_window_wayland_finish_move_resize (MetaWindow *window, + MetaRectangle new_geom, + MetaWaylandSurfaceState *pending); + int meta_window_wayland_get_geometry_scale (MetaWindow *window); void meta_window_wayland_place_relative_to (MetaWindow *window, @@ -71,6 +70,4 @@ void meta_window_wayland_get_max_size (MetaWindow *window, int *width, int *height); -gboolean meta_window_wayland_has_pending_move_resize (MetaWindow *window); - #endif