diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-10-03 21:21:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-03 21:21:25 +0200 |
commit | 7fdc557f1e16f14dea080714b3a261daf8f4634e (patch) | |
tree | 2564be2f236c91052227bf2cdf322d620caa18b4 | |
parent | Merge pull request #2757 from RyanDwyer/check-focus-stack-empty (diff) | |
parent | Reenable popup-handling for determining focus (diff) | |
download | sway-7fdc557f1e16f14dea080714b3a261daf8f4634e.tar.gz sway-7fdc557f1e16f14dea080714b3a261daf8f4634e.tar.zst sway-7fdc557f1e16f14dea080714b3a261daf8f4634e.zip |
Merge pull request #2709 from BuJo/feature/raise_floating
raise floating
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/config.h | 1 | ||||
-rw-r--r-- | include/sway/input/cursor.h | 1 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/raise_floating.c | 14 | ||||
-rw-r--r-- | sway/config.c | 1 | ||||
-rw-r--r-- | sway/input/cursor.c | 10 | ||||
-rw-r--r-- | sway/input/seat.c | 29 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway.5.scd | 5 | ||||
-rw-r--r-- | sway/tree/container.c | 34 |
11 files changed, 64 insertions, 34 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 64f707f4..f7fafb96 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -125,6 +125,7 @@ sway_cmd cmd_floating_modifier; | |||
125 | sway_cmd cmd_floating_scroll; | 125 | sway_cmd cmd_floating_scroll; |
126 | sway_cmd cmd_focus; | 126 | sway_cmd cmd_focus; |
127 | sway_cmd cmd_focus_follows_mouse; | 127 | sway_cmd cmd_focus_follows_mouse; |
128 | sway_cmd cmd_raise_floating; | ||
128 | sway_cmd cmd_focus_on_window_activation; | 129 | sway_cmd cmd_focus_on_window_activation; |
129 | sway_cmd cmd_focus_wrapping; | 130 | sway_cmd cmd_focus_wrapping; |
130 | sway_cmd cmd_font; | 131 | sway_cmd cmd_font; |
diff --git a/include/sway/config.h b/include/sway/config.h index 98a18b76..02ace979 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -359,6 +359,7 @@ struct sway_config { | |||
359 | 359 | ||
360 | // Flags | 360 | // Flags |
361 | bool focus_follows_mouse; | 361 | bool focus_follows_mouse; |
362 | bool raise_floating; | ||
362 | bool mouse_warping; | 363 | bool mouse_warping; |
363 | enum focus_wrapping_mode focus_wrapping; | 364 | enum focus_wrapping_mode focus_wrapping; |
364 | bool active; | 365 | bool active; |
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 7ec45120..4d47ab42 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h | |||
@@ -10,6 +10,7 @@ struct sway_cursor { | |||
10 | struct wlr_cursor *cursor; | 10 | struct wlr_cursor *cursor; |
11 | struct { | 11 | struct { |
12 | double x, y; | 12 | double x, y; |
13 | struct sway_node *node; | ||
13 | } previous; | 14 | } previous; |
14 | struct wlr_xcursor_manager *xcursor_manager; | 15 | struct wlr_xcursor_manager *xcursor_manager; |
15 | 16 | ||
diff --git a/sway/commands.c b/sway/commands.c index 72db8ab9..5dd27f7e 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -107,6 +107,7 @@ static struct cmd_handler handlers[] = { | |||
107 | { "new_window", cmd_default_border }, | 107 | { "new_window", cmd_default_border }, |
108 | { "no_focus", cmd_no_focus }, | 108 | { "no_focus", cmd_no_focus }, |
109 | { "output", cmd_output }, | 109 | { "output", cmd_output }, |
110 | { "raise_floating", cmd_raise_floating }, | ||
110 | { "seat", cmd_seat }, | 111 | { "seat", cmd_seat }, |
111 | { "set", cmd_set }, | 112 | { "set", cmd_set }, |
112 | { "show_marks", cmd_show_marks }, | 113 | { "show_marks", cmd_show_marks }, |
diff --git a/sway/commands/raise_floating.c b/sway/commands/raise_floating.c new file mode 100644 index 00000000..930299a1 --- /dev/null +++ b/sway/commands/raise_floating.c | |||
@@ -0,0 +1,14 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "util.h" | ||
5 | |||
6 | struct cmd_results *cmd_raise_floating(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "raise_floating", EXPECTED_EQUAL_TO, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | config->raise_floating = | ||
12 | parse_boolean(argv[0], config->raise_floating); | ||
13 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
14 | } | ||
diff --git a/sway/config.c b/sway/config.c index 048b57de..b56c4f71 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -221,6 +221,7 @@ static void config_defaults(struct sway_config *config) { | |||
221 | 221 | ||
222 | // Flags | 222 | // Flags |
223 | config->focus_follows_mouse = true; | 223 | config->focus_follows_mouse = true; |
224 | config->raise_floating = true; | ||
224 | config->mouse_warping = true; | 225 | config->mouse_warping = true; |
225 | config->focus_wrapping = WRAP_YES; | 226 | config->focus_wrapping = WRAP_YES; |
226 | config->validating = false; | 227 | config->validating = false; |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index afad6f6f..3c62acb9 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -567,15 +567,15 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
567 | struct wlr_surface *surface = NULL; | 567 | struct wlr_surface *surface = NULL; |
568 | double sx, sy; | 568 | double sx, sy; |
569 | 569 | ||
570 | // Find the node beneath the pointer's previous position | 570 | struct sway_node *prev_node = cursor->previous.node; |
571 | struct sway_node *prev_node = node_at_coords(seat, | 571 | struct sway_node *node = node_at_coords(seat, |
572 | cursor->previous.x, cursor->previous.y, &surface, &sx, &sy); | 572 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); |
573 | |||
573 | // Update the stored previous position | 574 | // Update the stored previous position |
574 | cursor->previous.x = cursor->cursor->x; | 575 | cursor->previous.x = cursor->cursor->x; |
575 | cursor->previous.y = cursor->cursor->y; | 576 | cursor->previous.y = cursor->cursor->y; |
577 | cursor->previous.node = node; | ||
576 | 578 | ||
577 | struct sway_node *node = node_at_coords(seat, | ||
578 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | ||
579 | if (node && config->focus_follows_mouse && allow_refocusing) { | 579 | if (node && config->focus_follows_mouse && allow_refocusing) { |
580 | struct sway_node *focus = seat_get_focus(seat); | 580 | struct sway_node *focus = seat_get_focus(seat); |
581 | if (focus && node->type == N_WORKSPACE) { | 581 | if (focus && node->type == N_WORKSPACE) { |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 69bee47e..15c56a43 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -606,6 +606,18 @@ static int handle_urgent_timeout(void *data) { | |||
606 | return 0; | 606 | return 0; |
607 | } | 607 | } |
608 | 608 | ||
609 | static void container_raise_floating(struct sway_container *con) { | ||
610 | // Bring container to front by putting it at the end of the floating list. | ||
611 | struct sway_container *floater = con; | ||
612 | while (floater->parent) { | ||
613 | floater = floater->parent; | ||
614 | } | ||
615 | if (container_is_floating(floater)) { | ||
616 | list_move_to_end(floater->workspace->floating, floater); | ||
617 | node_set_dirty(&floater->workspace->node); | ||
618 | } | ||
619 | } | ||
620 | |||
609 | void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node, | 621 | void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node, |
610 | bool warp, bool notify) { | 622 | bool warp, bool notify) { |
611 | if (seat->focused_layer) { | 623 | if (seat->focused_layer) { |
@@ -733,16 +745,8 @@ void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node, | |||
733 | } | 745 | } |
734 | 746 | ||
735 | // If we've focused a floating container, bring it to the front. | 747 | // If we've focused a floating container, bring it to the front. |
736 | // We do this by putting it at the end of the floating list. | 748 | if (container && config->raise_floating) { |
737 | if (container) { | 749 | container_raise_floating(container); |
738 | struct sway_container *floater = container; | ||
739 | while (floater->parent) { | ||
740 | floater = floater->parent; | ||
741 | } | ||
742 | if (container_is_floating(floater)) { | ||
743 | list_move_to_end(floater->workspace->floating, floater); | ||
744 | node_set_dirty(&floater->workspace->node); | ||
745 | } | ||
746 | } | 750 | } |
747 | 751 | ||
748 | if (last_focus) { | 752 | if (last_focus) { |
@@ -1017,6 +1021,11 @@ void seat_begin_down(struct sway_seat *seat, struct sway_container *con, | |||
1017 | seat->op_ref_con_lx = sx; | 1021 | seat->op_ref_con_lx = sx; |
1018 | seat->op_ref_con_ly = sy; | 1022 | seat->op_ref_con_ly = sy; |
1019 | seat->op_moved = false; | 1023 | seat->op_moved = false; |
1024 | |||
1025 | // In case the container was not raised by gaining focus, raise on click | ||
1026 | if (con && !config->raise_floating) { | ||
1027 | container_raise_floating(con); | ||
1028 | } | ||
1020 | } | 1029 | } |
1021 | 1030 | ||
1022 | void seat_begin_move_floating(struct sway_seat *seat, | 1031 | void seat_begin_move_floating(struct sway_seat *seat, |
diff --git a/sway/meson.build b/sway/meson.build index 00ebcb40..8ab28869 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -48,6 +48,7 @@ sway_sources = files( | |||
48 | 'commands/floating_modifier.c', | 48 | 'commands/floating_modifier.c', |
49 | 'commands/focus.c', | 49 | 'commands/focus.c', |
50 | 'commands/focus_follows_mouse.c', | 50 | 'commands/focus_follows_mouse.c', |
51 | 'commands/raise_floating.c', | ||
51 | 'commands/focus_on_window_activation.c', | 52 | 'commands/focus_on_window_activation.c', |
52 | 'commands/focus_wrapping.c', | 53 | 'commands/focus_wrapping.c', |
53 | 'commands/font.c', | 54 | 'commands/font.c', |
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 3202d517..3fda6cef 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -441,6 +441,11 @@ The default colors are: | |||
441 | devices. A list of input device names may be obtained via *swaymsg -t | 441 | devices. A list of input device names may be obtained via *swaymsg -t |
442 | get\_inputs*. | 442 | get\_inputs*. |
443 | 443 | ||
444 | *raise\_floating* yes|no | ||
445 | Controls the behaviour of floating windows. A _yes_ (the default) will | ||
446 | raise windows on gaining focus. A _no_ will only raise floating windows | ||
447 | by clicking anywhere in the window. | ||
448 | |||
444 | *seat* <seat> <seat-subcommands...> | 449 | *seat* <seat> <seat-subcommands...> |
445 | For details on seat subcommands, see *sway-input*(5). | 450 | For details on seat subcommands, see *sway-input*(5). |
446 | 451 | ||
diff --git a/sway/tree/container.c b/sway/tree/container.c index a069b177..9db7aed1 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -151,10 +151,10 @@ struct sway_container *container_find_child(struct sway_container *container, | |||
151 | return NULL; | 151 | return NULL; |
152 | } | 152 | } |
153 | 153 | ||
154 | static void surface_at_view(struct sway_container *con, double lx, double ly, | 154 | static struct sway_container *surface_at_view(struct sway_container *con, double lx, double ly, |
155 | struct wlr_surface **surface, double *sx, double *sy) { | 155 | struct wlr_surface **surface, double *sx, double *sy) { |
156 | if (!sway_assert(con->view, "Expected a view")) { | 156 | if (!sway_assert(con->view, "Expected a view")) { |
157 | return; | 157 | return NULL; |
158 | } | 158 | } |
159 | struct sway_view *view = con->view; | 159 | struct sway_view *view = con->view; |
160 | double view_sx = lx - view->x + view->geometry.x; | 160 | double view_sx = lx - view->x + view->geometry.x; |
@@ -184,7 +184,9 @@ static void surface_at_view(struct sway_container *con, double lx, double ly, | |||
184 | *sx = _sx; | 184 | *sx = _sx; |
185 | *sy = _sy; | 185 | *sy = _sy; |
186 | *surface = _surface; | 186 | *surface = _surface; |
187 | return con; | ||
187 | } | 188 | } |
189 | return NULL; | ||
188 | } | 190 | } |
189 | 191 | ||
190 | /** | 192 | /** |
@@ -355,37 +357,31 @@ struct sway_container *container_at(struct sway_workspace *workspace, | |||
355 | double lx, double ly, | 357 | double lx, double ly, |
356 | struct wlr_surface **surface, double *sx, double *sy) { | 358 | struct wlr_surface **surface, double *sx, double *sy) { |
357 | struct sway_container *c; | 359 | struct sway_container *c; |
360 | |||
358 | // Focused view's popups | 361 | // Focused view's popups |
359 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 362 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
360 | struct sway_container *focus = seat_get_focused_container(seat); | 363 | struct sway_container *focus = seat_get_focused_container(seat); |
361 | bool is_floating = focus && container_is_floating_or_child(focus); | 364 | bool is_floating = focus && container_is_floating_or_child(focus); |
362 | // Focused view's popups | 365 | // Focused view's popups |
363 | if (focus && focus->view) { | 366 | if (focus && focus->view) { |
364 | surface_at_view(focus, lx, ly, surface, sx, sy); | 367 | c = surface_at_view(focus, lx, ly, surface, sx, sy); |
365 | if (*surface && surface_is_popup(*surface)) { | 368 | if (c && surface_is_popup(*surface)) { |
366 | return focus; | 369 | return c; |
367 | } | 370 | } |
368 | *surface = NULL; | 371 | *surface = NULL; |
369 | } | 372 | } |
370 | // If focused is floating, focused view's non-popups | 373 | // Cast a ray to handle floating windows |
371 | if (focus && focus->view && is_floating) { | 374 | for (int i = workspace->floating->length - 1; i >= 0; --i) { |
372 | surface_at_view(focus, lx, ly, surface, sx, sy); | 375 | struct sway_container *cn = workspace->floating->items[i]; |
373 | if (*surface) { | 376 | if (cn->view && (c = surface_at_view(cn, lx, ly, surface, sx, sy))) { |
374 | return focus; | 377 | return c; |
375 | } | 378 | } |
376 | *surface = NULL; | ||
377 | } | ||
378 | // Floating (non-focused) | ||
379 | if ((c = floating_container_at(lx, ly, surface, sx, sy))) { | ||
380 | return c; | ||
381 | } | 379 | } |
382 | // If focused is tiling, focused view's non-popups | 380 | // If focused is tiling, focused view's non-popups |
383 | if (focus && focus->view && !is_floating) { | 381 | if (focus && focus->view && !is_floating) { |
384 | surface_at_view(focus, lx, ly, surface, sx, sy); | 382 | if ((c = surface_at_view(focus, lx, ly, surface, sx, sy))) { |
385 | if (*surface) { | 383 | return c; |
386 | return focus; | ||
387 | } | 384 | } |
388 | *surface = NULL; | ||
389 | } | 385 | } |
390 | // Tiling (non-focused) | 386 | // Tiling (non-focused) |
391 | if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { | 387 | if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { |