From f9bffae9fd7cf6263427239fa8c3c2286a92b496 Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Sat, 26 Apr 2014 12:55:54 +0200 Subject: [PATCH] wayland: Scale native surfaces for hidpi Scale surfaces based on output scale and the buffer scale set by them. We pick the scale factor of the monitor there are mostly on. We only handle native i.e non xwayland / legacy clients yet. https://bugzilla.gnome.org/show_bug.cgi?id=728902 --- src/compositor/meta-surface-actor-wayland.c | 89 +++++++++++++++++++++ src/compositor/meta-surface-actor-wayland.h | 2 + src/compositor/meta-window-actor.c | 11 +++ src/wayland/meta-wayland-pointer.c | 2 +- src/wayland/meta-wayland-surface.c | 6 ++ 5 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c index e0c6ff7b7..c55322884 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c @@ -108,6 +108,53 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor) return FALSE; } +static int +get_output_scale (int output_id) +{ + MetaMonitorManager *monitor_manager = meta_monitor_manager_get (); + MetaOutput *outputs; + guint n_outputs, i; + int output_scale = 1; + + outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs); + + for (i = 0; i < n_outputs; i++) + { + if (outputs[i].output_id == output_id) + { + output_scale = outputs[i].scale; + break; + } + } + + return output_scale; +} + +double +meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor) +{ + MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (actor); + MetaWaylandSurface *surface = priv->surface; + MetaWindow *window = surface->window; + int output_scale = 1; + + while (surface) + { + if (surface->window) + { + window = surface->window; + break; + } + surface = surface->sub.parent; + } + + /* XXX: We do not handle x11 clients yet */ + if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11) + output_scale = get_output_scale (window->monitor->output_id); + + return (double)output_scale / (double)priv->surface->scale; +} + static MetaWindow * meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor) { @@ -116,6 +163,44 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor) return priv->surface->window; } +static void +meta_surface_actor_wayland_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); + MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self)); + + clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), for_height, min_width_p, natural_width_p); + + if (min_width_p) + *min_width_p *= scale; + + if (natural_width_p) + *natural_width_p *= scale; +} + +static void +meta_surface_actor_wayland_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); + MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self)); + + clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), for_width, min_height_p, natural_height_p); + + if (min_height_p) + *min_height_p *= scale; + + if (natural_height_p) + *natural_height_p *= scale; +} + static void meta_surface_actor_wayland_dispose (GObject *object) { @@ -130,8 +215,12 @@ static void meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) { MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); + actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width; + actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height; + surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint; surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible; diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h index 35058ccf2..f820523fe 100644 --- a/src/compositor/meta-surface-actor-wayland.h +++ b/src/compositor/meta-surface-actor-wayland.h @@ -61,6 +61,8 @@ MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWay void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, MetaWaylandBuffer *buffer); +double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor); + G_END_DECLS #endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */ diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 33cd54782..c1628d55c 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -32,6 +32,7 @@ #include "meta-surface-actor.h" #include "meta-surface-actor-x11.h" +#include "meta-surface-actor-wayland.h" #include "wayland/meta-wayland-surface.h" @@ -549,6 +550,16 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self, MetaWindowActorPrivate *priv = self->priv; cairo_region_get_extents (priv->shape_region, bounds); + + if (meta_is_wayland_compositor ()) + { + double scale = priv->surface ? + meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (priv->surface)) : 1.; + bounds->x *= scale; + bounds->y *= scale; + bounds->width *= scale; + bounds->height *= scale; + } } static void diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index 5a3a09cff..f68c29c9a 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -721,7 +721,7 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer, ClutterPoint pos; clutter_input_device_get_coords (pointer->device, NULL, &pos); - clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface->surface_actor), + clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)), pos.x, pos.y, &xf, &yf); *sx = wl_fixed_from_double (xf) / surface->scale; diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 7696ff4d7..6a47167b9 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -324,6 +324,7 @@ commit_pending_state (MetaWaylandSurface *surface, MetaWaylandPendingState *pending) { MetaWaylandCompositor *compositor = surface->compositor; + double output_scale; /* If this surface is a subsurface in in synchronous mode, commit * has a special-case and should not apply the pending state immediately. @@ -374,6 +375,11 @@ commit_pending_state (MetaWaylandSurface *surface, g_list_foreach (surface->subsurfaces, parent_surface_committed, NULL); + /* scale surface texture */ + output_scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); + clutter_actor_set_scale (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)), + output_scale, output_scale); + /* wl_surface.frame */ wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list); wl_list_init (&pending->frame_callback_list);