diff --git a/include/view-impl-common.h b/include/view-impl-common.h index 31513b5a..5c5f90f7 100644 --- a/include/view-impl-common.h +++ b/include/view-impl-common.h @@ -10,6 +10,8 @@ struct view; +void view_impl_init_foreign_toplevel(struct view *view); + void view_impl_map(struct view *view); void view_impl_unmap(struct view *view); diff --git a/include/view.h b/include/view.h index a8456de2..2888512f 100644 --- a/include/view.h +++ b/include/view.h @@ -119,6 +119,7 @@ struct view_impl { void (*unmap)(struct view *view, bool client_request); void (*maximize)(struct view *view, enum view_axis maximized); void (*minimize)(struct view *view, bool minimize); + struct view *(*get_parent)(struct view *self); struct view *(*get_root)(struct view *self); void (*append_children)(struct view *self, struct wl_array *children); bool (*is_modal_dialog)(struct view *self); diff --git a/src/view-impl-common.c b/src/view-impl-common.c index 8cb4d80f..fdef5601 100644 --- a/src/view-impl-common.c +++ b/src/view-impl-common.c @@ -7,6 +7,24 @@ #include "view.h" #include "window-rules.h" +void +view_impl_init_foreign_toplevel(struct view *view) +{ + if (view->foreign_toplevel) { + return; + } + + view->foreign_toplevel = foreign_toplevel_create(view); + + if (view->impl->get_parent) { + struct view *parent = view->impl->get_parent(view); + if (parent && parent->foreign_toplevel) { + foreign_toplevel_set_parent(view->foreign_toplevel, + parent->foreign_toplevel); + } + } +} + void view_impl_map(struct view *view) { diff --git a/src/xdg.c b/src/xdg.c index affe53ff..311ad406 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -575,6 +575,14 @@ xdg_toplevel_view_minimize(struct view *view, bool minimized) /* noop */ } +static struct view * +xdg_toplevel_view_get_parent(struct view *view) +{ + struct wlr_xdg_toplevel *toplevel = xdg_toplevel_from_view(view); + return toplevel->parent ? + (struct view *)toplevel->parent->base->data : NULL; +} + static struct wlr_xdg_toplevel * top_parent_of(struct view *view) { @@ -755,24 +763,6 @@ set_initial_position(struct view *view) view_place_by_policy(view, /* allow_cursor */ true, rc.placement_policy); } -static void -init_foreign_toplevel(struct view *view) -{ - assert(!view->foreign_toplevel); - view->foreign_toplevel = foreign_toplevel_create(view); - - struct wlr_xdg_toplevel *toplevel = xdg_toplevel_from_view(view); - if (!toplevel->parent) { - return; - } - struct wlr_xdg_surface *surface = toplevel->parent->base; - struct view *parent = surface->data; - if (!parent->foreign_toplevel) { - return; - } - foreign_toplevel_set_parent(view->foreign_toplevel, parent->foreign_toplevel); -} - static void xdg_toplevel_view_map(struct view *view) { @@ -799,7 +789,7 @@ xdg_toplevel_view_map(struct view *view) } if (!view->foreign_toplevel) { - init_foreign_toplevel(view); + view_impl_init_foreign_toplevel(view); /* * Initial outputs will be synced via * view->events.new_outputs on view_moved() @@ -889,6 +879,7 @@ static const struct view_impl xdg_toplevel_view_impl = { .unmap = xdg_toplevel_view_unmap, .maximize = xdg_toplevel_view_maximize, .minimize = xdg_toplevel_view_minimize, + .get_parent = xdg_toplevel_view_get_parent, .get_root = xdg_toplevel_view_get_root, .append_children = xdg_toplevel_view_append_children, .is_modal_dialog = xdg_toplevel_view_is_modal_dialog, diff --git a/src/xwayland.c b/src/xwayland.c index ac30941f..47b6d12f 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -192,6 +192,13 @@ xwayland_view_offer_focus(struct view *view) wlr_xwayland_surface_offer_focus(xwayland_surface_from_view(view)); } +static struct view * +xwayland_view_get_parent(struct view *view) +{ + struct wlr_xwayland_surface *xsurface = xwayland_surface_from_view(view); + return xsurface->parent ? (struct view *)xsurface->parent->data : NULL; +} + static struct wlr_xwayland_surface * top_parent_of(struct view *view) { @@ -767,23 +774,6 @@ set_initial_position(struct view *view, view_adjust_for_layout_change(view); } -static void -init_foreign_toplevel(struct view *view) -{ - assert(!view->foreign_toplevel); - view->foreign_toplevel = foreign_toplevel_create(view); - - struct wlr_xwayland_surface *surface = xwayland_surface_from_view(view); - if (!surface->parent) { - return; - } - struct view *parent = (struct view *)surface->parent->data; - if (!parent || !parent->foreign_toplevel) { - return; - } - foreign_toplevel_set_parent(view->foreign_toplevel, parent->foreign_toplevel); -} - static void set_surface(struct view *view, struct wlr_surface *surface) { @@ -862,7 +852,7 @@ xwayland_view_map(struct view *view) * shown in taskbars/docks/etc. */ if (!view->foreign_toplevel && view_is_focusable(view)) { - init_foreign_toplevel(view); + view_impl_init_foreign_toplevel(view); /* * Initial outputs will be synced via * view->events.new_outputs on view_moved() @@ -1037,6 +1027,7 @@ static const struct view_impl xwayland_view_impl = { .unmap = xwayland_view_unmap, .maximize = xwayland_view_maximize, .minimize = xwayland_view_minimize, + .get_parent = xwayland_view_get_parent, .get_root = xwayland_view_get_root, .append_children = xwayland_view_append_children, .is_modal_dialog = xwayland_view_is_modal_dialog,