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;