void desktop_focus_view(struct view *view, bool raise);
void desktop_arrange_all_views(struct server *server);
void desktop_focus_output(struct output *output);
-struct view *desktop_topmost_mapped_view(struct server *server);
+struct view *desktop_topmost_focusable_view(struct server *server);
enum lab_cycle_dir {
LAB_CYCLE_DIR_NONE,
*/
struct view *desktop_cycle_view(struct server *server, struct view *start_view,
enum lab_cycle_dir dir);
-void desktop_focus_topmost_mapped_view(struct server *server);
+void desktop_focus_topmost_view(struct server *server);
void keyboard_cancel_keybind_repeat(struct keyboard *keyboard);
void keyboard_key_notify(struct wl_listener *listener, void *data);
struct view *(*get_root)(struct view *self);
void (*append_children)(struct view *self, struct wl_array *children);
struct view_size_hints (*get_size_hints)(struct view *self);
+ /* if not implemented, view is assumed to want focus */
+ bool (*wants_focus)(struct view *self);
};
struct view {
}
struct view *
-desktop_topmost_mapped_view(struct server *server)
+desktop_topmost_focusable_view(struct server *server)
{
struct view *view;
struct wl_list *node_list;
continue;
}
view = node_view_from_node(node);
- if (view->mapped) {
+ if (view->mapped && view_isfocusable(view)) {
return view;
}
}
}
void
-desktop_focus_topmost_mapped_view(struct server *server)
+desktop_focus_topmost_view(struct server *server)
{
- struct view *view = desktop_topmost_mapped_view(server);
+ struct view *view = desktop_topmost_focusable_view(server);
if (view) {
desktop_focus_view(view, /*raise*/ true);
} else {
{
if (!layer) {
seat->focused_layer = NULL;
- desktop_focus_topmost_mapped_view(seat->server);
+ desktop_focus_topmost_view(seat->server);
return;
}
seat_focus(seat, layer->surface);
{
struct session_lock *lock = wl_container_of(listener, lock, unlock);
session_lock_destroy(lock);
- desktop_focus_topmost_mapped_view(g_server);
+ desktop_focus_topmost_view(g_server);
}
static void
if (!view->surface) {
return false;
}
+ if (view->impl->wants_focus && !view->impl->wants_focus(view)) {
+ return false;
+ }
return (view->mapped || view->minimized);
}
if (update_focus) {
struct view *view = server->focused_view;
if (!view || !view_is_always_on_top(view)) {
- desktop_focus_topmost_mapped_view(server);
+ desktop_focus_topmost_view(server);
}
}
view->mapped = false;
wlr_scene_node_set_enabled(&view->scene_tree->node, false);
wl_list_remove(&view->commit.link);
- desktop_focus_topmost_mapped_view(view->server);
+ desktop_focus_topmost_view(view->server);
}
}
* to the topmost mapped view. This fixes dmenu
* not giving focus back when closed with ESC.
*/
- desktop_focus_topmost_mapped_view(server);
+ desktop_focus_topmost_view(server);
}
static void
* Validate that the unmanaged surface trying to grab focus is actually
* a child of the topmost mapped view before granting the request.
*/
- struct view *view = desktop_topmost_mapped_view(server);
+ struct view *view = desktop_topmost_focusable_view(server);
if (view && view->type == LAB_XWAYLAND_VIEW) {
struct wlr_xwayland_surface *surf =
wlr_xwayland_surface_from_wlr_surface(view->surface);
};
}
+static bool
+xwayland_view_wants_focus(struct view *view)
+{
+ xcb_icccm_wm_hints_t *hints = xwayland_surface_from_view(view)->hints;
+ if (!hints) {
+ return true;
+ }
+ return (bool)hints->input;
+}
+
static struct wlr_xwayland_surface *
top_parent_of(struct view *view)
{
view->mapped = false;
wl_list_remove(&view->commit.link);
wlr_scene_node_set_enabled(&view->scene_tree->node, false);
- desktop_focus_topmost_mapped_view(view->server);
+ desktop_focus_topmost_view(view->server);
/*
* If the view was explicitly unmapped by the client (rather
.get_root = xwayland_view_get_root,
.append_children = xwayland_view_append_children,
.get_size_hints = xwayland_view_get_size_hints,
+ .wants_focus = xwayland_view_wants_focus,
};
void