summaryrefslogtreecommitdiff
path: root/desktop-shell
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2019-02-19 17:45:26 +0100
committerDaniel Stone <daniels@collabora.com>2023-03-30 17:14:29 +0000
commitcc3d30c28bb645a1a4e48814346e052115a74210 (patch)
treec8cfad37349519a7a3aade47028f02ada006efbe /desktop-shell
parent28b3529ca8bf592d2a2cdfbd6562cb8c92dd9f63 (diff)
downloadweston-cc3d30c28bb645a1a4e48814346e052115a74210.tar.gz
shell: Keep window 'activated' state if child has focus
Popups should have keyboard focus when active, but the toplevel window should still appear "active". Make sure this is the case by changing the "active" tracking to see whether any child surface has keyboard focus. Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Diffstat (limited to 'desktop-shell')
-rw-r--r--desktop-shell/shell.c61
1 files changed, 59 insertions, 2 deletions
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 9140bed2..c7ab2256 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -1387,17 +1387,74 @@ handle_pointer_focus(struct wl_listener *listener, void *data)
}
static void
+has_keyboard_focused_child_callback(struct weston_desktop_surface *surface,
+ void *user_data);
+
+static void
+has_keyboard_focused_child_callback(struct weston_desktop_surface *surface,
+ void *user_data)
+{
+ struct weston_surface *es = weston_desktop_surface_get_surface(surface);
+ struct shell_surface *shsurf = get_shell_surface(es);
+ bool *has_keyboard_focus = user_data;
+
+ if (shsurf->focus_count > 0) {
+ *has_keyboard_focus = true;
+ return;
+ }
+
+ weston_desktop_surface_foreach_child(shsurf->desktop_surface,
+ has_keyboard_focused_child_callback,
+ &has_keyboard_focus);
+}
+
+static bool
+has_keyboard_focused_child(struct shell_surface *shsurf)
+{
+ bool has_keyboard_focus = false;
+
+ if (shsurf->focus_count > 0)
+ return true;
+
+ weston_desktop_surface_foreach_child(shsurf->desktop_surface,
+ has_keyboard_focused_child_callback,
+ &has_keyboard_focus);
+
+ return has_keyboard_focus;
+}
+
+static void
+sync_surface_activated_state(struct shell_surface *shsurf)
+{
+ struct weston_desktop_surface *surface = shsurf->desktop_surface;
+ struct weston_desktop_surface *parent;
+ struct weston_surface *parent_surface;
+
+ parent = weston_desktop_surface_get_parent(surface);
+ if (parent) {
+ parent_surface = weston_desktop_surface_get_surface(parent);
+ sync_surface_activated_state(get_shell_surface(parent_surface));
+ return;
+ }
+
+ if (has_keyboard_focused_child(shsurf))
+ weston_desktop_surface_set_activated(surface, true);
+ else
+ weston_desktop_surface_set_activated(surface, false);
+}
+
+static void
shell_surface_deactivate(struct shell_surface *shsurf)
{
if (--shsurf->focus_count == 0)
- weston_desktop_surface_set_activated(shsurf->desktop_surface, false);
+ sync_surface_activated_state(shsurf);
}
static void
shell_surface_activate(struct shell_surface *shsurf)
{
if (shsurf->focus_count++ == 0)
- weston_desktop_surface_set_activated(shsurf->desktop_surface, true);
+ sync_surface_activated_state(shsurf);
}
/* The surface will be inserted into the list immediately after the link