diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index d3580a078..3d4f0a9e7 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -133,6 +133,9 @@ static gboolean meta_wayland_surface_role_is_on_output (MetaWaylandSurfaceRole *surface_role, MetaMonitorInfo *info); +static MetaWaylandSurface * +meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role); + static void meta_wayland_surface_role_shell_surface_configure (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, int new_width, @@ -543,6 +546,16 @@ subsurface_role_commit (MetaWaylandSurfaceRole *surface_role, clutter_actor_hide (CLUTTER_ACTOR (surface_actor)); } +static MetaWaylandSurface * +subsurface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) +{ + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandSurface *parent = surface->sub.parent; + + return meta_wayland_surface_role_get_toplevel (parent->role); +} + /* A non-subsurface is always desynchronized. * * A subsurface is effectively synchronized if either its parent is @@ -1787,23 +1800,25 @@ meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface) surface->dnd.funcs->update (data_device, surface); } +MetaWaylandSurface * +meta_wayland_surface_get_toplevel (MetaWaylandSurface *surface) +{ + if (surface->role) + return meta_wayland_surface_role_get_toplevel (surface->role); + else + return NULL; +} + MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface) { - while (surface) - { - if (surface->window) - { - if (surface->popup.parent) - surface = surface->popup.parent; - else - return surface->window; - } - else - surface = surface->sub.parent; - } + MetaWaylandSurface *toplevel; - return NULL; + toplevel = meta_wayland_surface_get_toplevel (surface); + if (toplevel) + return toplevel->window; + else + return NULL; } void @@ -1901,6 +1916,18 @@ meta_wayland_surface_role_is_on_output (MetaWaylandSurfaceRole *surface_role, return FALSE; } +static MetaWaylandSurface * +meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) +{ + MetaWaylandSurfaceRoleClass *klass; + + klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); + if (klass->get_toplevel) + return klass->get_toplevel (surface_role); + else + return NULL; +} + MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role) { @@ -2056,6 +2083,7 @@ meta_wayland_surface_role_subsurface_class_init (MetaWaylandSurfaceRoleSubsurfac META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->commit = subsurface_role_commit; + surface_role_class->get_toplevel = subsurface_role_get_toplevel; } cairo_region_t * diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 920949e0b..85d33715f 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -62,6 +62,7 @@ struct _MetaWaylandSurfaceRoleClass MetaWaylandPendingState *pending); gboolean (*is_on_output) (MetaWaylandSurfaceRole *surface_role, MetaMonitorInfo *monitor); + MetaWaylandSurface * (*get_toplevel) (MetaWaylandSurfaceRole *surface_role); }; struct _MetaWaylandSerial { @@ -317,6 +318,8 @@ void meta_wayland_surface_drag_dest_update (MetaWaylandSurface void meta_wayland_surface_update_outputs (MetaWaylandSurface *surface); +MetaWaylandSurface *meta_wayland_surface_get_toplevel (MetaWaylandSurface *surface); + MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface); void meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface); diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c index d4a2e0722..135e6ccc8 100644 --- a/src/wayland/meta-wayland-wl-shell.c +++ b/src/wayland/meta-wayland-wl-shell.c @@ -509,6 +509,19 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_surface_apply_window_state (surface, pending); } +static MetaWaylandSurface * +wl_shell_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) +{ + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + + if (surface->wl_shell.state == META_WL_SHELL_SURFACE_STATE_POPUP && + surface->popup.parent) + return meta_wayland_surface_get_toplevel (surface->popup.parent); + else + return meta_wayland_surface_role_get_surface (surface_role); +} + static void wl_shell_surface_role_configure (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, int new_width, @@ -583,6 +596,7 @@ meta_wayland_wl_shell_surface_class_init (MetaWaylandWlShellSurfaceClass *klass) surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->commit = wl_shell_surface_role_commit; + surface_role_class->get_toplevel = wl_shell_surface_role_get_toplevel; shell_surface_role_class = META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_CLASS (klass); diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index b527d9b13..833d93455 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -588,6 +588,12 @@ xdg_surface_role_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_surface_apply_window_state (surface, pending); } +static MetaWaylandSurface * +xdg_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) +{ + return meta_wayland_surface_role_get_surface (surface_role); +} + static void xdg_surface_role_configure (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, int new_width, @@ -664,6 +670,7 @@ meta_wayland_xdg_surface_class_init (MetaWaylandXdgSurfaceClass *klass) META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->commit = xdg_surface_role_commit; + surface_role_class->get_toplevel = xdg_surface_role_get_toplevel; MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class = META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_CLASS (klass); @@ -699,6 +706,15 @@ xdg_popup_role_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_surface_apply_window_state (surface, pending); } +static MetaWaylandSurface * +xdg_popup_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) +{ + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + + return meta_wayland_surface_get_toplevel (surface->popup.parent); +} + static void xdg_popup_role_configure (MetaWaylandSurfaceRoleShellSurface *shell_surface_role, int new_width, @@ -760,6 +776,7 @@ meta_wayland_xdg_popup_class_init (MetaWaylandXdgPopupClass *klass) META_WAYLAND_SURFACE_ROLE_CLASS (klass); surface_role_class->commit = xdg_popup_role_commit; + surface_role_class->get_toplevel = xdg_popup_role_get_toplevel; MetaWaylandSurfaceRoleShellSurfaceClass *shell_surface_role_class = META_WAYLAND_SURFACE_ROLE_SHELL_SURFACE_CLASS (klass); diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index bf49f41dd..e8631c79e 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -618,6 +618,12 @@ xwayland_surface_commit (MetaWaylandSurfaceRole *surface_role, meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending); } +static MetaWaylandSurface * +xwayland_surface_get_toplevel (MetaWaylandSurfaceRole *surface_role) +{ + return meta_wayland_surface_role_get_surface (surface_role); +} + static void meta_wayland_surface_role_xwayland_init (MetaWaylandSurfaceRoleXWayland *role) { @@ -631,4 +637,5 @@ meta_wayland_surface_role_xwayland_class_init (MetaWaylandSurfaceRoleXWaylandCla surface_role_class->assigned = xwayland_surface_assigned; surface_role_class->commit = xwayland_surface_commit; + surface_role_class->get_toplevel = xwayland_surface_get_toplevel; }