summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/input/cursor.h9
-rw-r--r--sway/commands/border.c2
-rw-r--r--sway/commands/seat/cursor.c4
-rw-r--r--sway/input/cursor.c84
-rw-r--r--sway/input/seat.c4
5 files changed, 56 insertions, 47 deletions
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h
index 2141361d..03cb8b83 100644
--- a/include/sway/input/cursor.h
+++ b/include/sway/input/cursor.h
@@ -6,6 +6,7 @@
6struct sway_cursor { 6struct sway_cursor {
7 struct sway_seat *seat; 7 struct sway_seat *seat;
8 struct wlr_cursor *cursor; 8 struct wlr_cursor *cursor;
9 struct cursor_position *previous;
9 struct wlr_xcursor_manager *xcursor_manager; 10 struct wlr_xcursor_manager *xcursor_manager;
10 11
11 struct wl_client *image_client; 12 struct wl_client *image_client;
@@ -27,10 +28,14 @@ struct sway_cursor {
27 struct wl_listener request_set_cursor; 28 struct wl_listener request_set_cursor;
28}; 29};
29 30
31struct cursor_position {
32 double x, y;
33};
34
30void sway_cursor_destroy(struct sway_cursor *cursor); 35void sway_cursor_destroy(struct sway_cursor *cursor);
31struct sway_cursor *sway_cursor_create(struct sway_seat *seat); 36struct sway_cursor *sway_cursor_create(struct sway_seat *seat);
32void cursor_send_pointer_motion(struct sway_cursor *cursor, 37void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
33 double delta_x, double delta_y, uint32_t time_msec, bool allow_refocusing); 38 bool allow_refocusing);
34void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, 39void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec,
35 uint32_t button, enum wlr_button_state state); 40 uint32_t button, enum wlr_button_state state);
36 41
diff --git a/sway/commands/border.c b/sway/commands/border.c
index 5160eaa6..4ba361da 100644
--- a/sway/commands/border.c
+++ b/sway/commands/border.c
@@ -41,7 +41,7 @@ struct cmd_results *cmd_border(int argc, char **argv) {
41 41
42 struct sway_seat *seat = input_manager_current_seat(input_manager); 42 struct sway_seat *seat = input_manager_current_seat(input_manager);
43 if (seat->cursor) { 43 if (seat->cursor) {
44 cursor_send_pointer_motion(seat->cursor, 0, 0, 0, false); 44 cursor_send_pointer_motion(seat->cursor, 0, false);
45 } 45 }
46 46
47 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 47 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c
index 81fee31f..4d0a22c7 100644
--- a/sway/commands/seat/cursor.c
+++ b/sway/commands/seat/cursor.c
@@ -36,7 +36,7 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
36 int delta_x = strtol(argv[1], NULL, 10); 36 int delta_x = strtol(argv[1], NULL, 10);
37 int delta_y = strtol(argv[2], NULL, 10); 37 int delta_y = strtol(argv[2], NULL, 10);
38 wlr_cursor_move(cursor->cursor, NULL, delta_x, delta_y); 38 wlr_cursor_move(cursor->cursor, NULL, delta_x, delta_y);
39 cursor_send_pointer_motion(cursor, 0, 0, 0, true); 39 cursor_send_pointer_motion(cursor, 0, true);
40 } else if (strcasecmp(argv[0], "set") == 0) { 40 } else if (strcasecmp(argv[0], "set") == 0) {
41 if (argc < 3) { 41 if (argc < 3) {
42 return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); 42 return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
@@ -45,7 +45,7 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
45 float x = strtof(argv[1], NULL) / root_container.width; 45 float x = strtof(argv[1], NULL) / root_container.width;
46 float y = strtof(argv[2], NULL) / root_container.height; 46 float y = strtof(argv[2], NULL) / root_container.height;
47 wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y); 47 wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y);
48 cursor_send_pointer_motion(cursor, 0, 0, 0, true); 48 cursor_send_pointer_motion(cursor, 0, true);
49 } else { 49 } else {
50 if (argc < 2) { 50 if (argc < 2) {
51 return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); 51 return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index cc8d344f..a318bbd4 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -135,25 +135,23 @@ static struct sway_container *container_at_coords(
135 return output->swayc; 135 return output->swayc;
136} 136}
137 137
138void cursor_send_pointer_motion(struct sway_cursor *cursor, 138void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
139 double delta_x, double delta_y, uint32_t time_msec, bool allow_refocusing) { 139 bool allow_refocusing) {
140 struct sway_container *prev_c = NULL;
141 struct wlr_surface *surface = NULL;
142 double sx, sy;
143
144 if (delta_x != 0 || delta_y != 0) {
145 // Use the motion delta to find the container the pointer was previously
146 // over.
147 prev_c = container_at_coords(cursor->seat,
148 cursor->cursor->x - delta_x, cursor->cursor->y - delta_y,
149 &surface, &sx, &sy);
150 }
151
152 if (time_msec == 0) { 140 if (time_msec == 0) {
153 time_msec = get_current_time_msec(); 141 time_msec = get_current_time_msec();
154 } 142 }
155 143
156 struct wlr_seat *seat = cursor->seat->wlr_seat; 144 struct wlr_seat *seat = cursor->seat->wlr_seat;
145 struct wlr_surface *surface = NULL;
146 double sx, sy;
147
148 // Find the container the pointer was previously over
149 struct sway_container *prev_c = container_at_coords(cursor->seat,
150 cursor->previous->x, cursor->previous->y, &surface, &sx, &sy);
151 // Update the stored previous position
152 cursor->previous->x = cursor->cursor->x;
153 cursor->previous->y = cursor->cursor->y;
154
157 struct sway_container *c = container_at_coords(cursor->seat, 155 struct sway_container *c = container_at_coords(cursor->seat,
158 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); 156 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
159 if (c && config->focus_follows_mouse && allow_refocusing) { 157 if (c && config->focus_follows_mouse && allow_refocusing) {
@@ -173,39 +171,38 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor,
173 } 171 }
174 } else if (c->type == C_VIEW) { 172 } else if (c->type == C_VIEW) {
175 bool do_mouse_focus = true; 173 bool do_mouse_focus = true;
174 bool is_visible = view_is_visible(c->sway_view);
176 struct sway_container *p = c->parent; 175 struct sway_container *p = c->parent;
177 // Don't switch focus unless we have moved from one container to another. 176 // Don't switch focus unless we have moved from one container to another
178 if (c && prev_c && c == prev_c) { 177 if (c && c == prev_c) {
179 do_mouse_focus = false; 178 do_mouse_focus = false;
180 } 179 }
181 // Skip check if we already know not to focus. 180 // Don't switch focus on title mouseover for stacked and tabbed layouts
182 if (do_mouse_focus) { 181 // If pointed container is in nested containers which are inside
183 // Don't switch focus on title mouseover for 182 // tabbed/stacked layout we should skip them
184 // stacked and tabbed layouts 183 if (do_mouse_focus && !is_visible) {
185 // If pointed container is in nested containers which are
186 // inside tabbed/stacked layout we should skip them
187 bool is_visible = view_is_visible(c->sway_view);
188 while (p) { 184 while (p) {
189 if ((p->layout == L_TABBED || p->layout == L_STACKED) 185 if ((p->layout == L_TABBED || p->layout == L_STACKED)) {
190 && !is_visible) {
191 do_mouse_focus = false; 186 do_mouse_focus = false;
192 break; 187 break;
193 } 188 }
194 p = p->parent; 189 p = p->parent;
195 } 190 }
196 } 191 }
197 if (!do_mouse_focus) { 192 if (do_mouse_focus) {
198 struct sway_container *next_focus = seat_get_focus_inactive(
199 cursor->seat, p);
200 if(next_focus && !sway_assert(next_focus->type == C_VIEW,
201 "focus inactive container is not a view")) {
202 return;
203 }
204 if (next_focus && view_is_visible(next_focus->sway_view)) {
205 seat_set_focus_warp(cursor->seat, next_focus, false);
206 }
207 } else {
208 seat_set_focus_warp(cursor->seat, c, false); 193 seat_set_focus_warp(cursor->seat, c, false);
194 } else {
195 struct sway_container *next_focus =
196 seat_get_focus_inactive(cursor->seat, &root_container);
197 if (next_focus) {
198 if (!sway_assert(next_focus->type == C_VIEW,
199 "focus inactive container is not a view")) {
200 return;
201 }
202 if (view_is_visible(next_focus->sway_view)) {
203 seat_set_focus_warp(cursor->seat, next_focus, false);
204 }
205 }
209 } 206 }
210 } 207 }
211 } 208 }
@@ -238,8 +235,7 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) {
238 struct wlr_event_pointer_motion *event = data; 235 struct wlr_event_pointer_motion *event = data;
239 wlr_cursor_move(cursor->cursor, event->device, 236 wlr_cursor_move(cursor->cursor, event->device,
240 event->delta_x, event->delta_y); 237 event->delta_x, event->delta_y);
241 cursor_send_pointer_motion(cursor, event->delta_x, event->delta_y, 238 cursor_send_pointer_motion(cursor, event->time_msec, true);
242 event->time_msec, true);
243} 239}
244 240
245static void handle_cursor_motion_absolute( 241static void handle_cursor_motion_absolute(
@@ -249,7 +245,7 @@ static void handle_cursor_motion_absolute(
249 wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); 245 wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
250 struct wlr_event_pointer_motion_absolute *event = data; 246 struct wlr_event_pointer_motion_absolute *event = data;
251 wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); 247 wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y);
252 cursor_send_pointer_motion(cursor, 0, 0, event->time_msec, true); 248 cursor_send_pointer_motion(cursor, event->time_msec, true);
253} 249}
254 250
255void dispatch_cursor_button(struct sway_cursor *cursor, 251void dispatch_cursor_button(struct sway_cursor *cursor,
@@ -419,7 +415,7 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) {
419 } 415 }
420 416
421 wlr_cursor_warp_absolute(cursor->cursor, event->device, x, y); 417 wlr_cursor_warp_absolute(cursor->cursor, event->device, x, y);
422 cursor_send_pointer_motion(cursor, 0, 0, event->time_msec, true); 418 cursor_send_pointer_motion(cursor, event->time_msec, true);
423} 419}
424 420
425static void handle_tool_tip(struct wl_listener *listener, void *data) { 421static void handle_tool_tip(struct wl_listener *listener, void *data) {
@@ -496,8 +492,15 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
496 return NULL; 492 return NULL;
497 } 493 }
498 494
495 struct cursor_position *previous = calloc(1, sizeof(struct cursor_position));
496 if (!sway_assert(previous, "could not allocate sway cursor position")) {
497 free(cursor);
498 return NULL;
499 }
500
499 struct wlr_cursor *wlr_cursor = wlr_cursor_create(); 501 struct wlr_cursor *wlr_cursor = wlr_cursor_create();
500 if (!sway_assert(wlr_cursor, "could not allocate wlr cursor")) { 502 if (!sway_assert(wlr_cursor, "could not allocate wlr cursor")) {
503 free(previous);
501 free(cursor); 504 free(cursor);
502 return NULL; 505 return NULL;
503 } 506 }
@@ -548,6 +551,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
548 cursor->request_set_cursor.notify = handle_request_set_cursor; 551 cursor->request_set_cursor.notify = handle_request_set_cursor;
549 552
550 cursor->cursor = wlr_cursor; 553 cursor->cursor = wlr_cursor;
554 cursor->previous = previous;
551 555
552 return cursor; 556 return cursor;
553} 557}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index bb583286..7a3e928a 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -602,7 +602,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
602 wlr_output, seat->cursor->cursor->x, 602 wlr_output, seat->cursor->cursor->x,
603 seat->cursor->cursor->y)) { 603 seat->cursor->cursor->y)) {
604 wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); 604 wlr_cursor_warp(seat->cursor->cursor, NULL, x, y);
605 cursor_send_pointer_motion(seat->cursor, 0, 0, 0, true); 605 cursor_send_pointer_motion(seat->cursor, 0, true);
606 } 606 }
607 } 607 }
608 } 608 }
@@ -613,7 +613,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
613 } 613 }
614 614
615 if (last_workspace && last_workspace != new_workspace) { 615 if (last_workspace && last_workspace != new_workspace) {
616 cursor_send_pointer_motion(seat->cursor, 0, 0, 0, true); 616 cursor_send_pointer_motion(seat->cursor, 0, true);
617 } 617 }
618 618
619 seat->has_focus = (container != NULL); 619 seat->has_focus = (container != NULL);