diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-31 15:32:29 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-31 15:32:29 -0400 |
commit | 122b96abed9955f78e3f157167d34312f5bb551d (patch) | |
tree | fdcb6ffc0520145a029118aec443eb2199981d77 | |
parent | Merge pull request #1689 from emersion/destroy-output-segfaults (diff) | |
parent | Address review feedback (diff) | |
download | sway-122b96abed9955f78e3f157167d34312f5bb551d.tar.gz sway-122b96abed9955f78e3f157167d34312f5bb551d.tar.zst sway-122b96abed9955f78e3f157167d34312f5bb551d.zip |
Merge pull request #1684 from swaywm/follow-warp
Implement focus_follows_mouse, mouse_warping
-rw-r--r-- | include/sway/config.h | 1 | ||||
-rw-r--r-- | include/sway/input/seat.h | 3 | ||||
-rw-r--r-- | sway/commands.c | 2 | ||||
-rw-r--r-- | sway/commands/focus_follows_mouse.c | 12 | ||||
-rw-r--r-- | sway/commands/mouse_warping.c | 19 | ||||
-rw-r--r-- | sway/config.c | 1 | ||||
-rw-r--r-- | sway/input/cursor.c | 57 | ||||
-rw-r--r-- | sway/input/seat.c | 32 | ||||
-rw-r--r-- | sway/meson.build | 2 |
9 files changed, 95 insertions, 34 deletions
diff --git a/include/sway/config.h b/include/sway/config.h index ac1105b4..03b51948 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -304,7 +304,6 @@ struct sway_config { | |||
304 | bool reloading; | 304 | bool reloading; |
305 | bool reading; | 305 | bool reading; |
306 | bool auto_back_and_forth; | 306 | bool auto_back_and_forth; |
307 | bool seamless_mouse; | ||
308 | bool show_marks; | 307 | bool show_marks; |
309 | 308 | ||
310 | bool edge_gaps; | 309 | bool edge_gaps; |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 496bfd5d..31210a5a 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -56,6 +56,9 @@ void sway_seat_configure_xcursor(struct sway_seat *seat); | |||
56 | 56 | ||
57 | void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); | 57 | void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); |
58 | 58 | ||
59 | void sway_seat_set_focus_warp(struct sway_seat *seat, | ||
60 | struct sway_container *container, bool warp); | ||
61 | |||
59 | struct sway_container *sway_seat_get_focus(struct sway_seat *seat); | 62 | struct sway_container *sway_seat_get_focus(struct sway_seat *seat); |
60 | 63 | ||
61 | /** | 64 | /** |
diff --git a/sway/commands.c b/sway/commands.c index eee7f254..90544220 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -98,9 +98,11 @@ static struct cmd_handler handlers[] = { | |||
98 | { "bindsym", cmd_bindsym }, | 98 | { "bindsym", cmd_bindsym }, |
99 | { "exec", cmd_exec }, | 99 | { "exec", cmd_exec }, |
100 | { "exec_always", cmd_exec_always }, | 100 | { "exec_always", cmd_exec_always }, |
101 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | ||
101 | { "include", cmd_include }, | 102 | { "include", cmd_include }, |
102 | { "input", cmd_input }, | 103 | { "input", cmd_input }, |
103 | { "mode", cmd_mode }, | 104 | { "mode", cmd_mode }, |
105 | { "mouse_warping", cmd_mouse_warping }, | ||
104 | { "output", cmd_output }, | 106 | { "output", cmd_output }, |
105 | { "seat", cmd_seat }, | 107 | { "seat", cmd_seat }, |
106 | { "workspace", cmd_workspace }, | 108 | { "workspace", cmd_workspace }, |
diff --git a/sway/commands/focus_follows_mouse.c b/sway/commands/focus_follows_mouse.c new file mode 100644 index 00000000..661e7852 --- /dev/null +++ b/sway/commands/focus_follows_mouse.c | |||
@@ -0,0 +1,12 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | |||
5 | struct cmd_results *cmd_focus_follows_mouse(int argc, char **argv) { | ||
6 | struct cmd_results *error = NULL; | ||
7 | if ((error = checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1))) { | ||
8 | return error; | ||
9 | } | ||
10 | config->focus_follows_mouse = !strcasecmp(argv[0], "yes"); | ||
11 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
12 | } | ||
diff --git a/sway/commands/mouse_warping.c b/sway/commands/mouse_warping.c new file mode 100644 index 00000000..eef32ce7 --- /dev/null +++ b/sway/commands/mouse_warping.c | |||
@@ -0,0 +1,19 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | |||
5 | struct cmd_results *cmd_mouse_warping(int argc, char **argv) { | ||
6 | struct cmd_results *error = NULL; | ||
7 | if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) { | ||
8 | return error; | ||
9 | } else if (strcasecmp(argv[0], "output") == 0) { | ||
10 | config->mouse_warping = true; | ||
11 | } else if (strcasecmp(argv[0], "none") == 0) { | ||
12 | config->mouse_warping = false; | ||
13 | } else { | ||
14 | return cmd_results_new(CMD_FAILURE, "mouse_warping", | ||
15 | "Expected 'mouse_warping output|none'"); | ||
16 | } | ||
17 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
18 | } | ||
19 | |||
diff --git a/sway/config.c b/sway/config.c index e9e7057d..0eecf7f6 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -178,7 +178,6 @@ static void config_defaults(struct sway_config *config) { | |||
178 | config->active = false; | 178 | config->active = false; |
179 | config->failed = false; | 179 | config->failed = false; |
180 | config->auto_back_and_forth = false; | 180 | config->auto_back_and_forth = false; |
181 | config->seamless_mouse = true; | ||
182 | config->reading = false; | 181 | config->reading = false; |
183 | config->show_marks = true; | 182 | config->show_marks = true; |
184 | 183 | ||
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 67776f8f..d608a9cf 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -127,7 +127,10 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
127 | struct wlr_seat *seat = cursor->seat->wlr_seat; | 127 | struct wlr_seat *seat = cursor->seat->wlr_seat; |
128 | struct wlr_surface *surface = NULL; | 128 | struct wlr_surface *surface = NULL; |
129 | double sx, sy; | 129 | double sx, sy; |
130 | container_at_cursor(cursor, &surface, &sx, &sy); | 130 | struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); |
131 | if (c && config->focus_follows_mouse) { | ||
132 | sway_seat_set_focus_warp(cursor->seat, c, false); | ||
133 | } | ||
131 | 134 | ||
132 | // reset cursor if switching between clients | 135 | // reset cursor if switching between clients |
133 | struct wl_client *client = NULL; | 136 | struct wl_client *client = NULL; |
@@ -158,8 +161,8 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { | |||
158 | cursor_send_pointer_motion(cursor, event->time_msec); | 161 | cursor_send_pointer_motion(cursor, event->time_msec); |
159 | } | 162 | } |
160 | 163 | ||
161 | static void handle_cursor_motion_absolute(struct wl_listener *listener, | 164 | static void handle_cursor_motion_absolute( |
162 | void *data) { | 165 | struct wl_listener *listener, void *data) { |
163 | struct sway_cursor *cursor = | 166 | struct sway_cursor *cursor = |
164 | wl_container_of(listener, cursor, motion_absolute); | 167 | wl_container_of(listener, cursor, motion_absolute); |
165 | struct wlr_event_pointer_motion_absolute *event = data; | 168 | struct wlr_event_pointer_motion_absolute *event = data; |
@@ -172,33 +175,31 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
172 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); | 175 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); |
173 | struct wlr_event_pointer_button *event = data; | 176 | struct wlr_event_pointer_button *event = data; |
174 | 177 | ||
175 | if (event->button == BTN_LEFT) { | 178 | struct wlr_surface *surface = NULL; |
176 | struct wlr_surface *surface = NULL; | 179 | double sx, sy; |
177 | double sx, sy; | 180 | struct sway_container *cont = |
178 | struct sway_container *cont = | 181 | container_at_cursor(cursor, &surface, &sx, &sy); |
179 | container_at_cursor(cursor, &surface, &sx, &sy); | 182 | // Avoid moving keyboard focus from a surface that accepts it to one |
180 | // Avoid moving keyboard focus from a surface that accepts it to one | 183 | // that does not unless the change would move us to a new workspace. |
181 | // that does not unless the change would move us to a new workspace. | 184 | // |
182 | // | 185 | // This prevents, for example, losing focus when clicking on swaybar. |
183 | // This prevents, for example, losing focus when clicking on swaybar. | 186 | // |
184 | // | 187 | // TODO: Replace this condition with something like |
185 | // TODO: Replace this condition with something like | 188 | // !surface_accepts_keyboard_input |
186 | // !surface_accepts_keyboard_input | 189 | if (surface && cont && cont->type != C_VIEW) { |
187 | if (surface && cont && cont->type != C_VIEW) { | 190 | struct sway_container *new_ws = cont; |
188 | struct sway_container *new_ws = cont; | 191 | if (new_ws && new_ws->type != C_WORKSPACE) { |
189 | if (new_ws && new_ws->type != C_WORKSPACE) { | 192 | new_ws = container_parent(new_ws, C_WORKSPACE); |
190 | new_ws = container_parent(new_ws, C_WORKSPACE); | 193 | } |
191 | } | 194 | struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); |
192 | struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); | 195 | if (old_ws && old_ws->type != C_WORKSPACE) { |
193 | if (old_ws && old_ws->type != C_WORKSPACE) { | 196 | old_ws = container_parent(old_ws, C_WORKSPACE); |
194 | old_ws = container_parent(old_ws, C_WORKSPACE); | 197 | } |
195 | } | 198 | if (new_ws != old_ws) { |
196 | if (new_ws != old_ws) { | ||
197 | sway_seat_set_focus(cursor->seat, cont); | ||
198 | } | ||
199 | } else { | ||
200 | sway_seat_set_focus(cursor->seat, cont); | 199 | sway_seat_set_focus(cursor->seat, cont); |
201 | } | 200 | } |
201 | } else { | ||
202 | sway_seat_set_focus(cursor->seat, cont); | ||
202 | } | 203 | } |
203 | 204 | ||
204 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, | 205 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 8d592872..9aa34aca 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #define _XOPEN_SOURCE 700 | 1 | #define _XOPEN_SOURCE 700 |
2 | #include <wlr/types/wlr_cursor.h> | 2 | #include <wlr/types/wlr_cursor.h> |
3 | #include <wlr/types/wlr_output_layout.h> | ||
3 | #include <wlr/types/wlr_xcursor_manager.h> | 4 | #include <wlr/types/wlr_xcursor_manager.h> |
4 | #include "sway/tree/container.h" | 5 | #include "sway/tree/container.h" |
5 | #include "sway/input/seat.h" | 6 | #include "sway/input/seat.h" |
@@ -291,8 +292,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { | |||
291 | seat->cursor->cursor->y); | 292 | seat->cursor->cursor->y); |
292 | } | 293 | } |
293 | 294 | ||
294 | void sway_seat_set_focus(struct sway_seat *seat, | 295 | void sway_seat_set_focus_warp(struct sway_seat *seat, |
295 | struct sway_container *container) { | 296 | struct sway_container *container, bool warp) { |
296 | struct sway_container *last_focus = sway_seat_get_focus(seat); | 297 | struct sway_container *last_focus = sway_seat_get_focus(seat); |
297 | 298 | ||
298 | if (container && last_focus == container) { | 299 | if (container && last_focus == container) { |
@@ -333,15 +334,33 @@ void sway_seat_set_focus(struct sway_seat *seat, | |||
333 | if (last_focus) { | 334 | if (last_focus) { |
334 | struct sway_container *last_ws = last_focus; | 335 | struct sway_container *last_ws = last_focus; |
335 | if (last_ws && last_ws->type != C_WORKSPACE) { | 336 | if (last_ws && last_ws->type != C_WORKSPACE) { |
336 | last_ws = container_parent(last_focus, C_WORKSPACE); | 337 | last_ws = container_parent(last_ws, C_WORKSPACE); |
337 | } | 338 | } |
338 | if (last_ws) { | 339 | if (last_ws) { |
339 | wlr_log(L_DEBUG, "sending workspace event"); | ||
340 | ipc_event_workspace(last_ws, container, "focus"); | 340 | ipc_event_workspace(last_ws, container, "focus"); |
341 | if (last_ws->children->length == 0) { | 341 | if (last_ws->children->length == 0) { |
342 | container_workspace_destroy(last_ws); | 342 | container_workspace_destroy(last_ws); |
343 | } | 343 | } |
344 | } | 344 | } |
345 | struct sway_container *last_output = last_focus; | ||
346 | if (last_output && last_output->type != C_OUTPUT) { | ||
347 | last_output = container_parent(last_output, C_OUTPUT); | ||
348 | } | ||
349 | struct sway_container *new_output = container; | ||
350 | if (new_output && new_output->type != C_OUTPUT) { | ||
351 | new_output = container_parent(new_output, C_OUTPUT); | ||
352 | } | ||
353 | if (new_output && last_output && new_output != last_output | ||
354 | && config->mouse_warping && warp) { | ||
355 | struct wlr_output *output = new_output->sway_output->wlr_output; | ||
356 | double x = container->x + output->lx + container->width / 2.0; | ||
357 | double y = container->y + output->ly + container->height / 2.0; | ||
358 | if (!wlr_output_layout_contains_point( | ||
359 | root_container.sway_root->output_layout, | ||
360 | output, seat->cursor->cursor->x, seat->cursor->cursor->y)) { | ||
361 | wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); | ||
362 | } | ||
363 | } | ||
345 | } | 364 | } |
346 | 365 | ||
347 | if (last_focus && last_focus->type == C_VIEW && | 366 | if (last_focus && last_focus->type == C_VIEW && |
@@ -353,6 +372,11 @@ void sway_seat_set_focus(struct sway_seat *seat, | |||
353 | seat->has_focus = (container != NULL); | 372 | seat->has_focus = (container != NULL); |
354 | } | 373 | } |
355 | 374 | ||
375 | void sway_seat_set_focus(struct sway_seat *seat, | ||
376 | struct sway_container *container) { | ||
377 | sway_seat_set_focus_warp(seat, container, true); | ||
378 | } | ||
379 | |||
356 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { | 380 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { |
357 | struct sway_seat_container *current = NULL; | 381 | struct sway_seat_container *current = NULL; |
358 | struct sway_container *parent = NULL; | 382 | struct sway_container *parent = NULL; |
diff --git a/sway/meson.build b/sway/meson.build index e8a192f0..0cc620ea 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -13,6 +13,7 @@ sway_sources = files( | |||
13 | 'commands/exec.c', | 13 | 'commands/exec.c', |
14 | 'commands/exec_always.c', | 14 | 'commands/exec_always.c', |
15 | 'commands/focus.c', | 15 | 'commands/focus.c', |
16 | 'commands/focus_follows_mouse.c', | ||
16 | 'commands/kill.c', | 17 | 'commands/kill.c', |
17 | 'commands/include.c', | 18 | 'commands/include.c', |
18 | 'commands/input.c', | 19 | 'commands/input.c', |
@@ -63,6 +64,7 @@ sway_sources = files( | |||
63 | 'commands/input/xkb_options.c', | 64 | 'commands/input/xkb_options.c', |
64 | 'commands/input/xkb_rules.c', | 65 | 'commands/input/xkb_rules.c', |
65 | 'commands/input/xkb_variant.c', | 66 | 'commands/input/xkb_variant.c', |
67 | 'commands/mouse_warping.c', | ||
66 | 'commands/output.c', | 68 | 'commands/output.c', |
67 | 'commands/reload.c', | 69 | 'commands/reload.c', |
68 | 'commands/workspace.c', | 70 | 'commands/workspace.c', |