mirror of
https://github.com/swaywm/sway.git
synced 2024-11-13 05:54:11 +01:00
Give focus to another swaylock surface when output is disconnected
* Have multiple outputs * Launch swaylock * Unplug an output (possibly has to be the last "connected" one) * The swaylock surface on the remaining output would not respond to key events This was happening because when the output destroys, focus was not given to the other swaylock surface. This patch makes focus be transferred to another surface owned by the same Wayland client, but only if input was inhibited by the surface being destroyed, and only if it's in the overlay layer. I figure it's best to be overly specific and relax the requirements later if needed. This patch removes a check in seat_set_focus_surface which was preventing focus from being passed from a layer surface to any other surface. I don't know of a use case for this check, but it's possible that this change could produce issues.
This commit is contained in:
parent
681ed1826d
commit
32cb631143
@ -216,12 +216,48 @@ void arrange_layers(struct sway_output *output) {
|
||||
}
|
||||
}
|
||||
|
||||
static struct sway_layer_surface *find_any_layer_by_client(
|
||||
struct wl_client *client, struct wlr_output *ignore_output) {
|
||||
for (int i = 0; i < root->outputs->length; ++i) {
|
||||
struct sway_output *output = root->outputs->items[i];
|
||||
if (output->wlr_output == ignore_output) {
|
||||
continue;
|
||||
}
|
||||
// For now we'll only check the overlay layer
|
||||
struct sway_layer_surface *lsurface;
|
||||
wl_list_for_each(lsurface,
|
||||
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) {
|
||||
struct wl_resource *resource = lsurface->layer_surface->resource;
|
||||
if (wl_resource_get_client(resource) == client) {
|
||||
return lsurface;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_surface *sway_layer =
|
||||
wl_container_of(listener, sway_layer, output_destroy);
|
||||
// Determine if this layer is being used by an exclusive client. If it is,
|
||||
// try and find another layer owned by this client to pass focus to.
|
||||
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
|
||||
struct wl_client *client =
|
||||
wl_resource_get_client(sway_layer->layer_surface->resource);
|
||||
bool set_focus = seat->exclusive_client == client;
|
||||
|
||||
wl_list_remove(&sway_layer->output_destroy.link);
|
||||
wl_list_remove(&sway_layer->link);
|
||||
wl_list_init(&sway_layer->link);
|
||||
|
||||
if (set_focus) {
|
||||
struct sway_layer_surface *layer =
|
||||
find_any_layer_by_client(client, sway_layer->layer_surface->output);
|
||||
if (layer) {
|
||||
seat_set_focus_layer(seat, layer->layer_surface);
|
||||
}
|
||||
}
|
||||
|
||||
sway_layer->layer_surface->output = NULL;
|
||||
wlr_layer_surface_v1_close(sway_layer->layer_surface);
|
||||
}
|
||||
|
@ -800,9 +800,6 @@ void seat_set_focus_workspace(struct sway_seat *seat,
|
||||
|
||||
void seat_set_focus_surface(struct sway_seat *seat,
|
||||
struct wlr_surface *surface, bool unfocus) {
|
||||
if (seat->focused_layer != NULL) {
|
||||
return;
|
||||
}
|
||||
if (seat->has_focus && unfocus) {
|
||||
struct sway_node *focus = seat_get_focus(seat);
|
||||
seat_send_unfocus(focus, seat);
|
||||
|
Loading…
Reference in New Issue
Block a user