wayland: Push actor state instead of itself pulling

Make the Wayland objects push the state relevant to their role to the
MetaSurfaceActor instead of MetaSurfaceActorWayland pulling the state
from the associated surface.

This makes the relationship between the actor and the objects that
constructs it more clear; the actor is a drawable that the protocol
objects control, not the other way around.

This will make it easier to "detach" a surface actor from a surface,
which is necessary when unmapping a window while the underlying surface
is yet to be destroyed and potentially reused.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/5
https://bugzilla.gnome.org/show_bug.cgi?id=791938
This commit is contained in:
Jonas Ådahl 2017-12-22 14:28:28 +08:00
parent 0162cdf8ef
commit 44624736c5
13 changed files with 305 additions and 306 deletions

View File

@ -90,216 +90,6 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
return FALSE; return FALSE;
} }
double
meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *self)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaWindow *window;
int geometry_scale = 1;
g_assert (surface);
window = meta_wayland_surface_get_toplevel_window (surface);
if (!meta_is_stage_views_scaled ())
{
/* XXX: We do not handle x11 clients yet */
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
geometry_scale = meta_window_wayland_get_geometry_scale (window);
}
return (double) geometry_scale / (double) 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 geometry_scale = 1;
g_assert (surface);
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
if (toplevel_window)
geometry_scale = meta_window_wayland_get_geometry_scale (toplevel_window);
*x = *x * geometry_scale;
*y = *y * geometry_scale;
}
/* Convert the current actor state to the corresponding subsurface rectangle
* in logical pixel coordinate space. */
void
meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
MetaRectangle *rect)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
CoglTexture *texture;
MetaWindow *toplevel_window;
int geometry_scale;
float x, y;
g_assert (surface);
texture = buffer->texture;
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
geometry_scale = meta_window_wayland_get_geometry_scale (toplevel_window);
clutter_actor_get_position (CLUTTER_ACTOR (self), &x, &y);
*rect = (MetaRectangle) {
.x = x / geometry_scale,
.y = y / geometry_scale,
.width = cogl_texture_get_width (texture) / surface->scale,
.height = cogl_texture_get_height (texture) / surface->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;
g_assert (surface);
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)
{
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaShapedTexture *stex =
meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
double texture_scale;
g_assert (surface);
/* Given the surface's window type and what output the surface actor has the
* largest region, scale the actor with the determined scale. */
texture_scale = meta_surface_actor_wayland_get_scale (self);
/* Actor scale. */
clutter_actor_set_scale (CLUTTER_ACTOR (stex), texture_scale, texture_scale);
/* Input region */
if (surface->input_region)
{
cairo_region_t *scaled_input_region;
int region_scale;
/* The input region from the Wayland surface is in the Wayland surface
* coordinate space, while the surface actor input region is in the
* physical pixel coordinate space. */
region_scale = (int)(surface->scale * texture_scale);
scaled_input_region = meta_region_scale (surface->input_region,
region_scale);
meta_surface_actor_set_input_region (META_SURFACE_ACTOR (self),
scaled_input_region);
cairo_region_destroy (scaled_input_region);
}
else
{
meta_surface_actor_set_input_region (META_SURFACE_ACTOR (self), NULL);
}
/* Opaque region */
if (surface->opaque_region)
{
cairo_region_t *scaled_opaque_region;
/* The opaque region from the Wayland surface is in Wayland surface
* coordinate space, while the surface actor opaque region is in the
* same coordinate space as the unscaled buffer texture. */
scaled_opaque_region = meta_region_scale (surface->opaque_region,
surface->scale);
meta_surface_actor_set_opaque_region (META_SURFACE_ACTOR (self),
scaled_opaque_region);
cairo_region_destroy (scaled_opaque_region);
}
else
{
meta_surface_actor_set_opaque_region (META_SURFACE_ACTOR (self), NULL);
}
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;
GList *iter;
g_assert (surface);
window = meta_wayland_surface_get_toplevel_window (surface);
meta_surface_actor_wayland_sync_state (self);
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
{
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));
}
}
}
gboolean
meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
MetaLogicalMonitor *logical_monitor)
{
float x, y, width, height;
cairo_rectangle_int_t actor_rect;
cairo_region_t *region;
gboolean is_on_monitor;
clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y);
clutter_actor_get_transformed_size (CLUTTER_ACTOR (self), &width, &height);
actor_rect.x = (int)roundf (x);
actor_rect.y = (int)roundf (y);
actor_rect.width = (int)roundf (x + width) - actor_rect.x;
actor_rect.height = (int)roundf (y + height) - actor_rect.y;
/* Calculate the scaled surface actor region. */
region = cairo_region_create_rectangle (&actor_rect);
cairo_region_intersect_rectangle (region,
&((cairo_rectangle_int_t) {
.x = logical_monitor->rect.x,
.y = logical_monitor->rect.y,
.width = logical_monitor->rect.width,
.height = logical_monitor->rect.height,
}));
is_on_monitor = !cairo_region_is_empty (region);
cairo_region_destroy (region);
return is_on_monitor;
}
void void
meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self, meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
struct wl_list *frame_callbacks) struct wl_list *frame_callbacks)
@ -328,16 +118,11 @@ meta_surface_actor_wayland_get_preferred_width (ClutterActor *actor,
gfloat *natural_width_p) gfloat *natural_width_p)
{ {
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaShapedTexture *stex; MetaShapedTexture *stex;
double scale; double scale;
if (surface)
scale = meta_surface_actor_wayland_get_scale (self);
else
scale = 1.0;
stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale, NULL);
clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex),
for_height, for_height,
min_width_p, min_width_p,
@ -357,16 +142,11 @@ meta_surface_actor_wayland_get_preferred_height (ClutterActor *actor,
gfloat *natural_height_p) gfloat *natural_height_p)
{ {
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
MetaShapedTexture *stex; MetaShapedTexture *stex;
double scale; double scale;
if (surface)
scale = meta_surface_actor_wayland_get_scale (self);
else
scale = 1.0;
stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
clutter_actor_get_scale (CLUTTER_ACTOR (stex), NULL, &scale);
clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex),
for_width, for_width,
min_height_p, min_height_p,

View File

@ -67,15 +67,6 @@ double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self, void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
MetaRectangle *rect); MetaRectangle *rect);
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,
MetaLogicalMonitor *logical_monitor);
void meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self, void meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
struct wl_list *frame_callbacks); struct wl_list *frame_callbacks);

View File

@ -23,8 +23,12 @@
#include "wayland/meta-wayland-actor-surface.h" #include "wayland/meta-wayland-actor-surface.h"
#include "backends/meta-backend-private.h"
#include "backends/meta-logical-monitor.h"
#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor-wayland.h"
#include "compositor/region-utils.h"
#include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-surface.h"
#include "wayland/meta-window-wayland.h"
G_DEFINE_TYPE (MetaWaylandActorSurface, G_DEFINE_TYPE (MetaWaylandActorSurface,
meta_wayland_actor_surface, meta_wayland_actor_surface,
@ -55,10 +59,110 @@ queue_surface_actor_frame_callbacks (MetaWaylandSurface *surface,
wl_list_init (&pending->frame_callback_list); wl_list_init (&pending->frame_callback_list);
} }
double
meta_wayland_actor_surface_calculate_scale (MetaWaylandActorSurface *actor_surface)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (actor_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWindow *toplevel_window;
int geometry_scale;
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
if (meta_is_stage_views_scaled ())
{
geometry_scale = 1;
}
else
{
if (!toplevel_window ||
toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11)
geometry_scale = 1;
else
geometry_scale =
meta_window_wayland_get_geometry_scale (toplevel_window);
}
return (double) geometry_scale / (double) surface->scale;
}
static void
meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor_surface)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (actor_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActor *surface_actor;
MetaShapedTexture *stex;
double actor_scale;
GList *l;
surface_actor = surface->surface_actor;
stex = meta_surface_actor_get_texture (surface_actor);
actor_scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
clutter_actor_set_scale (CLUTTER_ACTOR (stex), actor_scale, actor_scale);
if (surface->input_region)
{
cairo_region_t *scaled_input_region;
int region_scale;
/* Wayland surface coordinate space -> stage coordinate space */
region_scale = (int) (surface->scale * actor_scale);
scaled_input_region = meta_region_scale (surface->input_region,
region_scale);
meta_surface_actor_set_input_region (surface_actor, scaled_input_region);
cairo_region_destroy (scaled_input_region);
}
else
{
meta_surface_actor_set_input_region (surface_actor, NULL);
}
if (surface->opaque_region)
{
cairo_region_t *scaled_opaque_region;
/* Wayland surface coordinate space -> stage coordinate space */
scaled_opaque_region = meta_region_scale (surface->opaque_region,
surface->scale);
meta_surface_actor_set_opaque_region (surface_actor,
scaled_opaque_region);
cairo_region_destroy (scaled_opaque_region);
}
else
{
meta_surface_actor_set_opaque_region (surface_actor, NULL);
}
for (l = surface->subsurfaces; l; l = l->next)
{
MetaWaylandSurface *subsurface_surface = l->data;
MetaWaylandActorSurface *subsurface_actor_surface =
META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
meta_wayland_actor_surface_sync_actor_state (subsurface_actor_surface);
}
}
void
meta_wayland_actor_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface)
{
MetaWaylandActorSurfaceClass *actor_surface_class =
META_WAYLAND_ACTOR_SURFACE_GET_CLASS (actor_surface);
actor_surface_class->sync_actor_state (actor_surface);
}
static void static void
meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending) MetaWaylandPendingState *pending)
{ {
MetaWaylandActorSurface *actor_surface =
META_WAYLAND_ACTOR_SURFACE (surface_role);
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandSurface *toplevel_surface; MetaWaylandSurface *toplevel_surface;
@ -69,8 +173,7 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
if (!toplevel_surface || !toplevel_surface->window) if (!toplevel_surface || !toplevel_surface->window)
return; return;
meta_surface_actor_wayland_sync_state ( meta_wayland_actor_surface_sync_actor_state (actor_surface);
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
} }
static gboolean static gboolean
@ -79,10 +182,38 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
{ {
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActorWayland *actor = ClutterActor *actor = CLUTTER_ACTOR (surface->surface_actor);
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); float x, y, width, height;
cairo_rectangle_int_t actor_rect;
cairo_region_t *region;
MetaRectangle logical_monitor_layout;
gboolean is_on_monitor;
return meta_surface_actor_wayland_is_on_monitor (actor, logical_monitor); clutter_actor_get_transformed_position (actor, &x, &y);
clutter_actor_get_transformed_size (actor, &width, &height);
actor_rect.x = (int) roundf (x);
actor_rect.y = (int) roundf (y);
actor_rect.width = (int) roundf (x + width) - actor_rect.x;
actor_rect.height = (int) roundf (y + height) - actor_rect.y;
/* Calculate the scaled surface actor region. */
region = cairo_region_create_rectangle (&actor_rect);
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
cairo_region_intersect_rectangle (region,
&((cairo_rectangle_int_t) {
.x = logical_monitor_layout.x,
.y = logical_monitor_layout.y,
.width = logical_monitor_layout.width,
.height = logical_monitor_layout.height,
}));
is_on_monitor = !cairo_region_is_empty (region);
cairo_region_destroy (region);
return is_on_monitor;
} }
static void static void
@ -100,4 +231,6 @@ meta_wayland_actor_surface_class_init (MetaWaylandActorSurfaceClass *klass)
surface_role_class->commit = meta_wayland_actor_surface_commit; surface_role_class->commit = meta_wayland_actor_surface_commit;
surface_role_class->is_on_logical_monitor = surface_role_class->is_on_logical_monitor =
meta_wayland_actor_surface_is_on_logical_monitor; meta_wayland_actor_surface_is_on_logical_monitor;
klass->sync_actor_state = meta_wayland_actor_surface_real_sync_actor_state;
} }

View File

@ -32,6 +32,12 @@ G_DECLARE_DERIVABLE_TYPE (MetaWaylandActorSurface,
struct _MetaWaylandActorSurfaceClass struct _MetaWaylandActorSurfaceClass
{ {
MetaWaylandSurfaceRoleClass parent_class; MetaWaylandSurfaceRoleClass parent_class;
void (* sync_actor_state) (MetaWaylandActorSurface *actor_surface);
}; };
void meta_wayland_actor_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface);
double meta_wayland_actor_surface_calculate_scale (MetaWaylandActorSurface *actor_surface);
#endif /* META_WAYLAND_ACTOR_SURFACE_H */ #endif /* META_WAYLAND_ACTOR_SURFACE_H */

View File

@ -26,11 +26,53 @@
#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor-wayland.h"
#include "wayland/meta-wayland-actor-surface.h" #include "wayland/meta-wayland-actor-surface.h"
#include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-buffer.h"
#include "wayland/meta-wayland-subsurface.h"
#include "wayland/meta-wayland-surface.h"
#include "wayland/meta-window-wayland.h"
G_DEFINE_TYPE (MetaWaylandShellSurface, G_DEFINE_TYPE (MetaWaylandShellSurface,
meta_wayland_shell_surface, meta_wayland_shell_surface,
META_TYPE_WAYLAND_ACTOR_SURFACE) META_TYPE_WAYLAND_ACTOR_SURFACE)
void
meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface,
MetaRectangle *out_geometry)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (shell_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandBuffer *buffer;
CoglTexture *texture;
MetaRectangle geometry;
GList *l;
buffer = surface->buffer_ref.buffer;
if (!buffer)
return;
texture = meta_wayland_buffer_get_texture (buffer);
geometry = (MetaRectangle) {
.x = 0,
.y = 0,
.width = cogl_texture_get_width (texture) / surface->scale,
.height = cogl_texture_get_height (texture) / surface->scale,
};
for (l = surface->subsurfaces; l; l = l->next)
{
MetaWaylandSurface *subsurface_surface = l->data;
MetaWaylandSubsurface *subsurface =
META_WAYLAND_SUBSURFACE (subsurface_surface->role);
meta_wayland_subsurface_union_geometry (subsurface,
0, 0,
&geometry);
}
*out_geometry = geometry;
}
void void
meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface,
int new_x, int new_x,
@ -83,13 +125,14 @@ static void
meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending) MetaWaylandPendingState *pending)
{ {
MetaWaylandActorSurface *actor_surface =
META_WAYLAND_ACTOR_SURFACE (surface_role);
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurfaceRoleClass *surface_role_class;
MetaWindow *window; MetaWindow *window;
MetaWaylandBuffer *buffer; MetaWaylandBuffer *buffer;
CoglTexture *texture; CoglTexture *texture;
MetaSurfaceActorWayland *surface_actor;
double scale; double scale;
surface_role_class = surface_role_class =
@ -104,8 +147,7 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role
if (!window) if (!window)
return; return;
surface_actor = META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
scale = meta_surface_actor_wayland_get_scale (surface_actor);
texture = meta_wayland_buffer_get_texture (buffer); texture = meta_wayland_buffer_get_texture (buffer);
window->buffer_rect.width = cogl_texture_get_width (texture) * scale; window->buffer_rect.width = cogl_texture_get_width (texture) * scale;

View File

@ -61,4 +61,7 @@ void meta_wayland_shell_surface_close (MetaWaylandShellSurface *shell_surface);
void meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface, void meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface,
MetaWindow *window); MetaWindow *window);
void meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface,
MetaRectangle *out_geometry);
#endif /* META_WAYLAND_SHELL_SURFACE_H */ #endif /* META_WAYLAND_SHELL_SURFACE_H */

View File

@ -24,7 +24,10 @@
#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor-wayland.h"
#include "wayland/meta-wayland.h" #include "wayland/meta-wayland.h"
#include "wayland/meta-wayland-actor-surface.h"
#include "wayland/meta-wayland-buffer.h"
#include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-surface.h"
#include "wayland/meta-window-wayland.h"
typedef enum typedef enum
{ {
@ -48,10 +51,39 @@ G_DEFINE_TYPE (MetaWaylandSubsurface,
meta_wayland_subsurface, meta_wayland_subsurface,
META_TYPE_WAYLAND_ACTOR_SURFACE) META_TYPE_WAYLAND_ACTOR_SURFACE)
static void
sync_actor_subsurface_state (MetaWaylandSurface *surface)
{
ClutterActor *actor = CLUTTER_ACTOR (surface->surface_actor);
MetaWindow *toplevel_window;
int geometry_scale;
int x, y;
toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
if (!toplevel_window)
return;
if (toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11)
return;
geometry_scale = meta_window_wayland_get_geometry_scale (toplevel_window);
x = (surface->offset_x + surface->sub.x) * geometry_scale;
y = (surface->offset_y + surface->sub.y) * geometry_scale;
clutter_actor_set_position (actor, x, y);
if (surface->buffer_ref.buffer)
clutter_actor_show (actor);
else
clutter_actor_hide (actor);
}
void void
meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface) meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface)
{ {
MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface); MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface);
MetaWaylandActorSurface *actor_surface =
META_WAYLAND_ACTOR_SURFACE (subsurface);
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
@ -108,27 +140,48 @@ meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface)
if (meta_wayland_surface_is_effectively_synchronized (surface)) if (meta_wayland_surface_is_effectively_synchronized (surface))
meta_wayland_surface_apply_pending_state (surface, surface->sub.pending); meta_wayland_surface_apply_pending_state (surface, surface->sub.pending);
meta_surface_actor_wayland_sync_subsurface_state ( meta_wayland_actor_surface_sync_actor_state (actor_surface);
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
} }
static void void
meta_wayland_subsurface_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
MetaWaylandPendingState *pending) int parent_x,
int parent_y,
MetaRectangle *out_geometry)
{ {
MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface);
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
ClutterActor *actor = CLUTTER_ACTOR (surface->surface_actor); MetaWaylandBuffer *buffer;
CoglTexture *texture;
MetaRectangle geometry;
GList *l;
surface_role_class = buffer = surface->buffer_ref.buffer;
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_subsurface_parent_class); if (!buffer)
surface_role_class->commit (surface_role, pending); return;
if (surface->buffer_ref.buffer != NULL) texture = meta_wayland_buffer_get_texture (buffer);
clutter_actor_show (actor); geometry = (MetaRectangle) {
else .x = surface->offset_x + surface->sub.x,
clutter_actor_hide (actor); .y = surface->offset_y + surface->sub.y,
.width = cogl_texture_get_width (texture) / surface->scale,
.height = cogl_texture_get_height (texture) / surface->scale,
};
meta_rectangle_union (out_geometry, &geometry, out_geometry);
for (l = surface->subsurfaces; l; l = l->next)
{
MetaWaylandSurface *subsurface_surface = l->data;
MetaWaylandSubsurface *subsurface =
META_WAYLAND_SUBSURFACE (subsurface_surface->role);
meta_wayland_subsurface_union_geometry (subsurface,
parent_x + geometry.x,
parent_y + geometry.y,
out_geometry);
}
} }
static MetaWaylandSurface * static MetaWaylandSurface *
@ -144,6 +197,21 @@ meta_wayland_subsurface_get_toplevel (MetaWaylandSurfaceRole *surface_role)
return NULL; return NULL;
} }
static void
meta_wayland_subsurface_sync_actor_state (MetaWaylandActorSurface *actor_surface)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (actor_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandActorSurfaceClass *actor_surface_class =
META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_subsurface_parent_class);
actor_surface_class->sync_actor_state (actor_surface);
sync_actor_subsurface_state (surface);
}
static void static void
meta_wayland_subsurface_init (MetaWaylandSubsurface *role) meta_wayland_subsurface_init (MetaWaylandSubsurface *role)
{ {
@ -154,9 +222,13 @@ meta_wayland_subsurface_class_init (MetaWaylandSubsurfaceClass *klass)
{ {
MetaWaylandSurfaceRoleClass *surface_role_class = MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass); META_WAYLAND_SURFACE_ROLE_CLASS (klass);
MetaWaylandActorSurfaceClass *actor_surface_class =
META_WAYLAND_ACTOR_SURFACE_CLASS (klass);
surface_role_class->commit = meta_wayland_subsurface_commit;
surface_role_class->get_toplevel = meta_wayland_subsurface_get_toplevel; surface_role_class->get_toplevel = meta_wayland_subsurface_get_toplevel;
actor_surface_class->sync_actor_state =
meta_wayland_subsurface_sync_actor_state;
} }
static void static void
@ -355,6 +427,7 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
MetaWindow *toplevel_window;
if (surface->wl_subsurface) if (surface->wl_subsurface)
{ {
@ -374,6 +447,11 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
return; return;
} }
toplevel_window = meta_wayland_surface_get_toplevel_window (parent);
if (toplevel_window &&
toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11)
g_warning ("XWayland subsurfaces not currently supported");
surface->wl_subsurface = surface->wl_subsurface =
wl_resource_create (client, wl_resource_create (client,
&wl_subsurface_interface, &wl_subsurface_interface,

View File

@ -31,6 +31,11 @@ G_DECLARE_FINAL_TYPE (MetaWaylandSubsurface,
void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface); void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface);
void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
int parent_x,
int parent_y,
MetaRectangle *out_geometry);
void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor); void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor);
#endif /* META_WAYLAND_SUBSURFACE_H */ #endif /* META_WAYLAND_SUBSURFACE_H */

View File

@ -334,45 +334,6 @@ dnd_surface_commit (MetaWaylandSurfaceRole *surface_role,
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending); meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
} }
void
meta_wayland_surface_calculate_window_geometry (MetaWaylandSurface *surface,
MetaRectangle *total_geometry,
float parent_x,
float parent_y)
{
MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
MetaRectangle subsurface_rect;
MetaRectangle geom;
GList *l;
/* Unmapped surfaces don't count. */
if (!CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (surface_actor)))
return;
if (!surface->buffer_ref.buffer)
return;
meta_surface_actor_wayland_get_subsurface_rect (surface_actor,
&subsurface_rect);
geom.x = parent_x + subsurface_rect.x;
geom.y = parent_x + subsurface_rect.y;
geom.width = subsurface_rect.width;
geom.height = subsurface_rect.height;
meta_rectangle_union (total_geometry, &geom, total_geometry);
for (l = surface->subsurfaces; l != NULL; l = l->next)
{
MetaWaylandSurface *subsurface = l->data;
meta_wayland_surface_calculate_window_geometry (subsurface,
total_geometry,
subsurface_rect.x,
subsurface_rect.y);
}
}
void void
meta_wayland_surface_destroy_window (MetaWaylandSurface *surface) meta_wayland_surface_destroy_window (MetaWaylandSurface *surface)
{ {

View File

@ -278,10 +278,6 @@ MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRo
cairo_region_t * meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface); cairo_region_t * meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface);
void meta_wayland_surface_calculate_window_geometry (MetaWaylandSurface *surface,
MetaRectangle *total_geometry,
float parent_x,
float parent_y);
void meta_wayland_surface_destroy_window (MetaWaylandSurface *surface); void meta_wayland_surface_destroy_window (MetaWaylandSurface *surface);

View File

@ -30,6 +30,7 @@
#include "wayland/meta-wayland-popup.h" #include "wayland/meta-wayland-popup.h"
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-seat.h" #include "wayland/meta-wayland-seat.h"
#include "wayland/meta-wayland-shell-surface.h"
#include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-surface.h"
#include "wayland/meta-wayland-versions.h" #include "wayland/meta-wayland-versions.h"
#include "wayland/meta-window-wayland.h" #include "wayland/meta-window-wayland.h"
@ -564,6 +565,8 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
{ {
MetaWaylandWlShellSurface *wl_shell_surface = MetaWaylandWlShellSurface *wl_shell_surface =
META_WAYLAND_WL_SHELL_SURFACE (surface_role); META_WAYLAND_WL_SHELL_SURFACE (surface_role);
MetaWaylandShellSurface *shell_surface =
META_WAYLAND_SHELL_SURFACE (wl_shell_surface);
MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurfaceRoleClass *surface_role_class;
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
@ -596,7 +599,7 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
if (!pending->newly_attached) if (!pending->newly_attached)
return; return;
meta_wayland_surface_calculate_window_geometry (surface, &geom, 0, 0); meta_wayland_shell_surface_calculate_geometry (shell_surface, &geom);
meta_window_wayland_move_resize (window, meta_window_wayland_move_resize (window,
NULL, NULL,
geom, pending->dx, pending->dy); geom, pending->dx, pending->dy);

View File

@ -32,6 +32,7 @@
#include "wayland/meta-wayland-popup.h" #include "wayland/meta-wayland-popup.h"
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-seat.h" #include "wayland/meta-wayland-seat.h"
#include "wayland/meta-wayland-shell-surface.h"
#include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-surface.h"
#include "wayland/meta-wayland-versions.h" #include "wayland/meta-wayland-versions.h"
#include "wayland/meta-window-wayland.h" #include "wayland/meta-window-wayland.h"
@ -1230,6 +1231,8 @@ meta_wayland_xdg_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending) MetaWaylandPendingState *pending)
{ {
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
MetaWaylandShellSurface *shell_surface =
META_WAYLAND_SHELL_SURFACE (xdg_surface);
MetaWaylandXdgSurfacePrivate *priv = MetaWaylandXdgSurfacePrivate *priv =
meta_wayland_xdg_surface_get_instance_private (xdg_surface); meta_wayland_xdg_surface_get_instance_private (xdg_surface);
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
@ -1283,9 +1286,8 @@ meta_wayland_xdg_surface_commit (MetaWaylandSurfaceRole *surface_role,
/* If the surface has never set any geometry, calculate /* If the surface has never set any geometry, calculate
* a default one unioning the surface and all subsurfaces together. */ * a default one unioning the surface and all subsurfaces together. */
meta_wayland_surface_calculate_window_geometry (surface, meta_wayland_shell_surface_calculate_geometry (shell_surface,
&new_geometry, &new_geometry);
0, 0);
if (!meta_rectangle_equal (&new_geometry, &priv->geometry)) if (!meta_rectangle_equal (&new_geometry, &priv->geometry))
{ {
pending->has_new_geometry = TRUE; pending->has_new_geometry = TRUE;

View File

@ -32,6 +32,7 @@
#include "window-private.h" #include "window-private.h"
#include "boxes-private.h" #include "boxes-private.h"
#include "stack-tracker.h" #include "stack-tracker.h"
#include "meta-wayland-actor-surface.h"
#include "meta-wayland-private.h" #include "meta-wayland-private.h"
#include "meta-wayland-surface.h" #include "meta-wayland-surface.h"
#include "meta-wayland-xdg-shell.h" #include "meta-wayland-xdg-shell.h"
@ -491,15 +492,13 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
window, window,
TRUE); TRUE);
/* The surface actor needs to update the scale recursively for itself and all
* its subsurfaces */
surface = window->surface; surface = window->surface;
if (surface) if (surface)
{ {
MetaSurfaceActorWayland *actor = MetaWaylandActorSurface *actor_surface =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); META_WAYLAND_ACTOR_SURFACE (surface->role);
meta_surface_actor_wayland_sync_state_recursive (actor); meta_wayland_actor_surface_sync_actor_state (actor_surface);
} }
wl_window->geometry_scale = geometry_scale; wl_window->geometry_scale = geometry_scale;