From 3b993131e8fbd7fab2a1d8379ce4791f17f817f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 5 Mar 2015 11:11:09 +0800 Subject: [PATCH] wayland: Fix subsurface positioning on HiDPI Keep the active position state in its original coordinate space, and synchronize the surface actor with it when it changes and when synchronizing the rest of the surface state, in case the surface scale had changed. https://bugzilla.gnome.org/show_bug.cgi?id=745655 --- src/compositor/meta-surface-actor-wayland.c | 53 +++++++++++++++++++-- src/compositor/meta-surface-actor-wayland.h | 2 + src/wayland/meta-wayland-surface.c | 23 ++++----- src/wayland/meta-wayland-surface.h | 3 ++ 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c index 7c354d64a..76c11944e 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c @@ -102,6 +102,45 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor) return (double)output_scale / (double)priv->surface->scale; } +static void +logical_to_actor_position (MetaSurfaceActorWayland *self, + int *x, + int *y) +{ + MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self); + MetaWindow *toplevel_window; + int monitor_scale = 1; + + toplevel_window = meta_wayland_surface_get_toplevel_window (surface); + if (toplevel_window) + monitor_scale = meta_window_wayland_get_main_monitor_scale (toplevel_window); + + *x = *x * monitor_scale; + *y = *y * monitor_scale; +} + +void +meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self) +{ + MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self); + MetaWindow *window; + int x = surface->offset_x + surface->sub.x; + int y = surface->offset_y + surface->sub.y; + + window = meta_wayland_surface_get_toplevel_window (surface); + if (window && window->client_type == META_WINDOW_CLIENT_TYPE_X11) + { + /* Bail directly if this is part of a Xwayland window and warn + * if there happen to be offsets anyway since that is not supposed + * to happen. */ + g_warn_if_fail (x == 0 && y == 0); + return; + } + + logical_to_actor_position (self, &x, &y); + clutter_actor_set_position (CLUTTER_ACTOR (self), x, y); +} + void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self) { @@ -148,22 +187,28 @@ meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self) scaled_opaque_region); cairo_region_destroy (scaled_opaque_region); } + + meta_surface_actor_wayland_sync_subsurface_state (self); } void meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self) { MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self); + MetaWindow *window = meta_wayland_surface_get_toplevel_window (surface); GList *iter; meta_surface_actor_wayland_sync_state (self); - for (iter = surface->subsurfaces; iter != NULL; iter = iter->next) + if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11) { - MetaWaylandSurface *subsurf = iter->data; + for (iter = surface->subsurfaces; iter != NULL; iter = iter->next) + { + MetaWaylandSurface *subsurf = iter->data; - meta_surface_actor_wayland_sync_state_recursive ( - META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor)); + meta_surface_actor_wayland_sync_state_recursive ( + META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor)); + } } } diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h index 443bacc3c..4051abde2 100644 --- a/src/compositor/meta-surface-actor-wayland.h +++ b/src/compositor/meta-surface-actor-wayland.h @@ -70,6 +70,8 @@ void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self); void meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self); +void meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self); + gboolean meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self, MetaMonitorInfo *monitor); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 8f0ae9504..b116bada8 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -382,18 +382,13 @@ static void subsurface_surface_commit (MetaWaylandSurface *surface, MetaWaylandPendingState *pending) { - MetaSurfaceActor *surface_actor = surface->surface_actor; - float x, y; + MetaSurfaceActorWayland *surface_actor = + META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); if (surface->buffer != NULL) clutter_actor_show (CLUTTER_ACTOR (surface_actor)); else clutter_actor_hide (CLUTTER_ACTOR (surface_actor)); - - clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y); - x += pending->dx; - y += pending->dy; - clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y); } /* A non-subsurface is always desynchronized. @@ -427,9 +422,8 @@ parent_surface_state_applied (gpointer data, gpointer user_data) if (surface->sub.pending_pos) { - clutter_actor_set_position (CLUTTER_ACTOR (surface->surface_actor), - surface->sub.pending_x, - surface->sub.pending_y); + surface->sub.x = surface->sub.pending_x; + surface->sub.y = surface->sub.pending_y; surface->sub.pending_pos = FALSE; } @@ -477,6 +471,9 @@ parent_surface_state_applied (gpointer data, gpointer user_data) if (is_surface_effectively_synchronized (surface)) apply_pending_state (surface, &surface->sub.pending); + + meta_surface_actor_wayland_sync_subsurface_state ( + META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); } static void @@ -522,9 +519,6 @@ apply_pending_state (MetaWaylandSurface *surface, surface->input_region = cairo_region_reference (pending->input_region); } - meta_surface_actor_wayland_sync_state ( - META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); - /* wl_surface.frame */ wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list); wl_list_init (&pending->frame_callback_list); @@ -549,6 +543,9 @@ apply_pending_state (MetaWaylandSurface *surface, break; } + meta_surface_actor_wayland_sync_state ( + META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); + pending_state_reset (pending); g_list_foreach (surface->subsurfaces, parent_surface_state_applied, NULL); diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index a1d4c7eab..e599af6ad 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -136,6 +136,9 @@ struct _MetaWaylandSurface MetaWaylandSurface *parent; struct wl_listener parent_destroy_listener; + int x; + int y; + /* When the surface is synchronous, its state will be applied * when the parent is committed. This is done by moving the * "real" pending state below to here when this surface is