From 623a08e14fa1434afe5cd0aa0c1b0f5789baa12d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 18:47:40 -0400 Subject: Identify topmost interactive layer post-arrange --- sway/desktop/layer_shell.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'sway') diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index c18f51c7..a187432b 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -187,6 +187,28 @@ void arrange_layers(struct sway_output *output) { &usable_area, false); arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &usable_area, false); + + // Find topmost keyboard interactive layer, if such a layer exists + uint32_t layers_above_shell[] = { + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, + }; + size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]); + struct sway_layer_surface *layer, *topmost = NULL; + for (size_t i = 0; i < nlayers; ++i) { + wl_list_for_each_reverse(layer, + &output->layers[layers_above_shell[i]], link) { + if (layer->layer_surface->current.keyboard_interactive) { + topmost = layer; + break; + } + } + if (topmost != NULL) { + break; + } + } + + wlr_log(L_DEBUG, "topmost layer: %p", topmost); } static void handle_output_destroy(struct wl_listener *listener, void *data) { -- cgit v1.2.3 From 56078edd65d05c1db1aa5d6e72134499e907063d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 21:07:46 -0400 Subject: Give exclusive focus to layers above shell layer --- include/sway/input/seat.h | 7 +++++++ sway/desktop/layer_shell.c | 7 ++++++- sway/input/seat.c | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) (limited to 'sway') diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index c780a52b..137fcd22 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -1,6 +1,7 @@ #ifndef _SWAY_INPUT_SEAT_H #define _SWAY_INPUT_SEAT_H +#include #include #include "sway/input/input-manager.h" @@ -28,6 +29,9 @@ struct sway_seat { bool has_focus; struct wl_list focus_stack; // list of containers in focus order + // If the focused layer is set, views cannot receive keyboard focus + struct wlr_layer_surface *focused_layer; + struct wl_listener focus_destroy; struct wl_listener new_container; @@ -57,6 +61,9 @@ void seat_set_focus(struct sway_seat *seat, struct sway_container *container); void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp); +void seat_set_focus_layer(struct sway_seat *seat, + struct wlr_layer_surface *layer); + struct sway_container *seat_get_focus(struct sway_seat *seat); /** diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index a187432b..3c7b45f7 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -7,6 +7,8 @@ #include #include #include +#include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "sway/layers.h" #include "sway/output.h" #include "sway/server.h" @@ -208,7 +210,10 @@ void arrange_layers(struct sway_output *output) { } } - wlr_log(L_DEBUG, "topmost layer: %p", topmost); + struct sway_seat *seat; + wl_list_for_each(seat, &input_manager->seats, link) { + seat_set_focus_layer(seat, topmost ? topmost->layer_surface : NULL); + } } static void handle_output_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/input/seat.c b/sway/input/seat.c index c41f7b2e..cf519a82 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -352,8 +352,11 @@ void seat_configure_xcursor(struct sway_seat *seat) { void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { - struct sway_container *last_focus = seat_get_focus(seat); + if (seat->focused_layer) { + return; + } + struct sway_container *last_focus = seat_get_focus(seat); if (container && last_focus == container) { return; } @@ -419,6 +422,37 @@ void seat_set_focus(struct sway_seat *seat, seat_set_focus_warp(seat, container, true); } +void seat_set_focus_layer(struct sway_seat *seat, + struct wlr_layer_surface *layer) { + if (!layer) { + seat->focused_layer = NULL; + return; + } + if (seat->focused_layer == layer) { + return; + } + if (seat->has_focus) { + struct sway_container *focus = seat_get_focus(seat); + if (focus->type == C_VIEW) { + wlr_seat_keyboard_clear_focus(seat->wlr_seat); + view_set_activated(focus->sway_view, false); + } + } + if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { + seat->focused_layer = layer; + } + struct wlr_keyboard *keyboard = + wlr_seat_get_keyboard(seat->wlr_seat); + if (keyboard) { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + layer->surface, keyboard->keycodes, + keyboard->num_keycodes, &keyboard->modifiers); + } else { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, + layer->surface, NULL, 0, NULL); + } +} + struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { return seat_get_focus_by_type(seat, container, C_TYPES); -- cgit v1.2.3 From 0bf3b88019b038f7465b5e333742baacfe0a9eed Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 21:17:16 -0400 Subject: Give layer shells under the shell layer focus --- sway/input/cursor.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'sway') diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 97b4473c..9229e92d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -180,13 +180,18 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { double sx, sy; struct sway_container *cont = container_at_cursor(cursor, &surface, &sx, &sy); + if (surface && wlr_surface_is_layer_surface(surface)) { + struct wlr_layer_surface *layer = + wlr_layer_surface_from_wlr_surface(surface); + if (layer->current.keyboard_interactive) { + seat_set_focus_layer(cursor->seat, layer); + return; + } + } // Avoid moving keyboard focus from a surface that accepts it to one // that does not unless the change would move us to a new workspace. // // This prevents, for example, losing focus when clicking on swaybar. - // - // TODO: Replace this condition with something like - // !surface_accepts_keyboard_input if (surface && cont && cont->type != C_VIEW) { struct sway_container *new_ws = cont; if (new_ws && new_ws->type != C_WORKSPACE) { -- cgit v1.2.3 From 1e549230db6b088aae2733e1084c7f953ff88abd Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Tue, 3 Apr 2018 14:37:00 -0400 Subject: Fix name generation for workspace number --- sway/tree/workspace.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'sway') diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c629f1f1..d6fd7c70 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -87,6 +87,24 @@ char *workspace_next_name(const char *output_name) { continue; } + // If the command is workspace number , isolate the name + if (strncmp(_target, "number ", strlen("number ")) == 0) { + size_t length = strlen(_target) - strlen("number ") + 1; + char *temp = malloc(length); + strncpy(temp, _target + strlen("number "), length - 1); + temp[length - 1] = '\0'; + free(_target); + _target = temp; + wlr_log(L_DEBUG, "Isolated name from workspace number: '%s'", _target); + + // Make sure the workspace number doesn't already exist + if (workspace_by_number(_target)) { + free(_target); + free(dup); + continue; + } + } + // Make sure that the workspace doesn't already exist if (workspace_by_name(_target)) { free(_target); -- cgit v1.2.3 From 5cd9457247146efe0bcbcae890968acb4716c667 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 18:47:04 -0400 Subject: Send enter event to layer shell surfaces --- sway/desktop/layer_shell.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sway') diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 3c7b45f7..663ec7ba 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -278,6 +278,8 @@ static void handle_map(struct wl_listener *listener, void *data) { sway_layer, map); struct sway_output *output = sway_layer->layer_surface->output->data; wlr_output_damage_add_box(output->damage, &sway_layer->geo); + wlr_surface_send_enter(sway_layer->layer_surface->surface, + sway_layer->layer_surface->output); } static void handle_unmap(struct wl_listener *listener, void *data) { -- cgit v1.2.3 From c0554d23d3d89b92b6a871807771b2c2e1f29f61 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 19:34:56 -0400 Subject: Fix rendering with multiple outputs --- sway/desktop/output.c | 40 ++++++++++++++++++---------------------- sway/tree/layout.c | 16 ++++++++++------ 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'sway') diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 10ed1f6d..4b407f41 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -46,10 +46,7 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, */ static bool surface_intersect_output(struct wlr_surface *surface, struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, - double lx, double ly, float rotation, struct wlr_box *box) { - double ox = lx, oy = ly; - wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); - + double ox, double oy, float rotation, struct wlr_box *box) { if (box != NULL) { box->x = ox * wlr_output->scale; box->y = oy * wlr_output->scale; @@ -58,7 +55,7 @@ static bool surface_intersect_output(struct wlr_surface *surface, } struct wlr_box layout_box = { - .x = lx, .y = ly, + .x = wlr_output->lx + ox, .y = wlr_output->ly + oy, .width = surface->current->width, .height = surface->current->height, }; wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); @@ -67,7 +64,7 @@ static bool surface_intersect_output(struct wlr_surface *surface, static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, - double lx, double ly, float rotation) { + double ox, double oy, float rotation) { struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); @@ -79,7 +76,7 @@ static void render_surface(struct wlr_surface *surface, struct wlr_box box; bool intersects = surface_intersect_output(surface, layout, wlr_output, - lx, ly, rotation, &box); + ox, oy, rotation, &box); if (intersects) { float matrix[9]; enum wl_output_transform transform = @@ -102,7 +99,7 @@ static void render_surface(struct wlr_surface *surface, surface->current->width, surface->current->height, rotation); render_surface(subsurface->surface, wlr_output, when, - lx + sx, ly + sy, rotation); + ox + sx, oy + sy, rotation); } } @@ -200,9 +197,7 @@ static void render_view(struct sway_container *view, void *data) { } } -static void render_layer(struct sway_output *output, - const struct wlr_box *output_layout_box, - struct timespec *when, +static void render_layer(struct sway_output *output, struct timespec *when, struct wl_list *layer) { struct sway_layer_surface *sway_layer; wl_list_for_each(sway_layer, layer, link) { @@ -234,14 +229,15 @@ static void render_output(struct sway_output *output, struct timespec *when, float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); - struct wlr_output_layout *layout = root_container.sway_root->output_layout; + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; const struct wlr_box *output_box = - wlr_output_layout_get_box(layout, wlr_output); + wlr_output_layout_get_box(output_layout, wlr_output); - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *focus = @@ -251,7 +247,7 @@ static void render_output(struct sway_output *output, struct timespec *when, focus = output->swayc->children->items[0]; } struct sway_container *workspace = focus->type == C_WORKSPACE ? - focus : container_parent(focus, C_WORKSPACE); + focus : container_parent(focus, C_WORKSPACE); struct render_data rdata = { .output = output, @@ -285,10 +281,10 @@ static void render_output(struct sway_output *output, struct timespec *when, } // TODO: Consider revising this when fullscreen windows are supported - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); - render_layer(output, output_box, when, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); + render_layer(output, when, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); renderer_end: wlr_renderer_end(renderer); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 95a84d12..617350d9 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -19,10 +19,14 @@ struct sway_container root_container; -static void output_layout_change_notify(struct wl_listener *listener, +static void output_layout_handle_change(struct wl_listener *listener, void *data) { - struct wlr_box *layout_box = wlr_output_layout_get_box( - root_container.sway_root->output_layout, NULL); + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; + const struct wlr_box *layout_box = + wlr_output_layout_get_box(output_layout, NULL); + root_container.x = layout_box->x; + root_container.y = layout_box->y; root_container.width = layout_box->width; root_container.height = layout_box->height; @@ -34,8 +38,8 @@ static void output_layout_change_notify(struct wl_listener *listener, } struct sway_output *output = output_container->sway_output; - struct wlr_box *output_box = wlr_output_layout_get_box( - root_container.sway_root->output_layout, output->wlr_output); + const struct wlr_box *output_box = + wlr_output_layout_get_box(output_layout, output->wlr_output); if (!output_box) { continue; } @@ -62,7 +66,7 @@ void layout_init(void) { wl_signal_init(&root_container.sway_root->events.new_container); root_container.sway_root->output_layout_change.notify = - output_layout_change_notify; + output_layout_handle_change; wl_signal_add(&root_container.sway_root->output_layout->events.change, &root_container.sway_root->output_layout_change); } -- cgit v1.2.3 From f3ef1da750d8da4b68869fa98fb8eceb8dda9858 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 3 Apr 2018 21:06:13 -0400 Subject: Fix wrong output container coordinates --- sway/config/output.c | 12 ++++++------ sway/tree/container.c | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'sway') diff --git a/sway/config/output.c b/sway/config/output.c index b4e56efa..6d832cbc 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -123,11 +123,13 @@ void terminate_swaybg(pid_t pid) { void apply_output_config(struct output_config *oc, struct sway_container *output) { assert(output->type == C_OUTPUT); + struct wlr_output_layout *output_layout = + root_container.sway_root->output_layout; struct wlr_output *wlr_output = output->sway_output->wlr_output; + if (oc && oc->enabled == 0) { - wlr_output_layout_remove(root_container.sway_root->output_layout, - wlr_output); container_output_destroy(output); + wlr_output_layout_remove(output_layout, wlr_output); return; } @@ -148,11 +150,9 @@ void apply_output_config(struct output_config *oc, struct sway_container *output // Find position for it if (oc && (oc->x != -1 || oc->y != -1)) { wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); - wlr_output_layout_add(root_container.sway_root->output_layout, - wlr_output, oc->x, oc->y); + wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); } else { - wlr_output_layout_add_auto(root_container.sway_root->output_layout, - wlr_output); + wlr_output_layout_add_auto(output_layout, wlr_output); } if (!oc || !oc->background) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 4db93ce8..c686401c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -160,8 +160,11 @@ struct sway_container *container_output_create( return NULL; } - apply_output_config(oc, output); + // Insert the child before applying config so that the container coordinates + // get updated container_add_child(&root_container, output); + apply_output_config(oc, output); + load_swaybars(); // Create workspace -- cgit v1.2.3