diff options
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 104 |
1 files changed, 72 insertions, 32 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index e0fd314a..e3d53cb6 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -27,6 +27,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | void sway_seat_destroy(struct sway_seat *seat) { | 29 | void sway_seat_destroy(struct sway_seat *seat) { |
30 | // TODO destroy seat containers | ||
30 | struct sway_seat_device *seat_device, *next; | 31 | struct sway_seat_device *seat_device, *next; |
31 | wl_list_for_each_safe(seat_device, next, &seat->devices, link) { | 32 | wl_list_for_each_safe(seat_device, next, &seat->devices, link) { |
32 | seat_device_destroy(seat_device); | 33 | seat_device_destroy(seat_device); |
@@ -36,30 +37,57 @@ void sway_seat_destroy(struct sway_seat *seat) { | |||
36 | wlr_seat_destroy(seat->wlr_seat); | 37 | wlr_seat_destroy(seat->wlr_seat); |
37 | } | 38 | } |
38 | 39 | ||
40 | static struct sway_seat_container *seat_container_from_container( | ||
41 | struct sway_seat *seat, struct sway_container *con); | ||
42 | |||
43 | static void seat_container_destroy(struct sway_seat_container *seat_con) { | ||
44 | struct sway_container *con = seat_con->container; | ||
45 | struct sway_container *child = NULL; | ||
46 | |||
47 | if (con->children != NULL) { | ||
48 | for (int i = 0; i < con->children->length; ++i) { | ||
49 | child = con->children->items[i]; | ||
50 | struct sway_seat_container *seat_child = | ||
51 | seat_container_from_container(seat_con->seat, child); | ||
52 | seat_container_destroy(seat_child); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | wl_list_remove(&seat_con->destroy.link); | ||
57 | wl_list_remove(&seat_con->link); | ||
58 | free(seat_con); | ||
59 | } | ||
60 | |||
39 | static void handle_seat_container_destroy(struct wl_listener *listener, | 61 | static void handle_seat_container_destroy(struct wl_listener *listener, |
40 | void *data) { | 62 | void *data) { |
41 | struct sway_seat_container *seat_con = | 63 | struct sway_seat_container *seat_con = |
42 | wl_container_of(listener, seat_con, destroy); | 64 | wl_container_of(listener, seat_con, destroy); |
43 | struct sway_seat *seat = seat_con->seat; | 65 | struct sway_seat *seat = seat_con->seat; |
44 | struct sway_container *con = seat_con->container; | 66 | struct sway_container *con = seat_con->container; |
67 | struct sway_container *parent = con->parent; | ||
68 | struct sway_container *focus = sway_seat_get_focus(seat); | ||
45 | 69 | ||
46 | bool is_focus = (sway_seat_get_focus(seat) == con); | 70 | // TODO handle workspace switch in the seat? |
71 | bool set_focus = | ||
72 | (focus == con || container_has_child(con, focus)) && | ||
73 | con->type != C_WORKSPACE; | ||
47 | 74 | ||
48 | wl_list_remove(&seat_con->link); | 75 | seat_container_destroy(seat_con); |
49 | 76 | ||
50 | if (is_focus) { | 77 | if (set_focus && con->type != C_WORKSPACE) { |
51 | // pick next focus | 78 | struct sway_container *next_focus = NULL; |
52 | sway_seat_set_focus(seat, NULL); | 79 | while (next_focus == NULL) { |
53 | struct sway_container *next = sway_seat_get_focus_inactive(seat, con->parent); | 80 | next_focus = sway_seat_get_focus_by_type(seat, parent, C_VIEW); |
54 | if (next == NULL) { | 81 | parent = parent->parent; |
55 | next = con->parent; | ||
56 | } | ||
57 | sway_seat_set_focus(seat, next); | ||
58 | } | ||
59 | 82 | ||
60 | wl_list_remove(&seat_con->destroy.link); | 83 | if (next_focus == NULL && parent->type == C_WORKSPACE) { |
84 | next_focus = parent; | ||
85 | break; | ||
86 | } | ||
87 | } | ||
61 | 88 | ||
62 | free(seat_con); | 89 | sway_seat_set_focus(seat, next_focus); |
90 | } | ||
63 | } | 91 | } |
64 | 92 | ||
65 | static struct sway_seat_container *seat_container_from_container( | 93 | static struct sway_seat_container *seat_container_from_container( |
@@ -293,11 +321,37 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { | |||
293 | seat->cursor->cursor->y); | 321 | seat->cursor->cursor->y); |
294 | } | 322 | } |
295 | 323 | ||
324 | static void seat_send_focus(struct sway_seat *seat, | ||
325 | struct sway_container *con) { | ||
326 | if (con->type != C_VIEW) { | ||
327 | return; | ||
328 | } | ||
329 | struct sway_view *view = con->sway_view; | ||
330 | if (view->type == SWAY_XWAYLAND_VIEW) { | ||
331 | struct wlr_xwayland *xwayland = | ||
332 | seat->input->server->xwayland; | ||
333 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | ||
334 | } | ||
335 | view_set_activated(view, true); | ||
336 | struct wlr_keyboard *keyboard = | ||
337 | wlr_seat_get_keyboard(seat->wlr_seat); | ||
338 | if (keyboard) { | ||
339 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, | ||
340 | view->surface, keyboard->keycodes, | ||
341 | keyboard->num_keycodes, &keyboard->modifiers); | ||
342 | } else { | ||
343 | wlr_seat_keyboard_notify_enter( | ||
344 | seat->wlr_seat, view->surface, NULL, 0, NULL); | ||
345 | } | ||
346 | |||
347 | } | ||
348 | |||
296 | void sway_seat_set_focus_warp(struct sway_seat *seat, | 349 | void sway_seat_set_focus_warp(struct sway_seat *seat, |
297 | struct sway_container *container, bool warp) { | 350 | struct sway_container *container, bool warp) { |
298 | struct sway_container *last_focus = sway_seat_get_focus(seat); | 351 | struct sway_container *last_focus = sway_seat_get_focus(seat); |
299 | 352 | ||
300 | if (container && last_focus == container) { | 353 | if (container && last_focus == container) { |
354 | seat_send_focus(seat, container); | ||
301 | return; | 355 | return; |
302 | } | 356 | } |
303 | 357 | ||
@@ -312,23 +366,7 @@ void sway_seat_set_focus_warp(struct sway_seat *seat, | |||
312 | wl_list_insert(&seat->focus_stack, &seat_con->link); | 366 | wl_list_insert(&seat->focus_stack, &seat_con->link); |
313 | 367 | ||
314 | if (container->type == C_VIEW) { | 368 | if (container->type == C_VIEW) { |
315 | struct sway_view *view = container->sway_view; | 369 | seat_send_focus(seat, container); |
316 | view_set_activated(view, true); | ||
317 | if (view->type == SWAY_XWAYLAND_VIEW) { | ||
318 | struct wlr_xwayland *xwayland = | ||
319 | seat->input->server->xwayland; | ||
320 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | ||
321 | } | ||
322 | struct wlr_keyboard *keyboard = | ||
323 | wlr_seat_get_keyboard(seat->wlr_seat); | ||
324 | if (keyboard) { | ||
325 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, | ||
326 | view->surface, keyboard->keycodes, | ||
327 | keyboard->num_keycodes, &keyboard->modifiers); | ||
328 | } else { | ||
329 | wlr_seat_keyboard_notify_enter( | ||
330 | seat->wlr_seat, view->surface, NULL, 0, NULL); | ||
331 | } | ||
332 | } | 370 | } |
333 | } | 371 | } |
334 | 372 | ||
@@ -378,7 +416,8 @@ void sway_seat_set_focus(struct sway_seat *seat, | |||
378 | sway_seat_set_focus_warp(seat, container, true); | 416 | sway_seat_set_focus_warp(seat, container, true); |
379 | } | 417 | } |
380 | 418 | ||
381 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { | 419 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, |
420 | struct sway_container *container) { | ||
382 | return sway_seat_get_focus_by_type(seat, container, C_TYPES); | 421 | return sway_seat_get_focus_by_type(seat, container, C_TYPES); |
383 | } | 422 | } |
384 | 423 | ||
@@ -401,7 +440,8 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, | |||
401 | } | 440 | } |
402 | 441 | ||
403 | while (parent) { | 442 | while (parent) { |
404 | if (parent == container && (type == C_TYPES || current->container->type == type)) { | 443 | if (parent == container && (type == C_TYPES || |
444 | current->container->type == type)) { | ||
405 | return current->container; | 445 | return current->container; |
406 | } | 446 | } |
407 | parent = parent->parent; | 447 | parent = parent->parent; |