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>
This commit is contained in:
Jonas Ådahl 2019-02-19 17:45:26 +01:00 committed by Daniel Stone
parent 28b3529ca8
commit cc3d30c28b
4 changed files with 80 additions and 5 deletions

View File

@ -1386,18 +1386,75 @@ handle_pointer_focus(struct wl_listener *listener, void *data)
weston_desktop_client_ping(client);
}
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

View File

@ -216,6 +216,14 @@ struct weston_size
weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface);
struct weston_size
weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface);
struct weston_desktop_surface *
weston_desktop_surface_get_parent(struct weston_desktop_surface *surface);
void
weston_desktop_surface_foreach_child(struct weston_desktop_surface *surface,
void (* callback)(struct weston_desktop_surface *child,
void *user_data),
void *user_data);
bool
weston_desktop_window_menu_supported(struct weston_desktop *desktop);

View File

@ -195,8 +195,6 @@ const struct weston_desktop_surface_implementation *
weston_desktop_surface_get_implementation(struct weston_desktop_surface *surface);
void *
weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface);
struct weston_desktop_surface *
weston_desktop_surface_get_parent(struct weston_desktop_surface *surface);
bool
weston_desktop_surface_get_grab(struct weston_desktop_surface *surface);

View File

@ -569,7 +569,7 @@ weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *su
return surface->implementation_data;
}
struct weston_desktop_surface *
WL_EXPORT struct weston_desktop_surface *
weston_desktop_surface_get_parent(struct weston_desktop_surface *surface)
{
return surface->parent;
@ -878,3 +878,15 @@ weston_desktop_surface_popup_dismiss(struct weston_desktop_surface *surface)
wl_list_init(&surface->grab_link);
weston_desktop_surface_close(surface);
}
WL_EXPORT void
weston_desktop_surface_foreach_child(struct weston_desktop_surface *surface,
void (* callback)(struct weston_desktop_surface *child,
void *user_data),
void *user_data)
{
struct weston_desktop_surface *child;
wl_list_for_each(child, &surface->children_list, children_link)
callback(child, user_data);
}