summaryrefslogtreecommitdiffstats
path: root/sway/input/seat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r--sway/input/seat.c134
1 files changed, 90 insertions, 44 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 27636c1e..c41f7b2e 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,4 +1,5 @@
1#define _XOPEN_SOURCE 700 1#define _XOPEN_SOURCE 700
2#include <assert.h>
2#include <wlr/types/wlr_cursor.h> 3#include <wlr/types/wlr_cursor.h>
3#include <wlr/types/wlr_output_layout.h> 4#include <wlr/types/wlr_output_layout.h>
4#include <wlr/types/wlr_xcursor_manager.h> 5#include <wlr/types/wlr_xcursor_manager.h>
@@ -35,31 +36,89 @@ void seat_destroy(struct sway_seat *seat) {
35 wlr_seat_destroy(seat->wlr_seat); 36 wlr_seat_destroy(seat->wlr_seat);
36} 37}
37 38
39static struct sway_seat_container *seat_container_from_container(
40 struct sway_seat *seat, struct sway_container *con);
41
42static void seat_container_destroy(struct sway_seat_container *seat_con) {
43 struct sway_container *con = seat_con->container;
44 struct sway_container *child = NULL;
45
46 if (con->children != NULL) {
47 for (int i = 0; i < con->children->length; ++i) {
48 child = con->children->items[i];
49 struct sway_seat_container *seat_child =
50 seat_container_from_container(seat_con->seat, child);
51 seat_container_destroy(seat_child);
52 }
53 }
54
55 wl_list_remove(&seat_con->destroy.link);
56 wl_list_remove(&seat_con->link);
57 free(seat_con);
58}
59
60static void seat_send_focus(struct sway_seat *seat,
61 struct sway_container *con) {
62 if (con->type != C_VIEW) {
63 return;
64 }
65 struct sway_view *view = con->sway_view;
66 if (view->type == SWAY_XWAYLAND_VIEW) {
67 struct wlr_xwayland *xwayland =
68 seat->input->server->xwayland;
69 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
70 }
71 view_set_activated(view, true);
72 struct wlr_keyboard *keyboard =
73 wlr_seat_get_keyboard(seat->wlr_seat);
74 if (keyboard) {
75 wlr_seat_keyboard_notify_enter(seat->wlr_seat,
76 view->surface, keyboard->keycodes,
77 keyboard->num_keycodes, &keyboard->modifiers);
78 } else {
79 wlr_seat_keyboard_notify_enter(
80 seat->wlr_seat, view->surface, NULL, 0, NULL);
81 }
82
83}
84
38static void handle_seat_container_destroy(struct wl_listener *listener, 85static void handle_seat_container_destroy(struct wl_listener *listener,
39 void *data) { 86 void *data) {
40 struct sway_seat_container *seat_con = 87 struct sway_seat_container *seat_con =
41 wl_container_of(listener, seat_con, destroy); 88 wl_container_of(listener, seat_con, destroy);
42 struct sway_seat *seat = seat_con->seat; 89 struct sway_seat *seat = seat_con->seat;
43 struct sway_container *con = seat_con->container; 90 struct sway_container *con = seat_con->container;
91 struct sway_container *parent = con->parent;
92 struct sway_container *focus = seat_get_focus(seat);
44 93
45 bool is_focus = (seat_get_focus(seat) == con); 94 bool set_focus =
95 focus != NULL &&
96 (focus == con || container_has_child(con, focus)) &&
97 con->type != C_WORKSPACE;
46 98
47 wl_list_remove(&seat_con->link); 99 seat_container_destroy(seat_con);
48 100
49 if (is_focus) { 101 if (set_focus) {
50 // pick next focus 102 struct sway_container *next_focus = NULL;
51 seat_set_focus(seat, NULL); 103 while (next_focus == NULL) {
52 struct sway_container *next = 104 next_focus = seat_get_focus_by_type(seat, parent, C_VIEW);
53 seat_get_focus_inactive(seat, con->parent);
54 if (next == NULL) {
55 next = con->parent;
56 }
57 seat_set_focus(seat, next);
58 }
59 105
60 wl_list_remove(&seat_con->destroy.link); 106 if (next_focus == NULL && parent->type == C_WORKSPACE) {
107 next_focus = parent;
108 break;
109 }
61 110
62 free(seat_con); 111 parent = parent->parent;
112 }
113
114 // the structure change might have caused it to move up to the top of
115 // the focus stack without sending focus notifications to the view
116 if (seat_get_focus(seat) == next_focus) {
117 seat_send_focus(seat, next_focus);
118 } else {
119 seat_set_focus(seat, next_focus);
120 }
121 }
63} 122}
64 123
65static struct sway_seat_container *seat_container_from_container( 124static struct sway_seat_container *seat_container_from_container(
@@ -310,23 +369,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
310 wl_list_insert(&seat->focus_stack, &seat_con->link); 369 wl_list_insert(&seat->focus_stack, &seat_con->link);
311 370
312 if (container->type == C_VIEW) { 371 if (container->type == C_VIEW) {
313 struct sway_view *view = container->sway_view; 372 seat_send_focus(seat, container);
314 view_set_activated(view, true);
315 if (view->type == SWAY_XWAYLAND_VIEW) {
316 struct wlr_xwayland *xwayland =
317 seat->input->server->xwayland;
318 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
319 }
320 struct wlr_keyboard *keyboard =
321 wlr_seat_get_keyboard(seat->wlr_seat);
322 if (keyboard) {
323 wlr_seat_keyboard_notify_enter(seat->wlr_seat,
324 view->surface, keyboard->keycodes,
325 keyboard->num_keycodes, &keyboard->modifiers);
326 } else {
327 wlr_seat_keyboard_notify_enter(
328 seat->wlr_seat, view->surface, NULL, 0, NULL);
329 }
330 } 373 }
331 } 374 }
332 375
@@ -378,17 +421,31 @@ void seat_set_focus(struct sway_seat *seat,
378 421
379struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, 422struct sway_container *seat_get_focus_inactive(struct sway_seat *seat,
380 struct sway_container *container) { 423 struct sway_container *container) {
424 return seat_get_focus_by_type(seat, container, C_TYPES);
425}
426
427struct sway_container *sway_seat_get_focus(struct sway_seat *seat) {
428 if (!seat->has_focus) {
429 return NULL;
430 }
431 return seat_get_focus_inactive(seat, &root_container);
432}
433
434struct sway_container *seat_get_focus_by_type(struct sway_seat *seat,
435 struct sway_container *container, enum sway_container_type type) {
381 struct sway_seat_container *current = NULL; 436 struct sway_seat_container *current = NULL;
382 struct sway_container *parent = NULL; 437 struct sway_container *parent = NULL;
383 wl_list_for_each(current, &seat->focus_stack, link) { 438 wl_list_for_each(current, &seat->focus_stack, link) {
384 parent = current->container->parent; 439 parent = current->container->parent;
385 440
386 if (current->container == container) { 441 if (current->container == container &&
442 (type == C_TYPES || container->type == type)) {
387 return current->container; 443 return current->container;
388 } 444 }
389 445
390 while (parent) { 446 while (parent) {
391 if (parent == container) { 447 if (parent == container && (type == C_TYPES ||
448 current->container->type == type)) {
392 return current->container; 449 return current->container;
393 } 450 }
394 parent = parent->parent; 451 parent = parent->parent;
@@ -405,17 +462,6 @@ struct sway_container *seat_get_focus(struct sway_seat *seat) {
405 return seat_get_focus_inactive(seat, &root_container); 462 return seat_get_focus_inactive(seat, &root_container);
406} 463}
407 464
408struct sway_container *seat_get_focus_by_type(struct sway_seat *seat,
409 enum sway_container_type type) {
410 struct sway_container *focus =
411 seat_get_focus_inactive(seat, &root_container);
412 if (focus->type == type) {
413 return focus;
414 }
415
416 return container_parent(focus, type);
417}
418
419void seat_apply_config(struct sway_seat *seat, 465void seat_apply_config(struct sway_seat *seat,
420 struct seat_config *seat_config) { 466 struct seat_config *seat_config) {
421 struct sway_seat_device *seat_device = NULL; 467 struct sway_seat_device *seat_device = NULL;