Skip to content
Snippets Groups Projects

kiosk-shell: Separate (keyboard) input focus from xdg-shell toplevel window activation

Merged Marius Vlad requested to merge mvlad/weston:fix-desktop-shell-top-level-activation into main
1 file
+ 44
21
Compare changes
  • Side-by-side
  • Inline
+ 92
65
@@ -57,14 +57,33 @@ get_kiosk_shell_seat(struct weston_seat *seat)
{
struct wl_listener *listener;
if (!seat)
return NULL;
listener = wl_signal_get(&seat->destroy_signal,
kiosk_shell_seat_handle_destroy);
assert(listener != NULL);
if (!listener)
return NULL;
return container_of(listener,
struct kiosk_shell_seat, seat_destroy_listener);
}
static struct weston_seat *
get_kiosk_shell_first_seat(struct kiosk_shell *shell)
{
struct wl_list *node;
struct weston_compositor *compositor = shell->compositor;
if (wl_list_empty(&compositor->seat_list))
return NULL;
node = compositor->seat_list.next;
return container_of(node, struct weston_seat, link);
}
static void
transform_handler(struct wl_listener *listener, void *data)
{
@@ -343,42 +362,44 @@ kiosk_shell_surface_create(struct kiosk_shell *shell,
return shsurf;
}
/*
* kiosk_shell_seat
*/
static void
kiosk_shell_seat_handle_keyboard_focus(struct wl_listener *listener, void *data)
kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_seat *kiosk_seat,
uint32_t activate_flags)
{
struct weston_keyboard *keyboard = data;
struct kiosk_shell_seat *shseat = get_kiosk_shell_seat(keyboard->seat);
if (shseat->focused_surface) {
struct kiosk_shell_surface *shsurf =
get_kiosk_shell_surface(shseat->focused_surface);
if (shsurf && --shsurf->focus_count == 0)
weston_desktop_surface_set_activated(shsurf->desktop_surface,
false);
}
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
struct weston_surface *surface =
weston_desktop_surface_get_surface(dsurface);
/* keyboard focus */
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
shseat->focused_surface = weston_surface_get_main_surface(keyboard->focus);
/* xdg-shell deactivation if there's a focused one */
if (kiosk_seat->focused_surface) {
struct kiosk_shell_surface *current_focus =
get_kiosk_shell_surface(kiosk_seat->focused_surface);
struct weston_desktop_surface *dsurface_focus;
assert(current_focus);
if (shseat->focused_surface) {
struct kiosk_shell_surface *shsurf =
get_kiosk_shell_surface(shseat->focused_surface);
if (shsurf && shsurf->focus_count++ == 0)
weston_desktop_surface_set_activated(shsurf->desktop_surface,
true);
dsurface_focus = current_focus->desktop_surface;
if (--current_focus->focus_count == 0)
weston_desktop_surface_set_activated(dsurface_focus, false);
}
/* xdg-shell activation for the new one */
kiosk_seat->focused_surface = surface;
if (shsurf->focus_count++ == 0)
weston_desktop_surface_set_activated(dsurface, true);
}
/*
* kiosk_shell_seat
*/
static void
kiosk_shell_seat_destroy(struct kiosk_shell_seat *shseat)
{
wl_list_remove(&shseat->keyboard_focus_listener.link);
wl_list_remove(&shseat->caps_changed_listener.link);
wl_list_remove(&shseat->seat_destroy_listener.link);
wl_list_remove(&shseat->link);
free(shseat);
}
@@ -393,31 +414,17 @@ kiosk_shell_seat_handle_destroy(struct wl_listener *listener, void *data)
kiosk_shell_seat_destroy(shseat);
}
static void
kiosk_shell_seat_handle_caps_changed(struct wl_listener *listener, void *data)
{
struct weston_keyboard *keyboard;
struct kiosk_shell_seat *shseat;
shseat = container_of(listener, struct kiosk_shell_seat,
caps_changed_listener);
keyboard = weston_seat_get_keyboard(shseat->seat);
if (keyboard &&
wl_list_empty(&shseat->keyboard_focus_listener.link)) {
wl_signal_add(&keyboard->focus_signal,
&shseat->keyboard_focus_listener);
} else if (!keyboard) {
wl_list_remove(&shseat->keyboard_focus_listener.link);
wl_list_init(&shseat->keyboard_focus_listener.link);
}
}
static struct kiosk_shell_seat *
kiosk_shell_seat_create(struct kiosk_shell *shell, struct weston_seat *seat)
{
struct kiosk_shell_seat *shseat;
if (wl_list_length(&shell->seat_list) > 0) {
weston_log("WARNING: multiple seats detected. kiosk-shell "
"can not handle multiple seats!\n");
return NULL;
}
shseat = zalloc(sizeof *shseat);
if (!shseat) {
weston_log("no memory to allocate shell seat\n");
@@ -429,14 +436,6 @@ kiosk_shell_seat_create(struct kiosk_shell *shell, struct weston_seat *seat)
shseat->seat_destroy_listener.notify = kiosk_shell_seat_handle_destroy;
wl_signal_add(&seat->destroy_signal, &shseat->seat_destroy_listener);
shseat->keyboard_focus_listener.notify = kiosk_shell_seat_handle_keyboard_focus;
wl_list_init(&shseat->keyboard_focus_listener.link);
shseat->caps_changed_listener.notify = kiosk_shell_seat_handle_caps_changed;
wl_signal_add(&seat->updated_caps_signal,
&shseat->caps_changed_listener);
kiosk_shell_seat_handle_caps_changed(&shseat->caps_changed_listener, NULL);
wl_list_insert(&shell->seat_list, &shseat->link);
return shseat;
@@ -619,13 +618,22 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
* parentage. */
static struct weston_view *
find_focus_successor(struct weston_layer *layer,
struct kiosk_shell_surface *shsurf)
struct kiosk_shell_surface *shsurf,
struct weston_surface *focused_surface)
{
struct kiosk_shell_surface *parent_root =
kiosk_shell_surface_get_parent_root(shsurf);
struct weston_view *top_view = NULL;
struct weston_view *view;
/* we need to take into account that the surface being destroyed it not
* always the same as the focus_surface, which could result in picking
* and *activating* the wrong window, so avoid returning a view for
* that case. A particular case is when a top-level child window, would
* pick a parent window below the focused_surface. */
if (focused_surface != shsurf->view->surface)
return top_view;
wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
struct kiosk_shell_surface *view_shsurf;
struct kiosk_shell_surface *root;
@@ -659,17 +667,27 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
weston_desktop_surface_get_surface(desktop_surface);
struct weston_view *focus_view;
struct weston_seat *seat;
struct kiosk_shell_seat* kiosk_seat;
if (!shsurf)
return;
focus_view = find_focus_successor(&shell->normal_layer, shsurf);
seat = get_kiosk_shell_first_seat(shell);
kiosk_seat = get_kiosk_shell_seat(seat);
if (seat && kiosk_seat) {
focus_view = find_focus_successor(&shell->normal_layer, shsurf,
kiosk_seat->focused_surface);
if (focus_view) {
struct kiosk_shell_surface *focus_shsurf =
get_kiosk_shell_surface(focus_view->surface);
if (focus_view) {
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
struct weston_keyboard *keyboard = seat->keyboard_state;
if (keyboard && keyboard->focus == surface)
weston_view_activate_input(focus_view, seat, 0);
kiosk_shell_surface_activate(focus_shsurf, kiosk_seat,
WESTON_ACTIVATE_FLAG_NONE);
} else {
if (kiosk_seat->focused_surface == surface)
kiosk_seat->focused_surface = NULL;
}
}
@@ -687,6 +705,8 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
bool is_resized;
bool is_fullscreen;
assert(shsurf);
if (surface->width == 0)
return;
@@ -716,15 +736,19 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
}
if (!weston_surface_is_mapped(surface)) {
struct weston_seat *seat;
struct weston_seat *seat =
get_kiosk_shell_first_seat(shsurf->shell);
struct kiosk_shell_seat *kiosk_seat;
weston_layer_entry_insert(&shsurf->shell->normal_layer.view_list,
&shsurf->view->layer_link);
shsurf->view->is_mapped = true;
surface->is_mapped = true;
wl_list_for_each(seat, &shsurf->shell->compositor->seat_list, link)
weston_view_activate_input(shsurf->view, seat, 0);
kiosk_seat = get_kiosk_shell_seat(seat);
if (seat && kiosk_seat)
kiosk_shell_surface_activate(shsurf, kiosk_seat,
WESTON_ACTIVATE_FLAG_NONE);
}
if (!is_fullscreen && (sx != 0 || sy != 0)) {
@@ -916,6 +940,8 @@ kiosk_shell_activate_view(struct kiosk_shell *shell,
weston_surface_get_main_surface(view->surface);
struct kiosk_shell_surface *shsurf =
get_kiosk_shell_surface(main_surface);
struct kiosk_shell_seat *kiosk_seat =
get_kiosk_shell_seat(seat);
if (!shsurf)
return;
@@ -932,7 +958,8 @@ kiosk_shell_activate_view(struct kiosk_shell *shell,
weston_surface_damage(view->surface);
}
weston_view_activate_input(view, seat, flags);
if (kiosk_seat)
kiosk_shell_surface_activate(shsurf, kiosk_seat, flags);
}
static void
Loading