window-actor/wayland: Draw black background for fullscreen windows
Fullscreen Wayland toplevel surfaces don't need to respect the configured size in which case it should be shown centered on the monitor with a black background. The black background becomes part of the window geometry. The surface container is responsible for correctly culling the surfaces and making sure the surface actors are removed from the actor tree to avoid destroying them. The window actor culling implementation assumes all surfaces to be direct children of said actor. The introduction of the surface_container actor broke that assumption. This implements the culling interface in MetaWindowActorWayland which is aware of the actor surface_container and fullscreen state. v2: Fix forwarding culling to surface even if there is a background. v2: Don't alter passed geometry. v2: Update window geometry code documentation to reflect these changes. v2: Only use constrained rect if we're acked fullscreen. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2338>
This commit is contained in:
parent
0034b54877
commit
909616b208
@ -34,6 +34,8 @@ struct _MetaWindowActorClass
|
|||||||
void (*update_regions) (MetaWindowActor *actor);
|
void (*update_regions) (MetaWindowActor *actor);
|
||||||
gboolean (*can_freeze_commits) (MetaWindowActor *actor);
|
gboolean (*can_freeze_commits) (MetaWindowActor *actor);
|
||||||
|
|
||||||
|
void (*sync_geometry) (MetaWindowActor *actor,
|
||||||
|
const MetaRectangle *actor_rect);
|
||||||
gboolean (*is_single_surface_actor) (MetaWindowActor *actor);
|
gboolean (*is_single_surface_actor) (MetaWindowActor *actor);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,15 +22,35 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "compositor/clutter-utils.h"
|
||||||
#include "compositor/meta-cullable.h"
|
#include "compositor/meta-cullable.h"
|
||||||
#include "compositor/meta-surface-actor-wayland.h"
|
#include "compositor/meta-surface-actor-wayland.h"
|
||||||
#include "compositor/meta-window-actor-wayland.h"
|
#include "compositor/meta-window-actor-wayland.h"
|
||||||
|
#include "compositor/region-utils.h"
|
||||||
#include "meta/meta-window-actor.h"
|
#include "meta/meta-window-actor.h"
|
||||||
#include "wayland/meta-wayland-surface.h"
|
#include "wayland/meta-wayland-surface.h"
|
||||||
|
#include "wayland/meta-window-wayland.h"
|
||||||
|
|
||||||
|
struct _MetaSurfaceContainerActorWayland
|
||||||
|
{
|
||||||
|
ClutterActor parent;
|
||||||
|
|
||||||
|
MetaWindowActor *window_actor;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void surface_container_cullable_iface_init (MetaCullableInterface *iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (MetaSurfaceContainerActorWayland,
|
||||||
|
meta_surface_container_actor_wayland,
|
||||||
|
CLUTTER_TYPE_ACTOR,
|
||||||
|
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE,
|
||||||
|
surface_container_cullable_iface_init))
|
||||||
|
|
||||||
struct _MetaWindowActorWayland
|
struct _MetaWindowActorWayland
|
||||||
{
|
{
|
||||||
MetaWindowActor parent;
|
MetaWindowActor parent;
|
||||||
|
ClutterActor *background;
|
||||||
|
MetaSurfaceContainerActorWayland *surface_container;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||||
@ -42,10 +62,90 @@ G_DEFINE_TYPE_WITH_CODE (MetaWindowActorWayland, meta_window_actor_wayland,
|
|||||||
|
|
||||||
typedef struct _SurfaceTreeTraverseData
|
typedef struct _SurfaceTreeTraverseData
|
||||||
{
|
{
|
||||||
MetaWindowActor *window_actor;
|
ClutterActor *surface_container;
|
||||||
int index;
|
int index;
|
||||||
} SurfaceTreeTraverseData;
|
} SurfaceTreeTraverseData;
|
||||||
|
|
||||||
|
static MetaSurfaceContainerActorWayland *
|
||||||
|
surface_container_new (MetaWindowActor *window_actor)
|
||||||
|
{
|
||||||
|
MetaSurfaceContainerActorWayland *surface_container;
|
||||||
|
|
||||||
|
surface_container = g_object_new (META_TYPE_SURFACE_CONTAINER_ACTOR_WAYLAND,
|
||||||
|
NULL);
|
||||||
|
surface_container->window_actor = window_actor;
|
||||||
|
|
||||||
|
return surface_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_container_cull_out (MetaCullable *cullable,
|
||||||
|
cairo_region_t *unobscured_region,
|
||||||
|
cairo_region_t *clip_region)
|
||||||
|
{
|
||||||
|
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
surface_container_is_untransformed (MetaCullable *cullable)
|
||||||
|
{
|
||||||
|
MetaSurfaceContainerActorWayland *surface_container =
|
||||||
|
META_SURFACE_CONTAINER_ACTOR_WAYLAND (cullable);
|
||||||
|
ClutterActor *actor = CLUTTER_ACTOR (cullable);
|
||||||
|
MetaWindowActor *window_actor;
|
||||||
|
float width, height;
|
||||||
|
graphene_point3d_t verts[4];
|
||||||
|
int geometry_scale;
|
||||||
|
|
||||||
|
clutter_actor_get_size (actor, &width, &height);
|
||||||
|
clutter_actor_get_abs_allocation_vertices (actor, verts);
|
||||||
|
|
||||||
|
window_actor = surface_container->window_actor;
|
||||||
|
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
||||||
|
|
||||||
|
return meta_actor_vertices_are_untransformed (verts,
|
||||||
|
width * geometry_scale,
|
||||||
|
height * geometry_scale,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_container_reset_culling (MetaCullable *cullable)
|
||||||
|
{
|
||||||
|
meta_cullable_reset_culling_children (cullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_container_cullable_iface_init (MetaCullableInterface *iface)
|
||||||
|
{
|
||||||
|
iface->cull_out = surface_container_cull_out;
|
||||||
|
iface->is_untransformed = surface_container_is_untransformed;
|
||||||
|
iface->reset_culling = surface_container_reset_culling;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_container_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
MetaSurfaceContainerActorWayland *self = META_SURFACE_CONTAINER_ACTOR_WAYLAND (object);
|
||||||
|
|
||||||
|
clutter_actor_remove_all_children (CLUTTER_ACTOR (self));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_surface_container_actor_wayland_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_surface_container_actor_wayland_class_init (MetaSurfaceContainerActorWaylandClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = surface_container_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_surface_container_actor_wayland_init (MetaSurfaceContainerActorWayland *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
get_surface_actor_list (GNode *node,
|
get_surface_actor_list (GNode *node,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
@ -64,23 +164,23 @@ set_surface_actor_index (GNode *node,
|
|||||||
{
|
{
|
||||||
MetaWaylandSurface *surface = node->data;
|
MetaWaylandSurface *surface = node->data;
|
||||||
SurfaceTreeTraverseData *traverse_data = data;
|
SurfaceTreeTraverseData *traverse_data = data;
|
||||||
ClutterActor *window_actor = CLUTTER_ACTOR (traverse_data->window_actor);
|
ClutterActor *container = traverse_data->surface_container;
|
||||||
ClutterActor *surface_actor =
|
ClutterActor *surface_actor =
|
||||||
CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
|
CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
|
||||||
|
|
||||||
if (clutter_actor_contains (window_actor, surface_actor))
|
if (clutter_actor_contains (container, surface_actor))
|
||||||
{
|
{
|
||||||
if (clutter_actor_get_child_at_index (window_actor, traverse_data->index) !=
|
if (clutter_actor_get_child_at_index (container, traverse_data->index) !=
|
||||||
surface_actor)
|
surface_actor)
|
||||||
{
|
{
|
||||||
clutter_actor_set_child_at_index (window_actor,
|
clutter_actor_set_child_at_index (container,
|
||||||
surface_actor,
|
surface_actor,
|
||||||
traverse_data->index);
|
traverse_data->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clutter_actor_insert_child_at_index (window_actor,
|
clutter_actor_insert_child_at_index (container,
|
||||||
surface_actor,
|
surface_actor,
|
||||||
traverse_data->index);
|
traverse_data->index);
|
||||||
}
|
}
|
||||||
@ -92,6 +192,7 @@ set_surface_actor_index (GNode *node,
|
|||||||
void
|
void
|
||||||
meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor)
|
meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor)
|
||||||
{
|
{
|
||||||
|
MetaWindowActorWayland *self = META_WINDOW_ACTOR_WAYLAND (actor);
|
||||||
MetaSurfaceActor *surface_actor =
|
MetaSurfaceActor *surface_actor =
|
||||||
meta_window_actor_get_surface (actor);
|
meta_window_actor_get_surface (actor);
|
||||||
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (
|
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (
|
||||||
@ -109,18 +210,21 @@ meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor)
|
|||||||
get_surface_actor_list,
|
get_surface_actor_list,
|
||||||
&surface_actors);
|
&surface_actors);
|
||||||
|
|
||||||
children = clutter_actor_get_children (CLUTTER_ACTOR (actor));
|
children =
|
||||||
|
clutter_actor_get_children (CLUTTER_ACTOR (self->surface_container));
|
||||||
for (l = children; l; l = l->next)
|
for (l = children; l; l = l->next)
|
||||||
{
|
{
|
||||||
ClutterActor *child_actor = l->data;
|
ClutterActor *child_actor = l->data;
|
||||||
|
|
||||||
if (META_IS_SURFACE_ACTOR_WAYLAND (child_actor) &&
|
if (!g_list_find (surface_actors, child_actor))
|
||||||
!g_list_find (surface_actors, child_actor))
|
{
|
||||||
clutter_actor_remove_child (CLUTTER_ACTOR (actor), child_actor);
|
clutter_actor_remove_child (CLUTTER_ACTOR (self->surface_container),
|
||||||
|
child_actor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
traverse_data = (SurfaceTreeTraverseData) {
|
traverse_data = (SurfaceTreeTraverseData) {
|
||||||
.window_actor = actor,
|
.surface_container = CLUTTER_ACTOR (self->surface_container),
|
||||||
.index = 0,
|
.index = 0,
|
||||||
};
|
};
|
||||||
g_node_traverse (root_node,
|
g_node_traverse (root_node,
|
||||||
@ -131,14 +235,48 @@ meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor)
|
|||||||
&traverse_data);
|
&traverse_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_region_t *
|
||||||
|
calculate_background_cull_region (MetaWindowActorWayland *self)
|
||||||
|
{
|
||||||
|
MetaWindowActor *window_actor = META_WINDOW_ACTOR (self);
|
||||||
|
int geometry_scale;
|
||||||
|
cairo_rectangle_int_t rect;
|
||||||
|
|
||||||
|
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
||||||
|
rect = (cairo_rectangle_int_t) {
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = clutter_actor_get_width (self->background) * geometry_scale,
|
||||||
|
.height = clutter_actor_get_height (self->background) * geometry_scale,
|
||||||
|
};
|
||||||
|
|
||||||
|
return cairo_region_create_rectangle (&rect);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_wayland_cull_out (MetaCullable *cullable,
|
meta_window_actor_wayland_cull_out (MetaCullable *cullable,
|
||||||
cairo_region_t *unobscured_region,
|
cairo_region_t *unobscured_region,
|
||||||
cairo_region_t *clip_region)
|
cairo_region_t *clip_region)
|
||||||
{
|
{
|
||||||
meta_cullable_cull_out_children (cullable,
|
MetaWindowActorWayland *self =
|
||||||
|
META_WINDOW_ACTOR_WAYLAND (cullable);
|
||||||
|
|
||||||
|
meta_cullable_cull_out_children (META_CULLABLE (self),
|
||||||
unobscured_region,
|
unobscured_region,
|
||||||
clip_region);
|
clip_region);
|
||||||
|
if (self->background)
|
||||||
|
{
|
||||||
|
cairo_region_t *background_cull_region;
|
||||||
|
|
||||||
|
background_cull_region = calculate_background_cull_region (self);
|
||||||
|
|
||||||
|
if (unobscured_region)
|
||||||
|
cairo_region_subtract (unobscured_region, background_cull_region);
|
||||||
|
if (clip_region)
|
||||||
|
cairo_region_subtract (clip_region, background_cull_region);
|
||||||
|
|
||||||
|
cairo_region_destroy (background_cull_region);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -157,19 +295,25 @@ cullable_iface_init (MetaCullableInterface *iface)
|
|||||||
static MetaSurfaceActor *
|
static MetaSurfaceActor *
|
||||||
meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor)
|
meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor)
|
||||||
{
|
{
|
||||||
|
MetaWindowActorWayland *self = META_WINDOW_ACTOR_WAYLAND (actor);
|
||||||
|
ClutterActor *surface_container = CLUTTER_ACTOR (self->surface_container);
|
||||||
ClutterActor *child_actor;
|
ClutterActor *child_actor;
|
||||||
MetaSurfaceActor *topmost_surface_actor;
|
MetaSurfaceActor *topmost_surface_actor;
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
|
|
||||||
child_actor = clutter_actor_get_last_child (CLUTTER_ACTOR (actor));
|
if (clutter_actor_get_last_child (CLUTTER_ACTOR (self)) != surface_container)
|
||||||
if (!child_actor || !META_IS_SURFACE_ACTOR_WAYLAND (child_actor))
|
return NULL;
|
||||||
|
|
||||||
|
child_actor = clutter_actor_get_last_child (surface_container);
|
||||||
|
if (!child_actor)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
topmost_surface_actor = META_SURFACE_ACTOR (child_actor);
|
topmost_surface_actor = META_SURFACE_ACTOR (child_actor);
|
||||||
|
|
||||||
window = meta_window_actor_get_meta_window (actor);
|
window = meta_window_actor_get_meta_window (actor);
|
||||||
if (!meta_window_is_fullscreen (window) &&
|
if (!meta_surface_actor_is_opaque (topmost_surface_actor) &&
|
||||||
!meta_surface_actor_is_opaque (topmost_surface_actor))
|
!(meta_window_is_fullscreen (window) &&
|
||||||
|
clutter_actor_get_n_children (surface_container) == 1))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return topmost_surface_actor;
|
return topmost_surface_actor;
|
||||||
@ -223,6 +367,13 @@ static void
|
|||||||
meta_window_actor_wayland_set_frozen (MetaWindowActor *actor,
|
meta_window_actor_wayland_set_frozen (MetaWindowActor *actor,
|
||||||
gboolean frozen)
|
gboolean frozen)
|
||||||
{
|
{
|
||||||
|
MetaWindowActorWayland *self = META_WINDOW_ACTOR_WAYLAND (actor);
|
||||||
|
ClutterActor *child;
|
||||||
|
ClutterActorIter iter;
|
||||||
|
|
||||||
|
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self->surface_container));
|
||||||
|
while (clutter_actor_iter_next (&iter, &child))
|
||||||
|
meta_surface_actor_set_frozen (META_SURFACE_ACTOR (child), frozen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -239,36 +390,122 @@ meta_window_actor_wayland_can_freeze_commits (MetaWindowActor *actor)
|
|||||||
static gboolean
|
static gboolean
|
||||||
meta_window_actor_wayland_is_single_surface_actor (MetaWindowActor *actor)
|
meta_window_actor_wayland_is_single_surface_actor (MetaWindowActor *actor)
|
||||||
{
|
{
|
||||||
return clutter_actor_get_n_children (CLUTTER_ACTOR (actor)) == 1;
|
MetaWindowActorWayland *self = META_WINDOW_ACTOR_WAYLAND (actor);
|
||||||
|
ClutterActor *surface_container = CLUTTER_ACTOR (self->surface_container);
|
||||||
|
|
||||||
|
return clutter_actor_get_n_children (surface_container) == 1 &&
|
||||||
|
!self->background;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
maybe_configure_black_background (MetaWindowActorWayland *self,
|
||||||
|
float *surfaces_width,
|
||||||
|
float *surfaces_height,
|
||||||
|
float *background_width,
|
||||||
|
float *background_height)
|
||||||
|
{
|
||||||
|
MetaWindowActor *window_actor = META_WINDOW_ACTOR (self);
|
||||||
|
MetaWindow *window = meta_window_actor_get_meta_window (window_actor);
|
||||||
|
MetaLogicalMonitor *logical_monitor;
|
||||||
|
int geometry_scale;
|
||||||
|
MetaRectangle fullscreen_layout;
|
||||||
|
ClutterActor *child;
|
||||||
|
ClutterActorIter iter;
|
||||||
|
float max_width = 0;
|
||||||
|
float max_height = 0;
|
||||||
|
|
||||||
|
if (!meta_window_wayland_is_acked_fullscreen (META_WINDOW_WAYLAND (window)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
||||||
|
|
||||||
|
logical_monitor = meta_window_get_main_logical_monitor (window);
|
||||||
|
fullscreen_layout = meta_logical_monitor_get_layout (logical_monitor);
|
||||||
|
|
||||||
|
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self->surface_container));
|
||||||
|
while (clutter_actor_iter_next (&iter, &child))
|
||||||
|
{
|
||||||
|
float child_width, child_height;
|
||||||
|
|
||||||
|
clutter_actor_get_size (child, &child_width, &child_height);
|
||||||
|
|
||||||
|
if (META_IS_SURFACE_ACTOR (child) &&
|
||||||
|
meta_surface_actor_is_opaque (META_SURFACE_ACTOR (child)) &&
|
||||||
|
G_APPROX_VALUE (clutter_actor_get_x (child), 0,
|
||||||
|
CLUTTER_COORDINATE_EPSILON) &&
|
||||||
|
G_APPROX_VALUE (clutter_actor_get_y (child), 0,
|
||||||
|
CLUTTER_COORDINATE_EPSILON) &&
|
||||||
|
G_APPROX_VALUE (child_width, fullscreen_layout.width,
|
||||||
|
CLUTTER_COORDINATE_EPSILON) &&
|
||||||
|
G_APPROX_VALUE (child_height, fullscreen_layout.height,
|
||||||
|
CLUTTER_COORDINATE_EPSILON))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
max_width = MAX (max_width, child_width);
|
||||||
|
max_height = MAX (max_height, child_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
*surfaces_width = max_width;
|
||||||
|
*surfaces_height = max_height;
|
||||||
|
*background_width = window->rect.width / geometry_scale;
|
||||||
|
*background_height = window->rect.height / geometry_scale;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_wayland_dispose (GObject *object)
|
meta_window_actor_wayland_sync_geometry (MetaWindowActor *actor,
|
||||||
|
const MetaRectangle *actor_rect)
|
||||||
{
|
{
|
||||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (object);
|
MetaWindowActorWayland *self = META_WINDOW_ACTOR_WAYLAND (actor);
|
||||||
MetaSurfaceActor *surface_actor =
|
ClutterActor *surface_container = CLUTTER_ACTOR (self->surface_container);
|
||||||
meta_window_actor_get_surface (window_actor);
|
MetaWindow *window;
|
||||||
g_autoptr (GList) children = NULL;
|
float surfaces_width, surfaces_height;
|
||||||
GList *l;
|
float background_width, background_height;
|
||||||
|
|
||||||
children = clutter_actor_get_children (CLUTTER_ACTOR (window_actor));
|
window = meta_window_actor_get_meta_window (actor);
|
||||||
for (l = children; l; l = l->next)
|
if (window->unmanaging)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (maybe_configure_black_background (self,
|
||||||
|
&surfaces_width, &surfaces_height,
|
||||||
|
&background_width, &background_height))
|
||||||
{
|
{
|
||||||
ClutterActor *child_actor = l->data;
|
int geometry_scale;
|
||||||
|
int child_actor_width, child_actor_height;
|
||||||
|
|
||||||
if (META_IS_SURFACE_ACTOR_WAYLAND (child_actor) &&
|
if (!self->background)
|
||||||
child_actor != CLUTTER_ACTOR (surface_actor))
|
{
|
||||||
clutter_actor_remove_child (CLUTTER_ACTOR (window_actor), child_actor);
|
self->background = clutter_actor_new ();
|
||||||
|
clutter_actor_set_background_color (self->background,
|
||||||
|
CLUTTER_COLOR_Black);
|
||||||
|
clutter_actor_set_reactive (self->background, TRUE);
|
||||||
|
clutter_actor_insert_child_below (CLUTTER_ACTOR (self),
|
||||||
|
self->background,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_window_actor_wayland_parent_class)->dispose (object);
|
geometry_scale =
|
||||||
|
meta_window_actor_get_geometry_scale (actor);
|
||||||
|
child_actor_width = actor_rect->width / geometry_scale;
|
||||||
|
child_actor_height = actor_rect->height / geometry_scale;
|
||||||
|
|
||||||
|
clutter_actor_set_size (self->background,
|
||||||
|
background_width, background_height);
|
||||||
|
clutter_actor_set_position (surface_container,
|
||||||
|
(child_actor_width - surfaces_width) / 2,
|
||||||
|
(child_actor_height - surfaces_height) / 2);
|
||||||
|
}
|
||||||
|
else if (self->background)
|
||||||
|
{
|
||||||
|
clutter_actor_set_position (surface_container, 0, 0);
|
||||||
|
g_clear_pointer (&self->background, clutter_actor_destroy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -280,12 +517,15 @@ meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass)
|
|||||||
window_actor_class->set_frozen = meta_window_actor_wayland_set_frozen;
|
window_actor_class->set_frozen = meta_window_actor_wayland_set_frozen;
|
||||||
window_actor_class->update_regions = meta_window_actor_wayland_update_regions;
|
window_actor_class->update_regions = meta_window_actor_wayland_update_regions;
|
||||||
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->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->dispose = meta_window_actor_wayland_dispose;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_wayland_init (MetaWindowActorWayland *self)
|
meta_window_actor_wayland_init (MetaWindowActorWayland *self)
|
||||||
{
|
{
|
||||||
|
self->surface_container = surface_container_new (META_WINDOW_ACTOR (self));
|
||||||
|
|
||||||
|
clutter_actor_add_child (CLUTTER_ACTOR (self),
|
||||||
|
CLUTTER_ACTOR (self->surface_container));
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,12 @@ G_DECLARE_FINAL_TYPE (MetaWindowActorWayland,
|
|||||||
META, WINDOW_ACTOR_WAYLAND,
|
META, WINDOW_ACTOR_WAYLAND,
|
||||||
MetaWindowActor)
|
MetaWindowActor)
|
||||||
|
|
||||||
|
#define META_TYPE_SURFACE_CONTAINER_ACTOR_WAYLAND (meta_surface_container_actor_wayland_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaSurfaceContainerActorWayland,
|
||||||
|
meta_surface_container_actor_wayland,
|
||||||
|
META, SURFACE_CONTAINER_ACTOR_WAYLAND,
|
||||||
|
ClutterActor)
|
||||||
|
|
||||||
void meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor);
|
void meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor);
|
||||||
|
|
||||||
#endif /*META_WINDOW_ACTOR_WAYLAND_H */
|
#endif /*META_WINDOW_ACTOR_WAYLAND_H */
|
||||||
|
@ -1511,6 +1511,7 @@ meta_window_actor_x11_set_frozen (MetaWindowActor *actor,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
actor_x11->is_frozen = frozen;
|
actor_x11->is_frozen = frozen;
|
||||||
|
meta_surface_actor_set_frozen (meta_window_actor_get_surface (actor), frozen);
|
||||||
|
|
||||||
if (frozen)
|
if (frozen)
|
||||||
meta_window_x11_freeze_commits (window);
|
meta_window_x11_freeze_commits (window);
|
||||||
@ -1538,6 +1539,12 @@ meta_window_actor_x11_is_single_surface_actor (MetaWindowActor *actor)
|
|||||||
return clutter_actor_get_n_children (CLUTTER_ACTOR (actor)) == 1;
|
return clutter_actor_get_n_children (CLUTTER_ACTOR (actor)) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_actor_x11_sync_geometry (MetaWindowActor *actor,
|
||||||
|
const MetaRectangle *actor_rect)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_x11_set_property (GObject *object,
|
meta_window_actor_x11_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -1672,6 +1679,9 @@ meta_window_actor_x11_dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
g_clear_signal_handler (&actor_x11->repaint_scheduled_id, surface_actor);
|
g_clear_signal_handler (&actor_x11->repaint_scheduled_id, surface_actor);
|
||||||
g_clear_signal_handler (&actor_x11->size_changed_id, surface_actor);
|
g_clear_signal_handler (&actor_x11->size_changed_id, surface_actor);
|
||||||
|
|
||||||
|
clutter_actor_remove_child (CLUTTER_ACTOR (object),
|
||||||
|
CLUTTER_ACTOR (surface_actor));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy);
|
g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy);
|
||||||
@ -1714,6 +1724,7 @@ meta_window_actor_x11_class_init (MetaWindowActorX11Class *klass)
|
|||||||
window_actor_class->set_frozen = meta_window_actor_x11_set_frozen;
|
window_actor_class->set_frozen = meta_window_actor_x11_set_frozen;
|
||||||
window_actor_class->update_regions = meta_window_actor_x11_update_regions;
|
window_actor_class->update_regions = meta_window_actor_x11_update_regions;
|
||||||
window_actor_class->can_freeze_commits = meta_window_actor_x11_can_freeze_commits;
|
window_actor_class->can_freeze_commits = meta_window_actor_x11_can_freeze_commits;
|
||||||
|
window_actor_class->sync_geometry = meta_window_actor_x11_sync_geometry;
|
||||||
window_actor_class->is_single_surface_actor = meta_window_actor_x11_is_single_surface_actor;
|
window_actor_class->is_single_surface_actor = meta_window_actor_x11_is_single_surface_actor;
|
||||||
|
|
||||||
actor_class->paint = meta_window_actor_x11_paint;
|
actor_class->paint = meta_window_actor_x11_paint;
|
||||||
|
@ -270,16 +270,6 @@ static void
|
|||||||
meta_window_actor_set_frozen (MetaWindowActor *self,
|
meta_window_actor_set_frozen (MetaWindowActor *self,
|
||||||
gboolean frozen)
|
gboolean frozen)
|
||||||
{
|
{
|
||||||
ClutterActor *child;
|
|
||||||
ClutterActorIter iter;
|
|
||||||
|
|
||||||
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self));
|
|
||||||
while (clutter_actor_iter_next (&iter, &child))
|
|
||||||
{
|
|
||||||
if (META_IS_SURFACE_ACTOR (child))
|
|
||||||
meta_surface_actor_set_frozen (META_SURFACE_ACTOR (child), frozen);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_WINDOW_ACTOR_GET_CLASS (self)->set_frozen (self, frozen);
|
META_WINDOW_ACTOR_GET_CLASS (self)->set_frozen (self, frozen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,12 +454,7 @@ meta_window_actor_dispose (GObject *object)
|
|||||||
|
|
||||||
g_clear_object (&priv->window);
|
g_clear_object (&priv->window);
|
||||||
|
|
||||||
if (priv->surface)
|
|
||||||
{
|
|
||||||
clutter_actor_remove_child (CLUTTER_ACTOR (self),
|
|
||||||
CLUTTER_ACTOR (priv->surface));
|
|
||||||
g_clear_object (&priv->surface);
|
g_clear_object (&priv->surface);
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
|
G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@ -861,6 +846,8 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
|
|||||||
if (meta_window_actor_is_frozen (self) && !did_placement)
|
if (meta_window_actor_is_frozen (self) && !did_placement)
|
||||||
return META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE;
|
return META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE;
|
||||||
|
|
||||||
|
META_WINDOW_ACTOR_GET_CLASS (self)->sync_geometry (self, &actor_rect);
|
||||||
|
|
||||||
if (clutter_actor_has_allocation (actor))
|
if (clutter_actor_has_allocation (actor))
|
||||||
{
|
{
|
||||||
ClutterActorBox box;
|
ClutterActorBox box;
|
||||||
|
@ -267,14 +267,13 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
|
|||||||
configured_rect.width = constrained_rect.width;
|
configured_rect.width = constrained_rect.width;
|
||||||
configured_rect.height = constrained_rect.height;
|
configured_rect.height = constrained_rect.height;
|
||||||
|
|
||||||
/* For wayland clients, the size is completely determined by the client,
|
/* The size is determined by the client, except when the client is explicitly
|
||||||
* and while this allows to avoid some trickery with frames and the resulting
|
* fullscreen, in which case the compositor compensates for the size
|
||||||
* lagging, we also need to insist a bit when the constraints would apply
|
* difference between what surface configuration the client provided, and the
|
||||||
* a different size than the client decides.
|
* size of the area a fullscreen window state is expected to fill.
|
||||||
*
|
*
|
||||||
* Note that this is not generally a problem for normal toplevel windows (the
|
* For non-explicit-fullscreen states, since the size is always determined by
|
||||||
* constraints don't see the size hints, or just change the position), but
|
* the client, the we cannot use the size calculated by the constraints.
|
||||||
* it can be for maximized or fullscreen.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (flags & META_MOVE_RESIZE_FORCE_MOVE)
|
if (flags & META_MOVE_RESIZE_FORCE_MOVE)
|
||||||
@ -283,16 +282,26 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
|
|||||||
}
|
}
|
||||||
else if (flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE)
|
else if (flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE)
|
||||||
{
|
{
|
||||||
/* This is a call to wl_surface_commit(), ignore the constrained_rect and
|
MetaWaylandWindowConfiguration *configuration;
|
||||||
* update the real client size to match the buffer size.
|
int new_width, new_height;
|
||||||
*/
|
|
||||||
|
|
||||||
if (window->rect.width != unconstrained_rect.width ||
|
configuration = wl_window->last_acked_configuration;
|
||||||
window->rect.height != unconstrained_rect.height)
|
if (configuration && configuration->is_fullscreen)
|
||||||
|
{
|
||||||
|
new_width = constrained_rect.width;
|
||||||
|
new_height = constrained_rect.height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_width = unconstrained_rect.width;
|
||||||
|
new_height = unconstrained_rect.height;
|
||||||
|
}
|
||||||
|
if (window->rect.width != new_width ||
|
||||||
|
window->rect.height != new_height)
|
||||||
{
|
{
|
||||||
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
|
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
|
||||||
window->rect.width = unconstrained_rect.width;
|
window->rect.width = new_width;
|
||||||
window->rect.height = unconstrained_rect.height;
|
window->rect.height = new_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->buffer_rect.width =
|
window->buffer_rect.width =
|
||||||
@ -1290,3 +1299,10 @@ meta_window_wayland_get_max_size (MetaWindow *window,
|
|||||||
scale = 1.0 / (float) meta_window_wayland_get_geometry_scale (window);
|
scale = 1.0 / (float) meta_window_wayland_get_geometry_scale (window);
|
||||||
scale_size (width, height, scale);
|
scale_size (width, height, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_window_wayland_is_acked_fullscreen (MetaWindowWayland *wl_window)
|
||||||
|
{
|
||||||
|
return (wl_window->last_acked_configuration &&
|
||||||
|
wl_window->last_acked_configuration->is_fullscreen);
|
||||||
|
}
|
||||||
|
@ -81,4 +81,6 @@ gboolean meta_window_wayland_is_resize (MetaWindowWayland *wl_window,
|
|||||||
int width,
|
int width,
|
||||||
int height);
|
int height);
|
||||||
|
|
||||||
|
gboolean meta_window_wayland_is_acked_fullscreen (MetaWindowWayland *wl_window);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user