diff --git a/seat.c b/seat.c index addceb1..e90c8e7 100644 --- a/seat.c +++ b/seat.c @@ -89,9 +89,14 @@ press_cursor_button(struct cg_seat *seat, struct wlr_input_device *device, struct wlr_surface *surface; struct cg_view *view = desktop_view_at(server, lx, ly, &surface, &sx, &sy); + struct cg_view *current = seat_get_focus(seat); + if (view == current) { + return; + } + /* Focus that client if the button was pressed and it has no open dialogs. */ - if (view && !view_has_children(server, view)) { + if (view && !view_is_transient_for(current, view)) { seat_set_focus(seat, view); } } diff --git a/view.c b/view.c index a5a81e5..b7f7c9a 100644 --- a/view.c +++ b/view.c @@ -38,15 +38,8 @@ view_is_primary(struct cg_view *view) } bool -view_has_children(struct cg_server *server, struct cg_view *parent) -{ - struct cg_view *child; - wl_list_for_each(child, &server->views, link) { - if (parent != child && parent->impl->is_parent(parent, child)) { - return true; - } - } - return false; +view_is_transient_for(struct cg_view *child, struct cg_view *parent) { + return child->impl->is_transient_for(child, parent); } void diff --git a/view.h b/view.h index b613c07..364afc2 100644 --- a/view.h +++ b/view.h @@ -35,7 +35,7 @@ struct cg_view_impl { char *(*get_title)(struct cg_view *view); void (*get_geometry)(struct cg_view *view, int *width_out, int *height_out); bool (*is_primary)(struct cg_view *view); - bool (*is_parent)(struct cg_view *parent, struct cg_view *child); + bool (*is_transient_for)(struct cg_view *child, struct cg_view *parent); void (*activate)(struct cg_view *view, bool activate); void (*maximize)(struct cg_view *view, int output_width, int output_height); void (*destroy)(struct cg_view *view); @@ -47,7 +47,7 @@ struct cg_view_impl { char *view_get_title(struct cg_view *view); bool view_is_primary(struct cg_view *view); -bool view_has_children(struct cg_server *server, struct cg_view *view); +bool view_is_transient_for(struct cg_view *child, struct cg_view *parent); void view_activate(struct cg_view *view, bool activate); void view_position(struct cg_view *view); void view_for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data); diff --git a/xdg_shell.c b/xdg_shell.c index 0444a1e..b2fdc9c 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -51,14 +51,22 @@ is_primary(struct cg_view *view) } static bool -is_parent(struct cg_view *parent, struct cg_view *child) +is_transient_for(struct cg_view *child, struct cg_view *parent) { - if (child->type != CAGE_XDG_SHELL_VIEW) { + if (parent->type != CAGE_XDG_SHELL_VIEW) { return false; } - struct cg_xdg_shell_view *_parent = xdg_shell_view_from_view(parent); struct cg_xdg_shell_view *_child = xdg_shell_view_from_view(child); - return _child->xdg_surface->toplevel->parent == _parent->xdg_surface; + struct wlr_xdg_surface *xdg_surface = _child->xdg_surface; + struct cg_xdg_shell_view *_parent = xdg_shell_view_from_view(parent); + struct wlr_xdg_surface *parent_xdg_surface = _parent->xdg_surface; + while (xdg_surface) { + if (xdg_surface->toplevel->parent == parent_xdg_surface) { + return true; + } + xdg_surface = xdg_surface->toplevel->parent; + } + return false; } static void @@ -133,7 +141,7 @@ static const struct cg_view_impl xdg_shell_view_impl = { .get_title = get_title, .get_geometry = get_geometry, .is_primary = is_primary, - .is_parent = is_parent, + .is_transient_for = is_transient_for, .activate = activate, .maximize = maximize, .destroy = destroy, diff --git a/xwayland.c b/xwayland.c index b8317c9..57839e2 100644 --- a/xwayland.c +++ b/xwayland.c @@ -47,14 +47,22 @@ is_primary(struct cg_view *view) } static bool -is_parent(struct cg_view *parent, struct cg_view *child) +is_transient_for(struct cg_view *child, struct cg_view *parent) { - if (child->type != CAGE_XWAYLAND_VIEW) { + if (parent->type != CAGE_XDG_SHELL_VIEW) { return false; } - struct cg_xwayland_view *_parent = xwayland_view_from_view(parent); struct cg_xwayland_view *_child = xwayland_view_from_view(child); - return _child->xwayland_surface->parent == _parent->xwayland_surface; + struct wlr_xwayland_surface *xwayland_surface = _child->xwayland_surface; + struct cg_xwayland_view *_parent = xwayland_view_from_view(parent); + struct wlr_xwayland_surface *parent_xwayland_surface = _parent->xwayland_surface; + while (xwayland_surface) { + if (xwayland_surface->parent == parent_xwayland_surface) { + return true; + } + xwayland_surface = xwayland_surface->parent; + } + return false; } static void @@ -128,7 +136,7 @@ static const struct cg_view_impl xwayland_view_impl = { .get_title = get_title, .get_geometry = get_geometry, .is_primary = is_primary, - .is_parent = is_parent, + .is_transient_for = is_transient_for, .activate = activate, .maximize = maximize, .destroy = destroy,