summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/commands.h1
-rw-r--r--include/container.h2
-rw-r--r--include/handlers.h4
-rw-r--r--include/input_state.h8
-rw-r--r--sway.5.txt4
-rw-r--r--sway/commands.c34
-rw-r--r--sway/container.c65
-rw-r--r--sway/focus.c26
-rw-r--r--sway/handlers.c88
-rw-r--r--sway/input_state.c43
10 files changed, 166 insertions, 109 deletions
diff --git a/include/commands.h b/include/commands.h
index 8e53c74d..f6777930 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -2,6 +2,7 @@
2#define _SWAY_COMMANDS_H 2#define _SWAY_COMMANDS_H
3#include <stdbool.h> 3#include <stdbool.h>
4#include <json-c/json.h> 4#include <json-c/json.h>
5#include <wlc/wlc.h>
5#include "config.h" 6#include "config.h"
6 7
7 8
diff --git a/include/container.h b/include/container.h
index ae9a9fc5..d5eb27c1 100644
--- a/include/container.h
+++ b/include/container.h
@@ -98,6 +98,8 @@ swayc_t *swayc_by_name(const char *name);
98swayc_t *swayc_active_output(void); 98swayc_t *swayc_active_output(void);
99swayc_t *swayc_active_workspace(void); 99swayc_t *swayc_active_workspace(void);
100swayc_t *swayc_active_workspace_for(swayc_t *view); 100swayc_t *swayc_active_workspace_for(swayc_t *view);
101// set focus to current pointer location and return focused container
102swayc_t *container_under_pointer(void);
101 103
102// Container information 104// Container information
103 105
diff --git a/include/handlers.h b/include/handlers.h
index 4c71f953..d7f6ffdd 100644
--- a/include/handlers.h
+++ b/include/handlers.h
@@ -5,10 +5,6 @@
5#include <wlc/wlc.h> 5#include <wlc/wlc.h>
6 6
7extern struct wlc_interface interface; 7extern struct wlc_interface interface;
8extern struct wlc_origin mouse_origin;
9extern uint32_t keys_pressed[32]; 8extern uint32_t keys_pressed[32];
10 9
11// set focus to current pointer location and return focused container
12swayc_t *container_under_pointer(void);
13
14#endif 10#endif
diff --git a/include/input_state.h b/include/input_state.h
index d87ae18c..a1f238e1 100644
--- a/include/input_state.h
+++ b/include/input_state.h
@@ -48,11 +48,6 @@ extern struct pointer_state {
48 struct pointer_button_state right; 48 struct pointer_button_state right;
49 struct pointer_button_state scroll; 49 struct pointer_button_state scroll;
50 50
51 // pointer position
52 struct mouse_origin{
53 int x, y;
54 } origin;
55
56 // change in pointer position 51 // change in pointer position
57 struct { 52 struct {
58 int x, y; 53 int x, y;
@@ -65,6 +60,9 @@ extern struct pointer_state {
65 int mode; 60 int mode;
66} pointer_state; 61} pointer_state;
67 62
63void pointer_position_set(struct wlc_origin *new_origin, bool force_focus);
64void center_pointer_on(swayc_t *view);
65
68// on button release unset mode depending on the button. 66// on button release unset mode depending on the button.
69// on button press set mode conditionally depending on the button 67// on button press set mode conditionally depending on the button
70void pointer_mode_set(uint32_t button, bool condition); 68void pointer_mode_set(uint32_t button, bool condition);
diff --git a/sway.5.txt b/sway.5.txt
index dad55c5f..27735db6 100644
--- a/sway.5.txt
+++ b/sway.5.txt
@@ -102,6 +102,10 @@ Commands
102 Moves the focused container to the workspace identified by _name_. 102 Moves the focused container to the workspace identified by _name_.
103 _name_ may be a special workspace name. See **workspace**. 103 _name_ may be a special workspace name. See **workspace**.
104 104
105**mouse_warping** <output|none>::
106 When _output_: place mouse at center of newly focused window when changing
107 output. When _none_: don't move mouse.
108
105**output** <name> <resolution|res WIDTHxHEIGHT> <position|pos X,Y>:: 109**output** <name> <resolution|res WIDTHxHEIGHT> <position|pos X,Y>::
106 Configures the specified output. It will use the given resolution and be 110 Configures the specified output. It will use the given resolution and be
107 arranged at the given position in the layout tree. You may omit either of 111 arranged at the given position in the layout tree. You may omit either of
diff --git a/sway/commands.c b/sway/commands.c
index 441b6fd7..00a4d1b0 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -21,6 +21,7 @@
21#include "handlers.h" 21#include "handlers.h"
22#include "sway.h" 22#include "sway.h"
23#include "resize.h" 23#include "resize.h"
24#include "input_state.h"
24 25
25typedef struct cmd_results *sway_cmd(int argc, char **argv); 26typedef struct cmd_results *sway_cmd(int argc, char **argv);
26 27
@@ -45,6 +46,7 @@ static sway_cmd cmd_kill;
45static sway_cmd cmd_layout; 46static sway_cmd cmd_layout;
46static sway_cmd cmd_log_colors; 47static sway_cmd cmd_log_colors;
47static sway_cmd cmd_mode; 48static sway_cmd cmd_mode;
49static sway_cmd cmd_mouse_warping;
48static sway_cmd cmd_move; 50static sway_cmd cmd_move;
49static sway_cmd cmd_output; 51static sway_cmd cmd_output;
50static sway_cmd cmd_reload; 52static sway_cmd cmd_reload;
@@ -383,9 +385,13 @@ static struct cmd_results *cmd_focus(int argc, char **argv) {
383 } else if (!workspace_switch(swayc_active_workspace_for(output))) { 385 } else if (!workspace_switch(swayc_active_workspace_for(output))) {
384 return cmd_results_new(CMD_FAILURE, "focus output", 386 return cmd_results_new(CMD_FAILURE, "focus output",
385 "Switching to workspace on output '%s' was blocked", argv[1]); 387 "Switching to workspace on output '%s' was blocked", argv[1]);
386 } else { 388 } else if (config->mouse_warping) {
387 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 389 swayc_t *focused = get_focused_view(output);
390 if (focused && focused->type == C_VIEW) {
391 center_pointer_on(focused);
392 }
388 } 393 }
394 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
389 } else if ((error = checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1))) { 395 } else if ((error = checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1))) {
390 return error; 396 return error;
391 } 397 }
@@ -528,6 +534,20 @@ static struct cmd_results *cmd_mode(int argc, char **argv) {
528 return cmd_results_new(mode_make ? CMD_BLOCK_MODE : CMD_SUCCESS, NULL, NULL); 534 return cmd_results_new(mode_make ? CMD_BLOCK_MODE : CMD_SUCCESS, NULL, NULL);
529} 535}
530 536
537static struct cmd_results *cmd_mouse_warping(int argc, char **argv) {
538 struct cmd_results *error = NULL;
539 if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) {
540 return error;
541 } else if (strcasecmp(argv[0], "output") == 0) {
542 config->mouse_warping = true;
543 } else if (strcasecmp(argv[0], "none") == 0) {
544 config->mouse_warping = false;
545 } else {
546 return cmd_results_new(CMD_FAILURE, "mouse_warping", "Expected 'mouse_warping output|none'");
547 }
548 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
549}
550
531static struct cmd_results *cmd_move(int argc, char **argv) { 551static struct cmd_results *cmd_move(int argc, char **argv) {
532 struct cmd_results *error = NULL; 552 struct cmd_results *error = NULL;
533 if (config->reading) return cmd_results_new(CMD_FAILURE, "move", "Can't be used in config file."); 553 if (config->reading) return cmd_results_new(CMD_FAILURE, "move", "Can't be used in config file.");
@@ -1165,7 +1185,16 @@ static struct cmd_results *cmd_workspace(int argc, char **argv) {
1165 ws = workspace_create(argv[0]); 1185 ws = workspace_create(argv[0]);
1166 } 1186 }
1167 } 1187 }
1188 swayc_t *old_output = swayc_active_output();
1168 workspace_switch(ws); 1189 workspace_switch(ws);
1190 swayc_t *new_output = swayc_active_output();
1191
1192 if (config->mouse_warping && old_output != new_output) {
1193 swayc_t *focused = get_focused_view(ws);
1194 if (focused && focused->type == C_VIEW) {
1195 center_pointer_on(focused);
1196 }
1197 }
1169 } else { 1198 } else {
1170 if (strcasecmp(argv[1], "output") == 0) { 1199 if (strcasecmp(argv[1], "output") == 0) {
1171 if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3))) { 1200 if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3))) {
@@ -1217,6 +1246,7 @@ static struct cmd_handler handlers[] = {
1217 { "layout", cmd_layout }, 1246 { "layout", cmd_layout },
1218 { "log_colors", cmd_log_colors }, 1247 { "log_colors", cmd_log_colors },
1219 { "mode", cmd_mode }, 1248 { "mode", cmd_mode },
1249 { "mouse_warping", cmd_mouse_warping },
1220 { "move", cmd_move }, 1250 { "move", cmd_move },
1221 { "output", cmd_output }, 1251 { "output", cmd_output },
1222 { "reload", cmd_reload }, 1252 { "reload", cmd_reload },
diff --git a/sway/container.c b/sway/container.c
index 6c4206fb..f3e2b3ae 100644
--- a/sway/container.c
+++ b/sway/container.c
@@ -8,6 +8,7 @@
8#include "workspace.h" 8#include "workspace.h"
9#include "focus.h" 9#include "focus.h"
10#include "layout.h" 10#include "layout.h"
11#include "input_state.h"
11#include "log.h" 12#include "log.h"
12 13
13#define ASSERT_NONNULL(PTR) \ 14#define ASSERT_NONNULL(PTR) \
@@ -508,6 +509,70 @@ swayc_t *swayc_active_workspace_for(swayc_t *cont) {
508 } 509 }
509} 510}
510 511
512static bool pointer_test(swayc_t *view, void *_origin) {
513 const struct wlc_origin *origin = _origin;
514 // Determine the output that the view is under
515 swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
516 if (origin->x >= view->x && origin->y >= view->y
517 && origin->x < view->x + view->width && origin->y < view->y + view->height
518 && view->visible && parent == root_container.focused) {
519 return true;
520 }
521 return false;
522}
523
524swayc_t *container_under_pointer(void) {
525 // root.output->workspace
526 if (!root_container.focused || !root_container.focused->focused) {
527 return NULL;
528 }
529 swayc_t *lookup = root_container.focused->focused;
530 // Case of empty workspace
531 if (lookup->children == 0) {
532 return NULL;
533 }
534 struct wlc_origin origin;
535 wlc_pointer_get_origin(&origin);
536 while (lookup->type != C_VIEW) {
537 int i;
538 int len;
539 // if tabbed/stacked go directly to focused container, otherwise search
540 // children
541 if (lookup->layout == L_TABBED || lookup->layout == L_STACKED) {
542 lookup = lookup->focused;
543 continue;
544 }
545 // if workspace, search floating
546 if (lookup->type == C_WORKSPACE) {
547 i = len = lookup->floating->length;
548 bool got_floating = false;
549 while (--i > -1) {
550 if (pointer_test(lookup->floating->items[i], &origin)) {
551 lookup = lookup->floating->items[i];
552 got_floating = true;
553 break;
554 }
555 }
556 if (got_floating) {
557 continue;
558 }
559 }
560 // search children
561 len = lookup->children->length;
562 for (i = 0; i < len; ++i) {
563 if (pointer_test(lookup->children->items[i], &origin)) {
564 lookup = lookup->children->items[i];
565 break;
566 }
567 }
568 // when border and titles are done, this could happen
569 if (i == len) {
570 break;
571 }
572 }
573 return lookup;
574}
575
511// Container information 576// Container information
512 577
513bool swayc_is_fullscreen(swayc_t *view) { 578bool swayc_is_fullscreen(swayc_t *view) {
diff --git a/sway/focus.c b/sway/focus.c
index 1aa7579b..7f0b1599 100644
--- a/sway/focus.c
+++ b/sway/focus.c
@@ -4,6 +4,8 @@
4#include "log.h" 4#include "log.h"
5#include "workspace.h" 5#include "workspace.h"
6#include "layout.h" 6#include "layout.h"
7#include "config.h"
8#include "input_state.h"
7 9
8bool locked_container_focus = false; 10bool locked_container_focus = false;
9bool locked_view_focus = false; 11bool locked_view_focus = false;
@@ -49,14 +51,24 @@ static void update_focus(swayc_t *c) {
49} 51}
50 52
51bool move_focus(enum movement_direction direction) { 53bool move_focus(enum movement_direction direction) {
52 swayc_t *view = get_focused_container(&root_container); 54 swayc_t *old_view = get_focused_container(&root_container);
53 view = get_swayc_in_direction(view, direction); 55 swayc_t *new_view = get_swayc_in_direction(old_view, direction);
54 if (view) { 56 if (!new_view) {
55 if (direction == MOVE_PARENT) { 57 return false;
56 return set_focused_container(view); 58 } else if (direction == MOVE_PARENT) {
57 } else { 59 return set_focused_container(new_view);
58 return set_focused_container(get_focused_view(view)); 60 } else if (config->mouse_warping) {
61 swayc_t *old_op = old_view->type == C_OUTPUT ?
62 old_view : swayc_parent_by_type(old_view, C_OUTPUT);
63 swayc_t *focused = get_focused_view(new_view);
64 if (set_focused_container(focused)) {
65 if (old_op != swayc_active_output() && focused && focused->type == C_VIEW) {
66 center_pointer_on(focused);
67 }
68 return true;
59 } 69 }
70 } else {
71 return set_focused_container(get_focused_view(new_view));
60 } 72 }
61 return false; 73 return false;
62} 74}
diff --git a/sway/handlers.c b/sway/handlers.c
index 1c5abca6..510b4261 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -24,68 +24,6 @@
24// Event handled by sway and should not be sent to client 24// Event handled by sway and should not be sent to client
25#define EVENT_HANDLED true 25#define EVENT_HANDLED true
26 26
27static bool pointer_test(swayc_t *view, void *_origin) {
28 const struct mouse_origin *origin = _origin;
29 // Determine the output that the view is under
30 swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
31 if (origin->x >= view->x && origin->y >= view->y
32 && origin->x < view->x + view->width && origin->y < view->y + view->height
33 && view->visible && parent == root_container.focused) {
34 return true;
35 }
36 return false;
37}
38
39swayc_t *container_under_pointer(void) {
40 // root.output->workspace
41 if (!root_container.focused || !root_container.focused->focused) {
42 return NULL;
43 }
44 swayc_t *lookup = root_container.focused->focused;
45 // Case of empty workspace
46 if (lookup->children == 0) {
47 return NULL;
48 }
49 while (lookup->type != C_VIEW) {
50 int i;
51 int len;
52 // if tabbed/stacked go directly to focused container, otherwise search
53 // children
54 if (lookup->layout == L_TABBED || lookup->layout == L_STACKED) {
55 lookup = lookup->focused;
56 continue;
57 }
58 // if workspace, search floating
59 if (lookup->type == C_WORKSPACE) {
60 i = len = lookup->floating->length;
61 bool got_floating = false;
62 while (--i > -1) {
63 if (pointer_test(lookup->floating->items[i], &pointer_state.origin)) {
64 lookup = lookup->floating->items[i];
65 got_floating = true;
66 break;
67 }
68 }
69 if (got_floating) {
70 continue;
71 }
72 }
73 // search children
74 len = lookup->children->length;
75 for (i = 0; i < len; ++i) {
76 if (pointer_test(lookup->children->items[i], &pointer_state.origin)) {
77 lookup = lookup->children->items[i];
78 break;
79 }
80 }
81 // when border and titles are done, this could happen
82 if (i == len) {
83 break;
84 }
85 }
86 return lookup;
87}
88
89/* Handles */ 27/* Handles */
90 28
91static bool handle_output_created(wlc_handle output) { 29static bool handle_output_created(wlc_handle output) {
@@ -394,27 +332,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct
394 } 332 }
395 } 333 }
396 334
397 // Update pointer origin 335 pointer_position_set(&new_origin, false);
398 pointer_state.delta.x = origin->x - pointer_state.origin.x;
399 pointer_state.delta.y = origin->y - pointer_state.origin.y;
400 pointer_state.origin.x = origin->x;
401 pointer_state.origin.y = origin->y;
402
403 // Update view under pointer
404 swayc_t *prev_view = pointer_state.view;
405 pointer_state.view = container_under_pointer();
406
407 // If pointer is in a mode, update it
408 if (pointer_state.mode) {
409 pointer_mode_update();
410 }
411 // Otherwise change focus if config is set an
412 else if (prev_view != pointer_state.view && config->focus_follows_mouse) {
413 if (pointer_state.view && pointer_state.view->type == C_VIEW) {
414 set_focused_container(pointer_state.view);
415 }
416 }
417 wlc_pointer_set_origin(&new_origin);
418 return EVENT_PASSTHROUGH; 336 return EVENT_PASSTHROUGH;
419} 337}
420 338
@@ -425,10 +343,6 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
425 // Update view pointer is on 343 // Update view pointer is on
426 pointer_state.view = container_under_pointer(); 344 pointer_state.view = container_under_pointer();
427 345
428 // Update pointer origin
429 pointer_state.origin.x = origin->x;
430 pointer_state.origin.y = origin->y;
431
432 // Update pointer_state 346 // Update pointer_state
433 switch (button) { 347 switch (button) {
434 case M_LEFT_CLICK: 348 case M_LEFT_CLICK:
diff --git a/sway/input_state.c b/sway/input_state.c
index 2743a9ea..9bd8ad4d 100644
--- a/sway/input_state.c
+++ b/sway/input_state.c
@@ -2,6 +2,7 @@
2#include <stdbool.h> 2#include <stdbool.h>
3#include <ctype.h> 3#include <ctype.h>
4#include "log.h" 4#include "log.h"
5#include "config.h"
5 6
6#include "input_state.h" 7#include "input_state.h"
7 8
@@ -161,6 +162,36 @@ static void reset_initial_sibling(void) {
161 pointer_state.mode = 0; 162 pointer_state.mode = 0;
162} 163}
163 164
165void pointer_position_set(struct wlc_origin *new_origin, bool force_focus) {
166 struct wlc_origin origin;
167 wlc_pointer_get_origin(&origin);
168 pointer_state.delta.x = new_origin->x - origin.x;
169 pointer_state.delta.y = new_origin->y - origin.y;
170
171 // Update view under pointer
172 swayc_t *prev_view = pointer_state.view;
173 pointer_state.view = container_under_pointer();
174
175 // If pointer is in a mode, update it
176 if (pointer_state.mode) {
177 pointer_mode_update();
178 // Otherwise change focus if config is set
179 } else if (force_focus || (prev_view != pointer_state.view && config->focus_follows_mouse)) {
180 if (pointer_state.view && pointer_state.view->type == C_VIEW) {
181 set_focused_container(pointer_state.view);
182 }
183 }
184
185 wlc_pointer_set_origin(new_origin);
186}
187
188void center_pointer_on(swayc_t *view) {
189 struct wlc_origin new_origin;
190 new_origin.x = view->x + view->width/2;
191 new_origin.y = view->y + view->height/2;
192 pointer_position_set(&new_origin, true);
193}
194
164// Mode set left/right click 195// Mode set left/right click
165 196
166static void pointer_mode_set_left(void) { 197static void pointer_mode_set_left(void) {
@@ -183,8 +214,10 @@ static void pointer_mode_set_right(void) {
183 int midway_x = initial.ptr->x + initial.ptr->width/2; 214 int midway_x = initial.ptr->x + initial.ptr->width/2;
184 int midway_y = initial.ptr->y + initial.ptr->height/2; 215 int midway_y = initial.ptr->y + initial.ptr->height/2;
185 216
186 lock.left = pointer_state.origin.x > midway_x; 217 struct wlc_origin origin;
187 lock.top = pointer_state.origin.y > midway_y; 218 wlc_pointer_get_origin(&origin);
219 lock.left = origin.x > midway_x;
220 lock.top = origin.y > midway_y;
188 221
189 if (initial.ptr->is_floating) { 222 if (initial.ptr->is_floating) {
190 pointer_state.mode = M_RESIZING | M_FLOATING; 223 pointer_state.mode = M_RESIZING | M_FLOATING;
@@ -246,8 +279,10 @@ void pointer_mode_update(void) {
246 pointer_state.mode = 0; 279 pointer_state.mode = 0;
247 return; 280 return;
248 } 281 }
249 int dx = pointer_state.origin.x; 282 struct wlc_origin origin;
250 int dy = pointer_state.origin.y; 283 wlc_pointer_get_origin(&origin);
284 int dx = origin.x;
285 int dy = origin.y;
251 286
252 switch (pointer_state.mode) { 287 switch (pointer_state.mode) {
253 case M_FLOATING | M_DRAGGING: 288 case M_FLOATING | M_DRAGGING: