window-actor/wayland: Align window content to physical pixel
Always ensure that the MetaSurfaceContainerActorWayland is aligned to physical pixel boundary in preparation for fractional-scale-v1 protocol support. This introduces an override of ClutterActor::apply_transform vfunc for MetaSurfaceContainerActorWayland that always ensures the actor content is aligned to physical pixel boundary. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2726>
This commit is contained in:
parent
e4d7667c43
commit
ed90c78872
@ -51,6 +51,7 @@ struct _MetaWindowActorWayland
|
|||||||
MetaWindowActor parent;
|
MetaWindowActor parent;
|
||||||
ClutterActor *background;
|
ClutterActor *background;
|
||||||
MetaSurfaceContainerActorWayland *surface_container;
|
MetaSurfaceContainerActorWayland *surface_container;
|
||||||
|
gulong highest_scale_monitor_handler_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||||
@ -123,6 +124,58 @@ surface_container_cullable_iface_init (MetaCullableInterface *iface)
|
|||||||
iface->reset_culling = surface_container_reset_culling;
|
iface->reset_culling = surface_container_reset_culling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_container_apply_transform (ClutterActor *actor,
|
||||||
|
graphene_matrix_t *matrix)
|
||||||
|
{
|
||||||
|
ClutterActor *parent = clutter_actor_get_parent (actor);
|
||||||
|
ClutterActorClass *parent_class =
|
||||||
|
CLUTTER_ACTOR_CLASS (meta_surface_container_actor_wayland_parent_class);
|
||||||
|
MetaWindow *window;
|
||||||
|
MetaLogicalMonitor *logical_monitor;
|
||||||
|
MetaRectangle monitor_rect;
|
||||||
|
float scale;
|
||||||
|
float rel_x, rel_y;
|
||||||
|
float abs_x, abs_y;
|
||||||
|
float adj_rel_x, adj_rel_y;
|
||||||
|
float x_off, y_off;
|
||||||
|
|
||||||
|
parent_class->apply_transform (actor, matrix);
|
||||||
|
|
||||||
|
if (!parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (parent));
|
||||||
|
if (!window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
logical_monitor = meta_window_get_highest_scale_monitor (window);
|
||||||
|
if (!logical_monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scale = meta_logical_monitor_get_scale (logical_monitor);
|
||||||
|
monitor_rect = meta_logical_monitor_get_layout (logical_monitor);
|
||||||
|
|
||||||
|
abs_x = clutter_actor_get_x (parent) + clutter_actor_get_x (actor);
|
||||||
|
abs_y = clutter_actor_get_y (parent) + clutter_actor_get_y (actor);
|
||||||
|
|
||||||
|
rel_x = abs_x - monitor_rect.x;
|
||||||
|
rel_y = abs_y - monitor_rect.y;
|
||||||
|
|
||||||
|
adj_rel_x = roundf (rel_x * scale) / scale;
|
||||||
|
adj_rel_y = roundf (rel_y * scale) / scale;
|
||||||
|
|
||||||
|
x_off = adj_rel_x - rel_x;
|
||||||
|
y_off = adj_rel_y - rel_y;
|
||||||
|
|
||||||
|
if (!G_APPROX_VALUE (x_off, 0.0, FLT_EPSILON) ||
|
||||||
|
!G_APPROX_VALUE (y_off, 0.0, FLT_EPSILON))
|
||||||
|
{
|
||||||
|
graphene_matrix_translate (matrix,
|
||||||
|
&GRAPHENE_POINT3D_INIT (x_off, y_off, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
surface_container_dispose (GObject *object)
|
surface_container_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@ -136,8 +189,11 @@ surface_container_dispose (GObject *object)
|
|||||||
static void
|
static void
|
||||||
meta_surface_container_actor_wayland_class_init (MetaSurfaceContainerActorWaylandClass *klass)
|
meta_surface_container_actor_wayland_class_init (MetaSurfaceContainerActorWaylandClass *klass)
|
||||||
{
|
{
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
actor_class->apply_transform = surface_container_apply_transform;
|
||||||
|
|
||||||
object_class->dispose = surface_container_dispose;
|
object_class->dispose = surface_container_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,10 +581,39 @@ meta_window_actor_wayland_sync_geometry (MetaWindowActor *actor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_actor_wayland_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
MetaWindowActorWayland *self = META_WINDOW_ACTOR_WAYLAND (object);
|
||||||
|
MetaWindow *window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (self));
|
||||||
|
GObjectClass *parent_class =
|
||||||
|
G_OBJECT_CLASS (meta_window_actor_wayland_parent_class);
|
||||||
|
|
||||||
|
g_clear_signal_handler (&self->highest_scale_monitor_handler_id,
|
||||||
|
window);
|
||||||
|
|
||||||
|
parent_class->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_actor_wayland_constructed (GObject *object)
|
||||||
|
{
|
||||||
|
MetaWindowActorWayland *self = META_WINDOW_ACTOR_WAYLAND (object);
|
||||||
|
MetaWindow *window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (self));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_window_actor_wayland_parent_class)->constructed (object);
|
||||||
|
|
||||||
|
self->highest_scale_monitor_handler_id =
|
||||||
|
g_signal_connect_swapped (window, "highest-scale-monitor-changed",
|
||||||
|
G_CALLBACK (clutter_actor_notify_transform_invalid),
|
||||||
|
self->surface_container);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass)
|
meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass)
|
||||||
{
|
{
|
||||||
MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass);
|
MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
window_actor_class->get_scanout_candidate = meta_window_actor_wayland_get_scanout_candidate;
|
window_actor_class->get_scanout_candidate = meta_window_actor_wayland_get_scanout_candidate;
|
||||||
window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor;
|
window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor;
|
||||||
@ -542,6 +627,9 @@ meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass)
|
|||||||
window_actor_class->can_freeze_commits = meta_window_actor_wayland_can_freeze_commits;
|
window_actor_class->can_freeze_commits = meta_window_actor_wayland_can_freeze_commits;
|
||||||
window_actor_class->sync_geometry = meta_window_actor_wayland_sync_geometry;
|
window_actor_class->sync_geometry = meta_window_actor_wayland_sync_geometry;
|
||||||
window_actor_class->is_single_surface_actor = meta_window_actor_wayland_is_single_surface_actor;
|
window_actor_class->is_single_surface_actor = meta_window_actor_wayland_is_single_surface_actor;
|
||||||
|
|
||||||
|
object_class->constructed = meta_window_actor_wayland_constructed;
|
||||||
|
object_class->dispose = meta_window_actor_wayland_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -551,4 +639,8 @@ meta_window_actor_wayland_init (MetaWindowActorWayland *self)
|
|||||||
|
|
||||||
clutter_actor_add_child (CLUTTER_ACTOR (self),
|
clutter_actor_add_child (CLUTTER_ACTOR (self),
|
||||||
CLUTTER_ACTOR (self->surface_container));
|
CLUTTER_ACTOR (self->surface_container));
|
||||||
|
|
||||||
|
g_signal_connect_swapped (self, "notify::allocation",
|
||||||
|
G_CALLBACK (clutter_actor_notify_transform_invalid),
|
||||||
|
self->surface_container);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user