aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/tiling_drag_threshold.c22
-rw-r--r--sway/config.c1
-rw-r--r--sway/input/cursor.c40
-rw-r--r--sway/input/seat.c11
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway-output.5.scd12
-rw-r--r--sway/sway.5.scd21
8 files changed, 97 insertions, 12 deletions
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[] = {
{ "smart_borders", cmd_smart_borders },
{ "smart_gaps", cmd_smart_gaps },
{ "tiling_drag", cmd_tiling_drag },
+ { "tiling_drag_threshold", cmd_tiling_drag_threshold },
{ "title_align", cmd_title_align },
{ "titlebar_border_thickness", cmd_titlebar_border_thickness },
{ "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 @@
+#include <string.h>
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "log.h"
+
+struct cmd_results *cmd_tiling_drag_threshold(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "tiling_drag_threshold", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ char *inv;
+ int value = strtol(argv[0], &inv, 10);
+ if (*inv != '\0' || value < 0) {
+ return cmd_results_new(CMD_INVALID, "tiling_drag_threshold",
+ "Invalid threshold specified");
+ }
+
+ config->tiling_drag_threshold = value;
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
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) {
config->show_marks = true;
config->title_align = ALIGN_LEFT;
config->tiling_drag = true;
+ config->tiling_drag_threshold = 9;
config->smart_gaps = false;
config->gaps_inner = 0;
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index f8302ddf..66a9e435 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,
desktop_damage_box(&seat->op_drop_box);
}
+static void handle_move_tiling_threshold_motion(struct sway_seat *seat,
+ struct sway_cursor *cursor) {
+ double cx = seat->cursor->cursor->x;
+ double cy = seat->cursor->cursor->y;
+ double sx = seat->op_ref_lx;
+ double sy = seat->op_ref_ly;
+
+ // Get the scaled threshold for the output. Even if the operation goes
+ // across multiple outputs of varying scales, just use the scale for the
+ // output that the cursor is currently on for simplicity.
+ struct wlr_output *wlr_output = wlr_output_layout_output_at(
+ root->output_layout, cx, cy);
+ double output_scale = wlr_output ? wlr_output->scale : 1;
+ double threshold = config->tiling_drag_threshold * output_scale;
+ threshold *= threshold;
+
+ // If the threshold has been exceeded, start the actual drag
+ if ((cx - sx) * (cx - sx) + (cy - sy) * (cy - sy) > threshold) {
+ seat->operation = OP_MOVE_TILING;
+ cursor_set_image(cursor, "grab", NULL);
+ handle_move_tiling_motion(seat, cursor);
+ }
+}
+
static void calculate_floating_constraints(struct sway_container *con,
int *min_width, int *max_width, int *min_height, int *max_height) {
if (config->floating_minimum_width == -1) { // no minimum
@@ -640,6 +664,9 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor,
case OP_MOVE_FLOATING:
handle_move_floating_motion(seat, cursor);
break;
+ case OP_MOVE_TILING_THRESHOLD:
+ handle_move_tiling_threshold_motion(seat, cursor);
+ break;
case OP_MOVE_TILING:
handle_move_tiling_motion(seat, cursor);
break;
@@ -984,12 +1011,21 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
if (config->tiling_drag && (mod_pressed || on_titlebar) &&
state == WLR_BUTTON_PRESSED && !is_floating_or_child &&
cont && !cont->is_fullscreen) {
- if (on_titlebar) {
+ struct sway_container *focus = seat_get_focused_container(seat);
+ bool focused = focus == cont || container_has_ancestor(focus, cont);
+ if (on_titlebar && !focused) {
node = seat_get_focus_inactive(seat, &cont->node);
seat_set_focus(seat, node);
}
+
seat_pointer_notify_button(seat, time_msec, button, state);
- seat_begin_move_tiling(seat, cont, button);
+
+ // If moving a container by it's title bar, use a threshold for the drag
+ if (!mod_pressed && config->tiling_drag_threshold > 0) {
+ seat_begin_move_tiling_threshold(seat, cont, button);
+ } else {
+ seat_begin_move_tiling(seat, cont, button);
+ }
return;
}
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,
cursor_set_image(seat->cursor, "grab", NULL);
}
+void seat_begin_move_tiling_threshold(struct sway_seat *seat,
+ struct sway_container *con, uint32_t button) {
+ seat->operation = OP_MOVE_TILING_THRESHOLD;
+ seat->op_container = con;
+ seat->op_button = button;
+ seat->op_target_node = NULL;
+ seat->op_target_edge = 0;
+ seat->op_ref_lx = seat->cursor->cursor->x;
+ seat->op_ref_ly = seat->cursor->cursor->y;
+}
+
void seat_begin_move_tiling(struct sway_seat *seat,
struct sway_container *con, uint32_t button) {
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(
'commands/swaynag_command.c',
'commands/swap.c',
'commands/tiling_drag.c',
+ 'commands/tiling_drag_threshold.c',
'commands/title_align.c',
'commands/title_format.c',
'commands/titlebar_border_thickness.c',
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd
index 9940d8e8..28524478 100644
--- a/sway/sway-output.5.scd
+++ b/sway/sway-output.5.scd
@@ -38,17 +38,20 @@ must be separated by one space. For example:
Places the specified output at the specific position in the global
coordinate space. If scaling is active, it has to be considered when
positioning. For example, if the scaling factor for the left output is 2,
- the relative position for the right output has to be divided by 2.
+ the relative position for the right output has to be divided by 2. The
+ reference point is the top left corner so if you want the bottoms aligned
+ this has to be considered as well.
Example:
output HDMI1 scale 2
- output HDMI1 pos 0 0 res 3200x1800
+ output HDMI1 pos 0 1020 res 3200x1800
output eDP1 pos 1600 0 res 1920x1080
- Note that the x-pos of eDP1 is 1600 = 3200/2.
+ Note that the left x-pos of eDP1 is 1600 = 3200/2 and the bottom y-pos is
+ 1020 + (1800 / 2) = 1920 = 0 + 1920
*output* <name> scale <factor>
Scales the specified output by the specified scale _factor_. An integer is
@@ -57,7 +60,8 @@ must be separated by one space. For example:
represent the contents of your windows - they will be rendered at the next
highest integral scale factor and downscaled. You may be better served by
setting an integral scale factor and adjusting the font size of your
- applications to taste.
+ applications to taste. HiDPI isn't supported with Xwayland clients (windows
+ will blur).
*output* <name> background|bg <file> <mode> [<fallback\_color>]
Sets the wallpaper for the given output to the specified file, using the
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index e6abef56..3757a097 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -327,7 +327,8 @@ runtime.
A view that does not have focus.
*client.urgent*
- A view with an urgency hint. *Note*: This is not currently implemented.
+ A view with an urgency hint. *Note*: Native Wayland windows do not
+ support urgency. Urgency only works for Xwayland windows.
The meaning of each color is:
@@ -431,7 +432,7 @@ The default colors are:
*focus\_follows\_mouse* yes|no|always
If set to _yes_, moving your mouse over a window will focus that window. If
- set to _always_, the window under the cursor will always be focused, even
+ set to _always_, the window under the cursor will always be focused, even
after switching between workspaces.
*focus\_wrapping* yes|no|force
@@ -450,11 +451,11 @@ The default colors are:
Thickness of the titlebar border in pixels
*titlebar\_padding* <horizontal> [<vertical>]
- Padding of the text in the titlebar. _horizontal_ value affects horizontal
- padding of the text while _vertical_ value affects vertical padding (space
- above and below text). Padding includes titlebar borders so their value
+ Padding of the text in the titlebar. _horizontal_ value affects horizontal
+ padding of the text while _vertical_ value affects vertical padding (space
+ above and below text). Padding includes titlebar borders so their value
should be greater than titlebar\_border\_thickness. If _vertical_ value is
- not specified it is set to the _horizontal_ value.
+ not specified it is set to the _horizontal_ value.
*for\_window* <criteria> <command>
Whenever a window that matches _criteria_ appears, run list of commands.
@@ -572,6 +573,14 @@ The default colors are:
the _floating\_mod_ will also allow the container to be dragged. _toggle_
should not be used in the config file.
+*tiling\_drag\_threshold* <threshold>
+ Sets the threshold that must be exceeded for a container to be dragged by
+ its titlebar. This has no effect if _floating\_mod_ is used or if
+ _tiling\_drag_ is set to _disable_. Once the threshold has been exceeded
+ once, the drag starts and the cursor can come back inside the threshold
+ without stopping the drag. _threshold_ is multiplied by the scale of the
+ output that the cursor on. The default is 9.
+
*title\_align* left|center|right
Sets the title alignment. If _right_ is selected and _show\_marks_ is set
to _yes_, the marks will be shown on the _left_ side instead of the