Commit 3b993131 authored by Jonas Ådahl's avatar Jonas Ådahl

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
parent 117f57f7
......@@ -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));
}
}
}
......
......@@ -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);
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment