From ae6d459000865f0a3a54a1d0429ee28b282a7954 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 10:49:52 -0400 Subject: [PATCH 1/4] Implement mouse warping --- sway/commands.c | 1 + sway/commands/mouse_warping.c | 19 +++++++++++++++++++ sway/input/cursor.c | 4 ++-- sway/input/seat.c | 18 ++++++++++++++++-- sway/meson.build | 1 + 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 sway/commands/mouse_warping.c diff --git a/sway/commands.c b/sway/commands.c index eee7f254e..d983dcbb1 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -101,6 +101,7 @@ static struct cmd_handler handlers[] = { { "include", cmd_include }, { "input", cmd_input }, { "mode", cmd_mode }, + { "mouse_warping", cmd_mouse_warping }, { "output", cmd_output }, { "seat", cmd_seat }, { "workspace", cmd_workspace }, diff --git a/sway/commands/mouse_warping.c b/sway/commands/mouse_warping.c new file mode 100644 index 000000000..eef32ce78 --- /dev/null +++ b/sway/commands/mouse_warping.c @@ -0,0 +1,19 @@ +#include +#include +#include "sway/commands.h" + +struct cmd_results *cmd_mouse_warping(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) { + return error; + } else if (strcasecmp(argv[0], "output") == 0) { + config->mouse_warping = true; + } else if (strcasecmp(argv[0], "none") == 0) { + config->mouse_warping = false; + } else { + return cmd_results_new(CMD_FAILURE, "mouse_warping", + "Expected 'mouse_warping output|none'"); + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 74af64268..9cdd66d8e 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -156,8 +156,8 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { cursor_send_pointer_motion(cursor, event->time_msec); } -static void handle_cursor_motion_absolute(struct wl_listener *listener, - void *data) { +static void handle_cursor_motion_absolute( + struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; diff --git a/sway/input/seat.c b/sway/input/seat.c index 8d5928721..eab5cf40d 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -333,15 +333,29 @@ void sway_seat_set_focus(struct sway_seat *seat, if (last_focus) { struct sway_container *last_ws = last_focus; if (last_ws && last_ws->type != C_WORKSPACE) { - last_ws = container_parent(last_focus, C_WORKSPACE); + last_ws = container_parent(last_ws, C_WORKSPACE); } if (last_ws) { - wlr_log(L_DEBUG, "sending workspace event"); ipc_event_workspace(last_ws, container, "focus"); if (last_ws->children->length == 0) { container_workspace_destroy(last_ws); } } + struct sway_container *last_output = last_focus; + if (last_output && last_output->type != C_OUTPUT) { + last_output = container_parent(last_output, C_OUTPUT); + } + struct sway_container *new_output = container; + if (new_output && new_output->type != C_OUTPUT) { + new_output = container_parent(new_output, C_OUTPUT); + } + if (new_output != last_output && config->mouse_warping) { + struct wlr_output *output = new_output->sway_output->wlr_output; + // TODO: Change container coords to layout coords + double x = container->x + output->lx + container->width / 2.0; + double y = container->y + output->ly + container->height / 2.0; + wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + } } if (last_focus && last_focus->type == C_VIEW && diff --git a/sway/meson.build b/sway/meson.build index e8a192f03..5bc579648 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -63,6 +63,7 @@ sway_sources = files( 'commands/input/xkb_options.c', 'commands/input/xkb_rules.c', 'commands/input/xkb_variant.c', + 'commands/mouse_warping.c', 'commands/output.c', 'commands/reload.c', 'commands/workspace.c', From 9b38ef950fcf293ba11f54c14d8b3a87f050b154 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 10:11:15 -0400 Subject: [PATCH 2/4] Implement focus_follows_mouse Also contains two other small changes: - Clicking any button will focus the container clicked (not just left) - Remove seamless_mouse (doesn't make sense on wlroots) --- include/sway/config.h | 1 - sway/commands.c | 1 + sway/commands/focus_follows_mouse.c | 12 +++++++ sway/config.c | 1 - sway/input/cursor.c | 53 +++++++++++++++-------------- sway/meson.build | 1 + 6 files changed, 41 insertions(+), 28 deletions(-) create mode 100644 sway/commands/focus_follows_mouse.c diff --git a/include/sway/config.h b/include/sway/config.h index ac1105b49..03b51948c 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -304,7 +304,6 @@ struct sway_config { bool reloading; bool reading; bool auto_back_and_forth; - bool seamless_mouse; bool show_marks; bool edge_gaps; diff --git a/sway/commands.c b/sway/commands.c index d983dcbb1..905442208 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -98,6 +98,7 @@ static struct cmd_handler handlers[] = { { "bindsym", cmd_bindsym }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, + { "focus_follows_mouse", cmd_focus_follows_mouse }, { "include", cmd_include }, { "input", cmd_input }, { "mode", cmd_mode }, diff --git a/sway/commands/focus_follows_mouse.c b/sway/commands/focus_follows_mouse.c new file mode 100644 index 000000000..661e7852b --- /dev/null +++ b/sway/commands/focus_follows_mouse.c @@ -0,0 +1,12 @@ +#include +#include +#include "sway/commands.h" + +struct cmd_results *cmd_focus_follows_mouse(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1))) { + return error; + } + config->focus_follows_mouse = !strcasecmp(argv[0], "yes"); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index e9e7057d2..0eecf7f6c 100644 --- a/sway/config.c +++ b/sway/config.c @@ -178,7 +178,6 @@ static void config_defaults(struct sway_config *config) { config->active = false; config->failed = false; config->auto_back_and_forth = false; - config->seamless_mouse = true; config->reading = false; config->show_marks = true; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 9cdd66d8e..35dd5dc8e 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -125,7 +125,10 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, struct wlr_seat *seat = cursor->seat->wlr_seat; struct wlr_surface *surface = NULL; double sx, sy; - container_at_cursor(cursor, &surface, &sx, &sy); + struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); + if (c && config->focus_follows_mouse) { + sway_seat_set_focus(cursor->seat, c); + } // reset cursor if switching between clients struct wl_client *client = NULL; @@ -170,33 +173,31 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, button); struct wlr_event_pointer_button *event = data; - if (event->button == BTN_LEFT) { - struct wlr_surface *surface = NULL; - double sx, sy; - struct sway_container *cont = - container_at_cursor(cursor, &surface, &sx, &sy); - // 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) { - new_ws = container_parent(new_ws, C_WORKSPACE); - } - struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); - if (old_ws && old_ws->type != C_WORKSPACE) { - old_ws = container_parent(old_ws, C_WORKSPACE); - } - if (new_ws != old_ws) { - sway_seat_set_focus(cursor->seat, cont); - } - } else { + struct wlr_surface *surface = NULL; + double sx, sy; + struct sway_container *cont = + container_at_cursor(cursor, &surface, &sx, &sy); + // 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) { + new_ws = container_parent(new_ws, C_WORKSPACE); + } + struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); + if (old_ws && old_ws->type != C_WORKSPACE) { + old_ws = container_parent(old_ws, C_WORKSPACE); + } + if (new_ws != old_ws) { sway_seat_set_focus(cursor->seat, cont); } + } else { + sway_seat_set_focus(cursor->seat, cont); } wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, diff --git a/sway/meson.build b/sway/meson.build index 5bc579648..0cc620ea8 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -13,6 +13,7 @@ sway_sources = files( 'commands/exec.c', 'commands/exec_always.c', 'commands/focus.c', + 'commands/focus_follows_mouse.c', 'commands/kill.c', 'commands/include.c', 'commands/input.c', From b9d2983324c91f0a2805b1f10afcf2a929f939b4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 11:18:29 -0400 Subject: [PATCH 3/4] Fix interaction between warping and following --- sway/input/cursor.c | 5 ++++- sway/input/seat.c | 13 ++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 35dd5dc8e..2a0960336 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -120,6 +120,9 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return NULL; } +void _sway_seat_set_focus(struct sway_seat *seat, + struct sway_container *container, bool warp); + static void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) { struct wlr_seat *seat = cursor->seat->wlr_seat; @@ -127,7 +130,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, double sx, sy; struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); if (c && config->focus_follows_mouse) { - sway_seat_set_focus(cursor->seat, c); + _sway_seat_set_focus(cursor->seat, c, false); } // reset cursor if switching between clients diff --git a/sway/input/seat.c b/sway/input/seat.c index eab5cf40d..4e7e018de 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -291,8 +291,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -void sway_seat_set_focus(struct sway_seat *seat, - struct sway_container *container) { +void _sway_seat_set_focus(struct sway_seat *seat, + struct sway_container *container, bool warp) { struct sway_container *last_focus = sway_seat_get_focus(seat); if (container && last_focus == container) { @@ -349,7 +349,9 @@ void sway_seat_set_focus(struct sway_seat *seat, if (new_output && new_output->type != C_OUTPUT) { new_output = container_parent(new_output, C_OUTPUT); } - if (new_output != last_output && config->mouse_warping) { + if (new_output && last_output && new_output != last_output + && config->mouse_warping && warp) { + wlr_log(L_DEBUG, "warpin the mouse baby"); struct wlr_output *output = new_output->sway_output->wlr_output; // TODO: Change container coords to layout coords double x = container->x + output->lx + container->width / 2.0; @@ -367,6 +369,11 @@ void sway_seat_set_focus(struct sway_seat *seat, seat->has_focus = (container != NULL); } +void sway_seat_set_focus(struct sway_seat *seat, + struct sway_container *container) { + _sway_seat_set_focus(seat, container, true); +} + struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { struct sway_seat_container *current = NULL; struct sway_container *parent = NULL; From f2332dc75c05a62f87ba290433f12f4ce7f467ec Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 15:13:27 -0400 Subject: [PATCH 4/4] Address review feedback --- include/sway/input/seat.h | 3 +++ sway/input/cursor.c | 5 +---- sway/input/seat.c | 13 ++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 496bfd5d0..31210a5a1 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); void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); +void sway_seat_set_focus_warp(struct sway_seat *seat, + struct sway_container *container, bool warp); + struct sway_container *sway_seat_get_focus(struct sway_seat *seat); /** diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 2a0960336..4a3f558d4 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -120,9 +120,6 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return NULL; } -void _sway_seat_set_focus(struct sway_seat *seat, - struct sway_container *container, bool warp); - static void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) { struct wlr_seat *seat = cursor->seat->wlr_seat; @@ -130,7 +127,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, double sx, sy; struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); if (c && config->focus_follows_mouse) { - _sway_seat_set_focus(cursor->seat, c, false); + sway_seat_set_focus_warp(cursor->seat, c, false); } // reset cursor if switching between clients diff --git a/sway/input/seat.c b/sway/input/seat.c index 4e7e018de..9aa34acac 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,5 +1,6 @@ #define _XOPEN_SOURCE 700 #include +#include #include #include "sway/tree/container.h" #include "sway/input/seat.h" @@ -291,7 +292,7 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -void _sway_seat_set_focus(struct sway_seat *seat, +void sway_seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { struct sway_container *last_focus = sway_seat_get_focus(seat); @@ -351,12 +352,14 @@ void _sway_seat_set_focus(struct sway_seat *seat, } if (new_output && last_output && new_output != last_output && config->mouse_warping && warp) { - wlr_log(L_DEBUG, "warpin the mouse baby"); struct wlr_output *output = new_output->sway_output->wlr_output; - // TODO: Change container coords to layout coords double x = container->x + output->lx + container->width / 2.0; double y = container->y + output->ly + container->height / 2.0; - wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + if (!wlr_output_layout_contains_point( + root_container.sway_root->output_layout, + output, seat->cursor->cursor->x, seat->cursor->cursor->y)) { + wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); + } } } @@ -371,7 +374,7 @@ void _sway_seat_set_focus(struct sway_seat *seat, void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container) { - _sway_seat_set_focus(seat, container, true); + sway_seat_set_focus_warp(seat, container, true); } struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) {