diff options
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | include/sway/input/seat.h | 4 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/tiling_drag_threshold.c | 22 | ||||
-rw-r--r-- | sway/config.c | 1 | ||||
-rw-r--r-- | sway/input/cursor.c | 41 | ||||
-rw-r--r-- | sway/input/seat.c | 11 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway.5.scd | 9 |
10 files changed, 91 insertions, 2 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 0e2d7931..7d0ff838 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -172,6 +172,7 @@ sway_cmd cmd_swaybg_command; | |||
172 | sway_cmd cmd_swaynag_command; | 172 | sway_cmd cmd_swaynag_command; |
173 | sway_cmd cmd_swap; | 173 | sway_cmd cmd_swap; |
174 | sway_cmd cmd_tiling_drag; | 174 | sway_cmd cmd_tiling_drag; |
175 | sway_cmd cmd_tiling_drag_threshold; | ||
175 | sway_cmd cmd_title_align; | 176 | sway_cmd cmd_title_align; |
176 | sway_cmd cmd_title_format; | 177 | sway_cmd cmd_title_format; |
177 | sway_cmd cmd_titlebar_border_thickness; | 178 | sway_cmd cmd_titlebar_border_thickness; |
diff --git a/include/sway/config.h b/include/sway/config.h index f604b054..ebf16e6a 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -426,7 +426,9 @@ struct sway_config { | |||
426 | bool auto_back_and_forth; | 426 | bool auto_back_and_forth; |
427 | bool show_marks; | 427 | bool show_marks; |
428 | enum alignment title_align; | 428 | enum alignment title_align; |
429 | |||
429 | bool tiling_drag; | 430 | bool tiling_drag; |
431 | int tiling_drag_threshold; | ||
430 | 432 | ||
431 | bool smart_gaps; | 433 | bool smart_gaps; |
432 | int gaps_inner; | 434 | int gaps_inner; |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index d665c86e..a3c20346 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -39,6 +39,7 @@ enum sway_seat_operation { | |||
39 | OP_NONE, | 39 | OP_NONE, |
40 | OP_DOWN, | 40 | OP_DOWN, |
41 | OP_MOVE_FLOATING, | 41 | OP_MOVE_FLOATING, |
42 | OP_MOVE_TILING_THRESHOLD, | ||
42 | OP_MOVE_TILING, | 43 | OP_MOVE_TILING, |
43 | OP_RESIZE_FLOATING, | 44 | OP_RESIZE_FLOATING, |
44 | OP_RESIZE_TILING, | 45 | OP_RESIZE_TILING, |
@@ -186,6 +187,9 @@ void seat_begin_down(struct sway_seat *seat, struct sway_container *con, | |||
186 | void seat_begin_move_floating(struct sway_seat *seat, | 187 | void seat_begin_move_floating(struct sway_seat *seat, |
187 | struct sway_container *con, uint32_t button); | 188 | struct sway_container *con, uint32_t button); |
188 | 189 | ||
190 | void seat_begin_move_tiling_threshold(struct sway_seat *seat, | ||
191 | struct sway_container *con, uint32_t button); | ||
192 | |||
189 | void seat_begin_move_tiling(struct sway_seat *seat, | 193 | void seat_begin_move_tiling(struct sway_seat *seat, |
190 | struct sway_container *con, uint32_t button); | 194 | struct sway_container *con, uint32_t button); |
191 | 195 | ||
diff --git a/sway/commands.c b/sway/commands.c index 927434bc..0883b57b 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -87,6 +87,7 @@ static struct cmd_handler handlers[] = { | |||
87 | { "smart_borders", cmd_smart_borders }, | 87 | { "smart_borders", cmd_smart_borders }, |
88 | { "smart_gaps", cmd_smart_gaps }, | 88 | { "smart_gaps", cmd_smart_gaps }, |
89 | { "tiling_drag", cmd_tiling_drag }, | 89 | { "tiling_drag", cmd_tiling_drag }, |
90 | { "tiling_drag_threshold", cmd_tiling_drag_threshold }, | ||
90 | { "title_align", cmd_title_align }, | 91 | { "title_align", cmd_title_align }, |
91 | { "titlebar_border_thickness", cmd_titlebar_border_thickness }, | 92 | { "titlebar_border_thickness", cmd_titlebar_border_thickness }, |
92 | { "titlebar_padding", cmd_titlebar_padding }, | 93 | { "titlebar_padding", cmd_titlebar_padding }, |
diff --git a/sway/commands/tiling_drag_threshold.c b/sway/commands/tiling_drag_threshold.c new file mode 100644 index 00000000..6b0531c3 --- /dev/null +++ b/sway/commands/tiling_drag_threshold.c | |||
@@ -0,0 +1,22 @@ | |||
1 | #include <string.h> | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/config.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct cmd_results *cmd_tiling_drag_threshold(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "tiling_drag_threshold", EXPECTED_EQUAL_TO, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | |||
12 | char *inv; | ||
13 | int value = strtol(argv[0], &inv, 10); | ||
14 | if (*inv != '\0' || value < 0) { | ||
15 | return cmd_results_new(CMD_INVALID, "tiling_drag_threshold", | ||
16 | "Invalid threshold specified"); | ||
17 | } | ||
18 | |||
19 | config->tiling_drag_threshold = value; | ||
20 | |||
21 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
22 | } | ||
diff --git a/sway/config.c b/sway/config.c index bb7f796d..5d631b7e 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -233,6 +233,7 @@ static void config_defaults(struct sway_config *config) { | |||
233 | config->show_marks = true; | 233 | config->show_marks = true; |
234 | config->title_align = ALIGN_LEFT; | 234 | config->title_align = ALIGN_LEFT; |
235 | config->tiling_drag = true; | 235 | config->tiling_drag = true; |
236 | config->tiling_drag_threshold = 9; | ||
236 | 237 | ||
237 | config->smart_gaps = false; | 238 | config->smart_gaps = false; |
238 | config->gaps_inner = 0; | 239 | config->gaps_inner = 0; |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f8302ddf..516251f7 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -384,6 +384,30 @@ static void handle_move_tiling_motion(struct sway_seat *seat, | |||
384 | desktop_damage_box(&seat->op_drop_box); | 384 | desktop_damage_box(&seat->op_drop_box); |
385 | } | 385 | } |
386 | 386 | ||
387 | static void handle_move_tiling_threshold_motion(struct sway_seat *seat, | ||
388 | struct sway_cursor *cursor) { | ||
389 | double cx = seat->cursor->cursor->x; | ||
390 | double cy = seat->cursor->cursor->y; | ||
391 | double sx = seat->op_ref_lx; | ||
392 | double sy = seat->op_ref_ly; | ||
393 | |||
394 | // Get the scaled threshold for the output. Even if the operation goes | ||
395 | // across multiple outputs of varying scales, just use the scale for the | ||
396 | // output that the cursor is currently on for simplicity. | ||
397 | struct wlr_output *wlr_output = wlr_output_layout_output_at( | ||
398 | root->output_layout, cx, cy); | ||
399 | double output_scale = wlr_output ? wlr_output->scale : 1; | ||
400 | double threshold = config->tiling_drag_threshold * output_scale; | ||
401 | threshold *= threshold; | ||
402 | |||
403 | // If the threshold has been exceeded, start the actual drag | ||
404 | if ((cx - sx) * (cx - sx) + (cy - sy) * (cy - sy) > threshold) { | ||
405 | seat->operation = OP_MOVE_TILING; | ||
406 | cursor_set_image(cursor, "grab", NULL); | ||
407 | handle_move_tiling_motion(seat, cursor); | ||
408 | } | ||
409 | } | ||
410 | |||
387 | static void calculate_floating_constraints(struct sway_container *con, | 411 | static void calculate_floating_constraints(struct sway_container *con, |
388 | int *min_width, int *max_width, int *min_height, int *max_height) { | 412 | int *min_width, int *max_width, int *min_height, int *max_height) { |
389 | if (config->floating_minimum_width == -1) { // no minimum | 413 | if (config->floating_minimum_width == -1) { // no minimum |
@@ -640,6 +664,9 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
640 | case OP_MOVE_FLOATING: | 664 | case OP_MOVE_FLOATING: |
641 | handle_move_floating_motion(seat, cursor); | 665 | handle_move_floating_motion(seat, cursor); |
642 | break; | 666 | break; |
667 | case OP_MOVE_TILING_THRESHOLD: | ||
668 | handle_move_tiling_threshold_motion(seat, cursor); | ||
669 | break; | ||
643 | case OP_MOVE_TILING: | 670 | case OP_MOVE_TILING: |
644 | handle_move_tiling_motion(seat, cursor); | 671 | handle_move_tiling_motion(seat, cursor); |
645 | break; | 672 | break; |
@@ -984,12 +1011,22 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
984 | if (config->tiling_drag && (mod_pressed || on_titlebar) && | 1011 | if (config->tiling_drag && (mod_pressed || on_titlebar) && |
985 | state == WLR_BUTTON_PRESSED && !is_floating_or_child && | 1012 | state == WLR_BUTTON_PRESSED && !is_floating_or_child && |
986 | cont && !cont->is_fullscreen) { | 1013 | cont && !cont->is_fullscreen) { |
987 | if (on_titlebar) { | 1014 | struct sway_container *focus = seat_get_focused_container(seat); |
1015 | bool focused = focus == cont || container_has_ancestor(focus, cont); | ||
1016 | if (on_titlebar && !focused) { | ||
988 | node = seat_get_focus_inactive(seat, &cont->node); | 1017 | node = seat_get_focus_inactive(seat, &cont->node); |
989 | seat_set_focus(seat, node); | 1018 | seat_set_focus(seat, node); |
990 | } | 1019 | } |
1020 | |||
991 | seat_pointer_notify_button(seat, time_msec, button, state); | 1021 | seat_pointer_notify_button(seat, time_msec, button, state); |
992 | seat_begin_move_tiling(seat, cont, button); | 1022 | |
1023 | // If moving a previously unfocused container by it's title bar, use a | ||
1024 | // threshold for the drag. | ||
1025 | if (!mod_pressed && !focused && config->tiling_drag_threshold > 0) { | ||
1026 | seat_begin_move_tiling_threshold(seat, cont, button); | ||
1027 | } else { | ||
1028 | seat_begin_move_tiling(seat, cont, button); | ||
1029 | } | ||
993 | return; | 1030 | return; |
994 | } | 1031 | } |
995 | 1032 | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index fa82c9ce..9422713d 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1052,6 +1052,17 @@ void seat_begin_move_floating(struct sway_seat *seat, | |||
1052 | cursor_set_image(seat->cursor, "grab", NULL); | 1052 | cursor_set_image(seat->cursor, "grab", NULL); |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | void seat_begin_move_tiling_threshold(struct sway_seat *seat, | ||
1056 | struct sway_container *con, uint32_t button) { | ||
1057 | seat->operation = OP_MOVE_TILING_THRESHOLD; | ||
1058 | seat->op_container = con; | ||
1059 | seat->op_button = button; | ||
1060 | seat->op_target_node = NULL; | ||
1061 | seat->op_target_edge = 0; | ||
1062 | seat->op_ref_lx = seat->cursor->cursor->x; | ||
1063 | seat->op_ref_ly = seat->cursor->cursor->y; | ||
1064 | } | ||
1065 | |||
1055 | void seat_begin_move_tiling(struct sway_seat *seat, | 1066 | void seat_begin_move_tiling(struct sway_seat *seat, |
1056 | struct sway_container *con, uint32_t button) { | 1067 | struct sway_container *con, uint32_t button) { |
1057 | seat->operation = OP_MOVE_TILING; | 1068 | seat->operation = OP_MOVE_TILING; |
diff --git a/sway/meson.build b/sway/meson.build index 7f739287..98676ce0 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -89,6 +89,7 @@ sway_sources = files( | |||
89 | 'commands/swaynag_command.c', | 89 | 'commands/swaynag_command.c', |
90 | 'commands/swap.c', | 90 | 'commands/swap.c', |
91 | 'commands/tiling_drag.c', | 91 | 'commands/tiling_drag.c', |
92 | 'commands/tiling_drag_threshold.c', | ||
92 | 'commands/title_align.c', | 93 | 'commands/title_align.c', |
93 | 'commands/title_format.c', | 94 | 'commands/title_format.c', |
94 | 'commands/titlebar_border_thickness.c', | 95 | 'commands/titlebar_border_thickness.c', |
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index e6abef56..37a9b24c 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -572,6 +572,15 @@ The default colors are: | |||
572 | the _floating\_mod_ will also allow the container to be dragged. _toggle_ | 572 | the _floating\_mod_ will also allow the container to be dragged. _toggle_ |
573 | should not be used in the config file. | 573 | should not be used in the config file. |
574 | 574 | ||
575 | *tiling\_drag\_threshold* <threshold> | ||
576 | Sets the threshold that must be exceeded for an unfocused tiling container | ||
577 | to be dragged by its titlebar. This has no effect if _floating\_mod_ is | ||
578 | used, if the container is focused, or if _tiling\_drag_ is set to | ||
579 | _disable_. Once the threshold has been exceeded once, the drag starts and | ||
580 | the cursor can come back inside the threshold without stopping the drag. | ||
581 | _threshold_ is multiplied by the scale of the output that the cursor on. | ||
582 | The default is 9. | ||
583 | |||
575 | *title\_align* left|center|right | 584 | *title\_align* left|center|right |
576 | Sets the title alignment. If _right_ is selected and _show\_marks_ is set | 585 | Sets the title alignment. If _right_ is selected and _show\_marks_ is set |
577 | to _yes_, the marks will be shown on the _left_ side instead of the | 586 | to _yes_, the marks will be shown on the _left_ side instead of the |