From a26fd5a75b4eff7d9efe0cc3f3058f55a64a2fc1 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sat, 31 Oct 2020 15:09:13 +0000 Subject: [PATCH] layers: handle top layer unmap/destroy better On losing top layer focus, set focus on topmost mapped view. --- include/labwc.h | 5 +++++ include/layers.h | 1 + src/layers.c | 29 +++++++++++++++++++++++++++-- src/seat.c | 14 ++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index 1c58677f..46121507 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,9 @@ struct seat { struct wlr_cursor *cursor; struct wlr_xcursor_manager *xcursor_manager; + /* if set, views cannot receive focus */ + struct wlr_layer_surface_v1 *focused_layer; + struct wl_list inputs; struct wl_listener new_input; @@ -244,6 +248,7 @@ void keyboard_init(struct seat *seat); void seat_init(struct server *server); void seat_finish(struct server *server); void seat_focus_surface(struct seat *seat, struct wlr_surface *surface); +void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer); void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges); diff --git a/include/layers.h b/include/layers.h index d47be386..5bf2f6a6 100644 --- a/include/layers.h +++ b/include/layers.h @@ -12,6 +12,7 @@ struct lab_layer_surface { struct wl_listener destroy; struct wl_listener map; + struct wl_listener unmap; struct wl_listener surface_commit; struct wl_listener output_destroy; diff --git a/src/layers.c b/src/layers.c index d91719bf..5041e4b1 100644 --- a/src/layers.c +++ b/src/layers.c @@ -220,9 +220,12 @@ arrange_layers(struct output *output) break; } } + struct seat *seat = &output->server->seat; if (topmost) { - seat_focus_surface(&output->server->seat, - topmost->layer_surface->surface); + seat_set_focus_layer(seat, topmost->layer_surface); + } else if (seat->focused_layer && + !seat->focused_layer->current.keyboard_interactive) { + seat_set_focus_layer(seat, NULL); } } @@ -257,11 +260,23 @@ surface_commit_notify(struct wl_listener *listener, void *data) arrange_layers(output_from_wlr_output(layer->server, wlr_output)); } +static void +unmap(struct lab_layer_surface *layer) +{ + struct seat *seat = &layer->server->seat; + if (seat->focused_layer == layer->layer_surface) { + seat_set_focus_layer(seat, NULL); + } +} + static void destroy_notify(struct wl_listener *listener, void *data) { struct lab_layer_surface *layer = wl_container_of( listener, layer, destroy); + if (layer->layer_surface->mapped) { + unmap(layer); + } wl_list_remove(&layer->link); wl_list_remove(&layer->destroy.link); wl_list_remove(&layer->map.link); @@ -275,6 +290,13 @@ destroy_notify(struct wl_listener *listener, void *data) free(layer); } +static void +unmap_notify(struct wl_listener *listener, void *data) +{ + struct lab_layer_surface *l = wl_container_of(listener, l, unmap); + unmap(l); +} + static void map_notify(struct wl_listener *listener, void *data) { @@ -322,6 +344,9 @@ new_layer_surface_notify(struct wl_listener *listener, void *data) surface->map.notify = map_notify; wl_signal_add(&layer_surface->events.map, &surface->map); + surface->unmap.notify = unmap_notify; + wl_signal_add(&layer_surface->events.unmap, &surface->unmap); + wl_list_insert(&output->layers[layer_surface->client_pending.layer], &surface->link); /* diff --git a/src/seat.c b/src/seat.c index dcfff4b7..d4242634 100644 --- a/src/seat.c +++ b/src/seat.c @@ -124,3 +124,17 @@ seat_focus_surface(struct seat *seat, struct wlr_surface *surface) wlr_seat_keyboard_notify_enter(seat->seat, surface, kb->keycodes, kb->num_keycodes, &kb->modifiers); } + +void +seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer) +{ + if (!layer) { + seat->focused_layer = NULL; + desktop_focus_topmost_mapped_view(seat->server); + return; + } + seat_focus_surface(seat, layer->surface); + if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { + seat->focused_layer = layer; + } +}