diff options
author | Jonas Ådahl <jadahl@gmail.com> | 2019-02-19 17:45:26 +0100 |
---|---|---|
committer | Daniel Stone <daniels@collabora.com> | 2023-03-30 17:14:29 +0000 |
commit | cc3d30c28bb645a1a4e48814346e052115a74210 (patch) | |
tree | c8cfad37349519a7a3aade47028f02ada006efbe /desktop-shell | |
parent | 28b3529ca8bf592d2a2cdfbd6562cb8c92dd9f63 (diff) | |
download | weston-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.c | 61 |
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 |