From 20176d0395294b9eeb7f0e28f1a1a35705fa0888 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sat, 17 Mar 2018 05:03:12 -0300 Subject: wayland: Check if state and size changed before calling move_resize() The current implementation of the XdgSurface v6 protocol does not check if the window changed before calling meta_window_wayland_move_resize(). The problem with this approach is that calling this function is a costly operation since we enter the compositor side. In GNOME Shell case, it is in JavaScript, which triggers a GJS trampoline. Calling this function on every mouse movement is naturally as terrible as it could be - and is exactly what happens now. This commit adds the necessary checks to only call move_resize() when the window actually changed, or when it needs to be updated. https://bugzilla.gnome.org/show_bug.cgi?id=780292 Issue: #78 --- src/wayland/meta-wayland-legacy-xdg-shell.c | 18 +++++++++++++++++- src/wayland/meta-wayland-xdg-shell.c | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/wayland/meta-wayland-legacy-xdg-shell.c b/src/wayland/meta-wayland-legacy-xdg-shell.c index c43bcff3e..cfc0dfedd 100644 --- a/src/wayland/meta-wayland-legacy-xdg-shell.c +++ b/src/wayland/meta-wayland-legacy-xdg-shell.c @@ -585,6 +585,17 @@ is_new_size_hints_valid (MetaWindow *window, (new_max_height == 0 || new_min_height <= new_max_height)); } +static inline gboolean +did_geometry_change (MetaWaylandZxdgSurfaceV6 *xdg_surface, + MetaWaylandPendingState *pending) +{ + MetaWaylandZxdgSurfaceV6Private *priv = + meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); + + return pending->has_new_geometry && + !meta_rectangle_equal (&priv->geometry, &pending->new_geometry); +} + static void meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandPendingState *pending) @@ -600,6 +611,11 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_surface_role_get_surface (surface_role); MetaWindow *window = surface->window; MetaRectangle window_geometry; + gboolean geometry_changed; + + /* This check must happen before chaining up, otherwise the new geometry + * is applied and it'll always return FALSE. */ + geometry_changed = did_geometry_change (xdg_surface, pending); surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class); @@ -618,7 +634,7 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role, if (!window) return; - if (pending->has_new_geometry) + if (geometry_changed || meta_window_wayland_needs_move_resize (window)) { window_geometry = meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface); diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index c750d3f66..a08520d31 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -608,6 +608,17 @@ is_new_size_hints_valid (MetaWindow *window, (new_max_height == 0 || new_min_height <= new_max_height)); } +static inline gboolean +did_geometry_change (MetaWaylandXdgSurface *xdg_surface, + MetaWaylandPendingState *pending) +{ + MetaWaylandXdgSurfacePrivate *priv = + meta_wayland_xdg_surface_get_instance_private (xdg_surface); + + return pending->has_new_geometry && + !meta_rectangle_equal (&priv->geometry, &pending->new_geometry); +} + static void meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandPendingState *pending) @@ -621,6 +632,7 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_surface_role_get_surface (surface_role); MetaWindow *window; MetaRectangle window_geometry; + gboolean geometry_changed; if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached) { @@ -630,6 +642,10 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role, window = surface->window; + /* This check must happen before chaining up, otherwise the new geometry + * is applied and it'll always return FALSE. */ + geometry_changed = did_geometry_change (xdg_surface, pending); + surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class); surface_role_class->commit (surface_role, pending); @@ -643,7 +659,7 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role, if (!pending->newly_attached) return; - if (pending->has_new_geometry) + if (geometry_changed || meta_window_wayland_needs_move_resize (window)) { window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); meta_window_wayland_move_resize (window, -- cgit v1.2.1