From 44624736c59fb44f574e62dd4b7838f8c0157f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 22 Dec 2017 14:28:28 +0800 Subject: [PATCH] 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 --- src/compositor/meta-surface-actor-wayland.c | 224 +------------------- src/compositor/meta-surface-actor-wayland.h | 9 - src/wayland/meta-wayland-actor-surface.c | 143 ++++++++++++- src/wayland/meta-wayland-actor-surface.h | 6 + src/wayland/meta-wayland-shell-surface.c | 48 ++++- src/wayland/meta-wayland-shell-surface.h | 3 + src/wayland/meta-wayland-subsurface.c | 108 ++++++++-- src/wayland/meta-wayland-subsurface.h | 5 + src/wayland/meta-wayland-surface.c | 39 ---- src/wayland/meta-wayland-surface.h | 4 - src/wayland/meta-wayland-wl-shell.c | 5 +- src/wayland/meta-wayland-xdg-shell.c | 8 +- src/wayland/meta-window-wayland.c | 9 +- 13 files changed, 305 insertions(+), 306 deletions(-) diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c index fb4876141..7505b7d79 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c @@ -90,216 +90,6 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor) 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 meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self, struct wl_list *frame_callbacks) @@ -328,16 +118,11 @@ meta_surface_actor_wayland_get_preferred_width (ClutterActor *actor, gfloat *natural_width_p) { MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); - MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self); MetaShapedTexture *stex; 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)); + clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale, NULL); clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), for_height, min_width_p, @@ -357,16 +142,11 @@ meta_surface_actor_wayland_get_preferred_height (ClutterActor *actor, gfloat *natural_height_p) { MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); - MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self); MetaShapedTexture *stex; 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)); + clutter_actor_get_scale (CLUTTER_ACTOR (stex), NULL, &scale); clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), for_width, min_height_p, diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h index 58943cf72..277b1a39d 100644 --- a/src/compositor/meta-surface-actor-wayland.h +++ b/src/compositor/meta-surface-actor-wayland.h @@ -67,15 +67,6 @@ double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor); void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self, 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, struct wl_list *frame_callbacks); diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index a07d0d5e9..3ffe493f6 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -23,8 +23,12 @@ #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/region-utils.h" #include "wayland/meta-wayland-surface.h" +#include "wayland/meta-window-wayland.h" G_DEFINE_TYPE (MetaWaylandActorSurface, meta_wayland_actor_surface, @@ -55,10 +59,110 @@ queue_surface_actor_frame_callbacks (MetaWaylandSurface *surface, 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 meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandPendingState *pending) { + MetaWaylandActorSurface *actor_surface = + META_WAYLAND_ACTOR_SURFACE (surface_role); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaWaylandSurface *toplevel_surface; @@ -69,8 +173,7 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role, if (!toplevel_surface || !toplevel_surface->window) return; - meta_surface_actor_wayland_sync_state ( - META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); + meta_wayland_actor_surface_sync_actor_state (actor_surface); } static gboolean @@ -79,10 +182,38 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac { MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaSurfaceActorWayland *actor = - META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); + ClutterActor *actor = CLUTTER_ACTOR (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 @@ -100,4 +231,6 @@ meta_wayland_actor_surface_class_init (MetaWaylandActorSurfaceClass *klass) surface_role_class->commit = meta_wayland_actor_surface_commit; surface_role_class->is_on_logical_monitor = meta_wayland_actor_surface_is_on_logical_monitor; + + klass->sync_actor_state = meta_wayland_actor_surface_real_sync_actor_state; } diff --git a/src/wayland/meta-wayland-actor-surface.h b/src/wayland/meta-wayland-actor-surface.h index 9f0f79e7b..a5cc24455 100644 --- a/src/wayland/meta-wayland-actor-surface.h +++ b/src/wayland/meta-wayland-actor-surface.h @@ -32,6 +32,12 @@ G_DECLARE_DERIVABLE_TYPE (MetaWaylandActorSurface, struct _MetaWaylandActorSurfaceClass { 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 */ diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c index 023ece00a..becaecb08 100644 --- a/src/wayland/meta-wayland-shell-surface.c +++ b/src/wayland/meta-wayland-shell-surface.c @@ -26,11 +26,53 @@ #include "compositor/meta-surface-actor-wayland.h" #include "wayland/meta-wayland-actor-surface.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, meta_wayland_shell_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 meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, int new_x, @@ -83,13 +125,14 @@ static void meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandPendingState *pending) { + MetaWaylandActorSurface *actor_surface = + META_WAYLAND_ACTOR_SURFACE (surface_role); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaWaylandSurfaceRoleClass *surface_role_class; MetaWindow *window; MetaWaylandBuffer *buffer; CoglTexture *texture; - MetaSurfaceActorWayland *surface_actor; double scale; surface_role_class = @@ -104,8 +147,7 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role if (!window) return; - surface_actor = META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); - scale = meta_surface_actor_wayland_get_scale (surface_actor); + scale = meta_wayland_actor_surface_calculate_scale (actor_surface); texture = meta_wayland_buffer_get_texture (buffer); window->buffer_rect.width = cogl_texture_get_width (texture) * scale; diff --git a/src/wayland/meta-wayland-shell-surface.h b/src/wayland/meta-wayland-shell-surface.h index 72b0828b5..0cfb5b69d 100644 --- a/src/wayland/meta-wayland-shell-surface.h +++ b/src/wayland/meta-wayland-shell-surface.h @@ -61,4 +61,7 @@ void meta_wayland_shell_surface_close (MetaWaylandShellSurface *shell_surface); void meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface, MetaWindow *window); +void meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface, + MetaRectangle *out_geometry); + #endif /* META_WAYLAND_SHELL_SURFACE_H */ diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c index 1e630fa98..4bcffd0ea 100644 --- a/src/wayland/meta-wayland-subsurface.c +++ b/src/wayland/meta-wayland-subsurface.c @@ -24,7 +24,10 @@ #include "compositor/meta-surface-actor-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-window-wayland.h" typedef enum { @@ -48,10 +51,39 @@ G_DEFINE_TYPE (MetaWaylandSubsurface, meta_wayland_subsurface, 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 meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface) { MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface); + MetaWaylandActorSurface *actor_surface = + META_WAYLAND_ACTOR_SURFACE (subsurface); MetaWaylandSurface *surface = 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)) meta_wayland_surface_apply_pending_state (surface, surface->sub.pending); - meta_surface_actor_wayland_sync_subsurface_state ( - META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); + meta_wayland_actor_surface_sync_actor_state (actor_surface); } -static void -meta_wayland_subsurface_commit (MetaWaylandSurfaceRole *surface_role, - MetaWaylandPendingState *pending) +void +meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, + int parent_x, + int parent_y, + MetaRectangle *out_geometry) { - MetaWaylandSurfaceRoleClass *surface_role_class; + MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface); MetaWaylandSurface *surface = 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 = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_subsurface_parent_class); - surface_role_class->commit (surface_role, pending); + buffer = surface->buffer_ref.buffer; + if (!buffer) + return; - if (surface->buffer_ref.buffer != NULL) - clutter_actor_show (actor); - else - clutter_actor_hide (actor); + texture = meta_wayland_buffer_get_texture (buffer); + geometry = (MetaRectangle) { + .x = surface->offset_x + surface->sub.x, + .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 * @@ -144,6 +197,21 @@ meta_wayland_subsurface_get_toplevel (MetaWaylandSurfaceRole *surface_role) 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 meta_wayland_subsurface_init (MetaWaylandSubsurface *role) { @@ -154,9 +222,13 @@ meta_wayland_subsurface_class_init (MetaWaylandSubsurfaceClass *klass) { MetaWaylandSurfaceRoleClass *surface_role_class = 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; + + actor_surface_class->sync_actor_state = + meta_wayland_subsurface_sync_actor_state; } static void @@ -355,6 +427,7 @@ wl_subcompositor_get_subsurface (struct wl_client *client, { MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource); + MetaWindow *toplevel_window; if (surface->wl_subsurface) { @@ -374,6 +447,11 @@ wl_subcompositor_get_subsurface (struct wl_client *client, 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 = wl_resource_create (client, &wl_subsurface_interface, diff --git a/src/wayland/meta-wayland-subsurface.h b/src/wayland/meta-wayland-subsurface.h index eac3c6c7b..d92c02197 100644 --- a/src/wayland/meta-wayland-subsurface.h +++ b/src/wayland/meta-wayland-subsurface.h @@ -31,6 +31,11 @@ G_DECLARE_FINAL_TYPE (MetaWaylandSubsurface, 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); #endif /* META_WAYLAND_SUBSURFACE_H */ diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 301992627..8c41a1078 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -334,45 +334,6 @@ dnd_surface_commit (MetaWaylandSurfaceRole *surface_role, 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 meta_wayland_surface_destroy_window (MetaWaylandSurface *surface) { diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 92e385030..e04acb655 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -278,10 +278,6 @@ MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRo 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); diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c index 86d809193..4b93c95c8 100644 --- a/src/wayland/meta-wayland-wl-shell.c +++ b/src/wayland/meta-wayland-wl-shell.c @@ -30,6 +30,7 @@ #include "wayland/meta-wayland-popup.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-seat.h" +#include "wayland/meta-wayland-shell-surface.h" #include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-versions.h" #include "wayland/meta-window-wayland.h" @@ -564,6 +565,8 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role, { MetaWaylandWlShellSurface *wl_shell_surface = META_WAYLAND_WL_SHELL_SURFACE (surface_role); + MetaWaylandShellSurface *shell_surface = + META_WAYLAND_SHELL_SURFACE (wl_shell_surface); MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); @@ -596,7 +599,7 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role, if (!pending->newly_attached) 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, NULL, geom, pending->dx, pending->dy); diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index 0fe5c2845..855d31342 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -32,6 +32,7 @@ #include "wayland/meta-wayland-popup.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-seat.h" +#include "wayland/meta-wayland-shell-surface.h" #include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-versions.h" #include "wayland/meta-window-wayland.h" @@ -1230,6 +1231,8 @@ meta_wayland_xdg_surface_commit (MetaWaylandSurfaceRole *surface_role, MetaWaylandPendingState *pending) { MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); + MetaWaylandShellSurface *shell_surface = + META_WAYLAND_SHELL_SURFACE (xdg_surface); MetaWaylandXdgSurfacePrivate *priv = meta_wayland_xdg_surface_get_instance_private (xdg_surface); MetaWaylandSurface *surface = @@ -1283,9 +1286,8 @@ meta_wayland_xdg_surface_commit (MetaWaylandSurfaceRole *surface_role, /* If the surface has never set any geometry, calculate * a default one unioning the surface and all subsurfaces together. */ - meta_wayland_surface_calculate_window_geometry (surface, - &new_geometry, - 0, 0); + meta_wayland_shell_surface_calculate_geometry (shell_surface, + &new_geometry); if (!meta_rectangle_equal (&new_geometry, &priv->geometry)) { pending->has_new_geometry = TRUE; diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 4d9aadbbb..939071e08 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -32,6 +32,7 @@ #include "window-private.h" #include "boxes-private.h" #include "stack-tracker.h" +#include "meta-wayland-actor-surface.h" #include "meta-wayland-private.h" #include "meta-wayland-surface.h" #include "meta-wayland-xdg-shell.h" @@ -491,15 +492,13 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window, window, TRUE); - /* The surface actor needs to update the scale recursively for itself and all - * its subsurfaces */ surface = window->surface; if (surface) { - MetaSurfaceActorWayland *actor = - META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); + MetaWaylandActorSurface *actor_surface = + 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;