aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/seat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r--sway/input/seat.c514
1 files changed, 254 insertions, 260 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 4b7c7893..2f7a3318 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -47,48 +47,36 @@ void seat_destroy(struct sway_seat *seat) {
47 seat_device_destroy(seat_device); 47 seat_device_destroy(seat_device);
48 } 48 }
49 sway_cursor_destroy(seat->cursor); 49 sway_cursor_destroy(seat->cursor);
50 wl_list_remove(&seat->new_container.link); 50 wl_list_remove(&seat->new_node.link);
51 wl_list_remove(&seat->new_drag_icon.link); 51 wl_list_remove(&seat->new_drag_icon.link);
52 wl_list_remove(&seat->link); 52 wl_list_remove(&seat->link);
53 wlr_seat_destroy(seat->wlr_seat); 53 wlr_seat_destroy(seat->wlr_seat);
54} 54}
55 55
56static struct sway_seat_container *seat_container_from_container( 56static struct sway_seat_node *seat_node_from_node(
57 struct sway_seat *seat, struct sway_container *con); 57 struct sway_seat *seat, struct sway_node *node);
58 58
59static void seat_container_destroy(struct sway_seat_container *seat_con) { 59static void seat_node_destroy(struct sway_seat_node *seat_node) {
60 struct sway_container *con = seat_con->container; 60 wl_list_remove(&seat_node->destroy.link);
61 struct sway_container *child = NULL; 61 wl_list_remove(&seat_node->link);
62 62 free(seat_node);
63 if (con->children != NULL) {
64 for (int i = 0; i < con->children->length; ++i) {
65 child = con->children->items[i];
66 struct sway_seat_container *seat_child =
67 seat_container_from_container(seat_con->seat, child);
68 seat_container_destroy(seat_child);
69 }
70 }
71
72 wl_list_remove(&seat_con->destroy.link);
73 wl_list_remove(&seat_con->link);
74 free(seat_con);
75} 63}
76 64
77/** 65/**
78 * Activate all views within this container recursively. 66 * Activate all views within this container recursively.
79 */ 67 */
80static void seat_send_activate(struct sway_container *con, 68static void seat_send_activate(struct sway_node *node, struct sway_seat *seat) {
81 struct sway_seat *seat) { 69 if (node_is_view(node)) {
82 if (con->type == C_VIEW) { 70 if (!seat_is_input_allowed(seat, node->sway_container->view->surface)) {
83 if (!seat_is_input_allowed(seat, con->sway_view->surface)) {
84 wlr_log(WLR_DEBUG, "Refusing to set focus, input is inhibited"); 71 wlr_log(WLR_DEBUG, "Refusing to set focus, input is inhibited");
85 return; 72 return;
86 } 73 }
87 view_set_activated(con->sway_view, true); 74 view_set_activated(node->sway_container->view, true);
88 } else { 75 } else {
89 for (int i = 0; i < con->children->length; ++i) { 76 list_t *children = node_get_children(node);
90 struct sway_container *child = con->children->items[i]; 77 for (int i = 0; i < children->length; ++i) {
91 seat_send_activate(child, seat); 78 struct sway_container *child = children->items[i];
79 seat_send_activate(&child->node, seat);
92 } 80 }
93 } 81 }
94} 82}
@@ -98,14 +86,15 @@ static void seat_send_activate(struct sway_container *con,
98 * If con is a container, set all child views as active and don't enable 86 * If con is a container, set all child views as active and don't enable
99 * keyboard input on any. 87 * keyboard input on any.
100 */ 88 */
101static void seat_send_focus(struct sway_container *con, 89static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) {
102 struct sway_seat *seat) { 90 seat_send_activate(node, seat);
103 seat_send_activate(con, seat);
104 91
105 if (con->type == C_VIEW 92 struct sway_view *view = node->type == N_CONTAINER ?
106 && seat_is_input_allowed(seat, con->sway_view->surface)) { 93 node->sway_container->view : NULL;
94
95 if (view && seat_is_input_allowed(seat, view->surface)) {
107#ifdef HAVE_XWAYLAND 96#ifdef HAVE_XWAYLAND
108 if (con->sway_view->type == SWAY_VIEW_XWAYLAND) { 97 if (view->type == SWAY_VIEW_XWAYLAND) {
109 struct wlr_xwayland *xwayland = 98 struct wlr_xwayland *xwayland =
110 seat->input->server->xwayland.wlr_xwayland; 99 seat->input->server->xwayland.wlr_xwayland;
111 wlr_xwayland_set_seat(xwayland, seat->wlr_seat); 100 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
@@ -114,71 +103,67 @@ static void seat_send_focus(struct sway_container *con,
114 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); 103 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
115 if (keyboard) { 104 if (keyboard) {
116 wlr_seat_keyboard_notify_enter(seat->wlr_seat, 105 wlr_seat_keyboard_notify_enter(seat->wlr_seat,
117 con->sway_view->surface, keyboard->keycodes, 106 view->surface, keyboard->keycodes,
118 keyboard->num_keycodes, &keyboard->modifiers); 107 keyboard->num_keycodes, &keyboard->modifiers);
119 } else { 108 } else {
120 wlr_seat_keyboard_notify_enter( 109 wlr_seat_keyboard_notify_enter(
121 seat->wlr_seat, con->sway_view->surface, NULL, 0, NULL); 110 seat->wlr_seat, view->surface, NULL, 0, NULL);
122 } 111 }
123 } 112 }
124} 113}
125 114
126void seat_focus_inactive_children_for_each(struct sway_seat *seat, 115void seat_for_each_node(struct sway_seat *seat,
127 struct sway_container *container, 116 void (*f)(struct sway_node *node, void *data), void *data) {
128 void (*f)(struct sway_container *container, void *data), void *data) { 117 struct sway_seat_node *current = NULL;
129 struct sway_seat_container *current = NULL;
130 wl_list_for_each(current, &seat->focus_stack, link) { 118 wl_list_for_each(current, &seat->focus_stack, link) {
131 if (current->container->parent == NULL) { 119 f(current->node, data);
132 continue;
133 }
134 if (current->container->parent == container) {
135 f(current->container, data);
136 }
137 } 120 }
138} 121}
139 122
140struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, 123struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat,
141 struct sway_container *ancestor) { 124 struct sway_node *ancestor) {
142 if (ancestor->type == C_VIEW) { 125 if (ancestor->type == N_CONTAINER && ancestor->sway_container->view) {
143 return ancestor; 126 return ancestor->sway_container;
144 } 127 }
145 struct sway_seat_container *current; 128 struct sway_seat_node *current;
146 wl_list_for_each(current, &seat->focus_stack, link) { 129 wl_list_for_each(current, &seat->focus_stack, link) {
147 struct sway_container *con = current->container; 130 struct sway_node *node = current->node;
148 if (con->type == C_VIEW && container_has_ancestor(con, ancestor)) { 131 if (node->type == N_CONTAINER && node->sway_container->view &&
149 return con; 132 node_has_ancestor(node, ancestor)) {
133 return node->sway_container;
150 } 134 }
151 } 135 }
152 return NULL; 136 return NULL;
153} 137}
154 138
155static void handle_seat_container_destroy(struct wl_listener *listener, 139static void handle_seat_node_destroy(struct wl_listener *listener, void *data) {
156 void *data) { 140 struct sway_seat_node *seat_node =
157 struct sway_seat_container *seat_con = 141 wl_container_of(listener, seat_node, destroy);
158 wl_container_of(listener, seat_con, destroy); 142 struct sway_seat *seat = seat_node->seat;
159 struct sway_seat *seat = seat_con->seat; 143 struct sway_node *node = seat_node->node;
160 struct sway_container *con = seat_con->container; 144 struct sway_node *parent = node_get_parent(node);
161 struct sway_container *parent = con->parent; 145 struct sway_node *focus = seat_get_focus(seat);
162 struct sway_container *focus = seat_get_focus(seat);
163 146
164 bool set_focus = 147 bool set_focus =
165 focus != NULL && 148 focus != NULL &&
166 (focus == con || container_has_ancestor(focus, con)) && 149 (focus == node || node_has_ancestor(focus, node)) &&
167 con->type != C_WORKSPACE; 150 node->type == N_CONTAINER;
168 151
169 seat_container_destroy(seat_con); 152 seat_node_destroy(seat_node);
170 153
171 if (set_focus) { 154 if (set_focus) {
172 struct sway_container *next_focus = NULL; 155 struct sway_node *next_focus = NULL;
173 while (next_focus == NULL) { 156 while (next_focus == NULL) {
174 next_focus = seat_get_focus_inactive_view(seat, parent); 157 struct sway_container *con =
158 seat_get_focus_inactive_view(seat, parent);
159 next_focus = con ? &con->node : NULL;
175 160
176 if (next_focus == NULL && parent->type == C_WORKSPACE) { 161 if (next_focus == NULL && parent->type == N_WORKSPACE) {
177 next_focus = parent; 162 next_focus = parent;
178 break; 163 break;
179 } 164 }
180 165
181 parent = parent->parent; 166 parent = node_get_parent(parent);
182 } 167 }
183 168
184 // the structure change might have caused it to move up to the top of 169 // the structure change might have caused it to move up to the top of
@@ -191,39 +176,39 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
191 } 176 }
192} 177}
193 178
194static struct sway_seat_container *seat_container_from_container( 179static struct sway_seat_node *seat_node_from_node(
195 struct sway_seat *seat, struct sway_container *con) { 180 struct sway_seat *seat, struct sway_node *node) {
196 if (con->type == C_ROOT || con->type == C_OUTPUT) { 181 if (node->type == N_ROOT || node->type == N_OUTPUT) {
197 // these don't get seat containers ever 182 // these don't get seat nodes ever
198 return NULL; 183 return NULL;
199 } 184 }
200 185
201 struct sway_seat_container *seat_con = NULL; 186 struct sway_seat_node *seat_node = NULL;
202 wl_list_for_each(seat_con, &seat->focus_stack, link) { 187 wl_list_for_each(seat_node, &seat->focus_stack, link) {
203 if (seat_con->container == con) { 188 if (seat_node->node == node) {
204 return seat_con; 189 return seat_node;
205 } 190 }
206 } 191 }
207 192
208 seat_con = calloc(1, sizeof(struct sway_seat_container)); 193 seat_node = calloc(1, sizeof(struct sway_seat_node));
209 if (seat_con == NULL) { 194 if (seat_node == NULL) {
210 wlr_log(WLR_ERROR, "could not allocate seat container"); 195 wlr_log(WLR_ERROR, "could not allocate seat node");
211 return NULL; 196 return NULL;
212 } 197 }
213 198
214 seat_con->container = con; 199 seat_node->node = node;
215 seat_con->seat = seat; 200 seat_node->seat = seat;
216 wl_list_insert(seat->focus_stack.prev, &seat_con->link); 201 wl_list_insert(seat->focus_stack.prev, &seat_node->link);
217 wl_signal_add(&con->events.destroy, &seat_con->destroy); 202 wl_signal_add(&node->events.destroy, &seat_node->destroy);
218 seat_con->destroy.notify = handle_seat_container_destroy; 203 seat_node->destroy.notify = handle_seat_node_destroy;
219 204
220 return seat_con; 205 return seat_node;
221} 206}
222 207
223static void handle_new_container(struct wl_listener *listener, void *data) { 208static void handle_new_node(struct wl_listener *listener, void *data) {
224 struct sway_seat *seat = wl_container_of(listener, seat, new_container); 209 struct sway_seat *seat = wl_container_of(listener, seat, new_node);
225 struct sway_container *con = data; 210 struct sway_node *node = data;
226 seat_container_from_container(seat, con); 211 seat_node_from_node(seat, node);
227} 212}
228 213
229static void drag_icon_damage_whole(struct sway_drag_icon *icon) { 214static void drag_icon_damage_whole(struct sway_drag_icon *icon) {
@@ -272,8 +257,7 @@ static void drag_icon_handle_unmap(struct wl_listener *listener, void *data) {
272 drag_icon_damage_whole(icon); 257 drag_icon_damage_whole(icon);
273} 258}
274 259
275static void drag_icon_handle_destroy(struct wl_listener *listener, 260static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) {
276 void *data) {
277 struct sway_drag_icon *icon = wl_container_of(listener, icon, destroy); 261 struct sway_drag_icon *icon = wl_container_of(listener, icon, destroy);
278 icon->wlr_drag_icon->data = NULL; 262 icon->wlr_drag_icon->data = NULL;
279 wl_list_remove(&icon->link); 263 wl_list_remove(&icon->link);
@@ -305,20 +289,29 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) {
305 icon->destroy.notify = drag_icon_handle_destroy; 289 icon->destroy.notify = drag_icon_handle_destroy;
306 wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy); 290 wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
307 291
308 wl_list_insert(&root_container.sway_root->drag_icons, &icon->link); 292 wl_list_insert(&root->drag_icons, &icon->link);
309 293
310 drag_icon_update_position(icon); 294 drag_icon_update_position(icon);
311} 295}
312 296
313static void collect_focus_iter(struct sway_container *con, void *data) { 297static void collect_focus_iter(struct sway_node *node, void *data) {
314 struct sway_seat *seat = data; 298 struct sway_seat *seat = data;
315 struct sway_seat_container *seat_con = 299 struct sway_seat_node *seat_node = seat_node_from_node(seat, node);
316 seat_container_from_container(seat, con); 300 if (!seat_node) {
317 if (!seat_con) {
318 return; 301 return;
319 } 302 }
320 wl_list_remove(&seat_con->link); 303 wl_list_remove(&seat_node->link);
321 wl_list_insert(&seat->focus_stack, &seat_con->link); 304 wl_list_insert(&seat->focus_stack, &seat_node->link);
305}
306
307static void collect_focus_workspace_iter(struct sway_workspace *workspace,
308 void *data) {
309 collect_focus_iter(&workspace->node, data);
310}
311
312static void collect_focus_container_iter(struct sway_container *container,
313 void *data) {
314 collect_focus_iter(&container->node, data);
322} 315}
323 316
324struct sway_seat *seat_create(struct sway_input_manager *input, 317struct sway_seat *seat_create(struct sway_input_manager *input,
@@ -345,12 +338,11 @@ struct sway_seat *seat_create(struct sway_input_manager *input,
345 // init the focus stack 338 // init the focus stack
346 wl_list_init(&seat->focus_stack); 339 wl_list_init(&seat->focus_stack);
347 340
348 root_for_each_workspace(collect_focus_iter, seat); 341 root_for_each_workspace(collect_focus_workspace_iter, seat);
349 root_for_each_container(collect_focus_iter, seat); 342 root_for_each_container(collect_focus_container_iter, seat);
350 343
351 wl_signal_add(&root_container.sway_root->events.new_container, 344 wl_signal_add(&root->events.new_node, &seat->new_node);
352 &seat->new_container); 345 seat->new_node.notify = handle_new_node;
353 seat->new_container.notify = handle_new_container;
354 346
355 wl_signal_add(&seat->wlr_seat->events.new_drag_icon, &seat->new_drag_icon); 347 wl_signal_add(&seat->wlr_seat->events.new_drag_icon, &seat->new_drag_icon);
356 seat->new_drag_icon.notify = handle_new_drag_icon; 348 seat->new_drag_icon.notify = handle_new_drag_icon;
@@ -388,19 +380,11 @@ static void seat_apply_input_config(struct sway_seat *seat,
388 if (mapped_to_output != NULL) { 380 if (mapped_to_output != NULL) {
389 wlr_log(WLR_DEBUG, "Mapping input device %s to output %s", 381 wlr_log(WLR_DEBUG, "Mapping input device %s to output %s",
390 sway_device->input_device->identifier, mapped_to_output); 382 sway_device->input_device->identifier, mapped_to_output);
391 struct sway_container *output = NULL; 383 struct sway_output *output = output_by_name(mapped_to_output);
392 for (int i = 0; i < root_container.children->length; ++i) {
393 struct sway_container *_output = root_container.children->items[i];
394 if (strcasecmp(_output->name, mapped_to_output) == 0) {
395 output = _output;
396 break;
397 }
398 }
399 if (output) { 384 if (output) {
400 wlr_cursor_map_input_to_output(seat->cursor->cursor, 385 wlr_cursor_map_input_to_output(seat->cursor->cursor,
401 sway_device->input_device->wlr_device, 386 sway_device->input_device->wlr_device, output->wlr_output);
402 output->sway_output->wlr_output); 387 wlr_log(WLR_DEBUG, "Mapped to output %s", output->wlr_output->name);
403 wlr_log(WLR_DEBUG, "Mapped to output %s", output->name);
404 } 388 }
405 } 389 }
406} 390}
@@ -423,12 +407,12 @@ static void seat_configure_keyboard(struct sway_seat *seat,
423 sway_keyboard_configure(seat_device->keyboard); 407 sway_keyboard_configure(seat_device->keyboard);
424 wlr_seat_set_keyboard(seat->wlr_seat, 408 wlr_seat_set_keyboard(seat->wlr_seat,
425 seat_device->input_device->wlr_device); 409 seat_device->input_device->wlr_device);
426 struct sway_container *focus = seat_get_focus(seat); 410 struct sway_node *focus = seat_get_focus(seat);
427 if (focus && focus->type == C_VIEW) { 411 if (focus && node_is_view(focus)) {
428 // force notify reenter to pick up the new configuration 412 // force notify reenter to pick up the new configuration
429 wlr_seat_keyboard_clear_focus(seat->wlr_seat); 413 wlr_seat_keyboard_clear_focus(seat->wlr_seat);
430 wlr_seat_keyboard_notify_enter(seat->wlr_seat, 414 wlr_seat_keyboard_notify_enter(seat->wlr_seat,
431 focus->sway_view->surface, wlr_keyboard->keycodes, 415 focus->sway_container->view->surface, wlr_keyboard->keycodes,
432 wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); 416 wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers);
433 } 417 }
434} 418}
@@ -461,8 +445,7 @@ static struct sway_seat_device *seat_get_device(struct sway_seat *seat,
461 445
462void seat_configure_device(struct sway_seat *seat, 446void seat_configure_device(struct sway_seat *seat,
463 struct sway_input_device *input_device) { 447 struct sway_input_device *input_device) {
464 struct sway_seat_device *seat_device = 448 struct sway_seat_device *seat_device = seat_get_device(seat, input_device);
465 seat_get_device(seat, input_device);
466 if (!seat_device) { 449 if (!seat_device) {
467 return; 450 return;
468 } 451 }
@@ -512,8 +495,7 @@ void seat_add_device(struct sway_seat *seat,
512 495
513void seat_remove_device(struct sway_seat *seat, 496void seat_remove_device(struct sway_seat *seat,
514 struct sway_input_device *input_device) { 497 struct sway_input_device *input_device) {
515 struct sway_seat_device *seat_device = 498 struct sway_seat_device *seat_device = seat_get_device(seat, input_device);
516 seat_get_device(seat, input_device);
517 499
518 if (!seat_device) { 500 if (!seat_device) {
519 return; 501 return;
@@ -539,11 +521,9 @@ void seat_configure_xcursor(struct sway_seat *seat) {
539 } 521 }
540 } 522 }
541 523
542 for (int i = 0; i < root_container.children->length; ++i) { 524 for (int i = 0; i < root->outputs->length; ++i) {
543 struct sway_container *output_container = 525 struct sway_output *sway_output = root->outputs->items[i];
544 root_container.children->items[i]; 526 struct wlr_output *output = sway_output->wlr_output;
545 struct wlr_output *output =
546 output_container->sway_output->wlr_output;
547 bool result = 527 bool result =
548 wlr_xcursor_manager_load(seat->cursor->xcursor_manager, 528 wlr_xcursor_manager_load(seat->cursor->xcursor_manager,
549 output->scale); 529 output->scale);
@@ -566,17 +546,20 @@ bool seat_is_input_allowed(struct sway_seat *seat,
566 return !seat->exclusive_client || seat->exclusive_client == client; 546 return !seat->exclusive_client || seat->exclusive_client == client;
567} 547}
568 548
549static void send_unfocus(struct sway_container *con, void *data) {
550 if (con->view) {
551 view_set_activated(con->view, false);
552 }
553}
554
569// Unfocus the container and any children (eg. when leaving `focus parent`) 555// Unfocus the container and any children (eg. when leaving `focus parent`)
570static void seat_send_unfocus(struct sway_container *container, 556static void seat_send_unfocus(struct sway_node *node, struct sway_seat *seat) {
571 struct sway_seat *seat) { 557 wlr_seat_keyboard_clear_focus(seat->wlr_seat);
572 if (container->type == C_VIEW) { 558 if (node->type == N_WORKSPACE) {
573 wlr_seat_keyboard_clear_focus(seat->wlr_seat); 559 workspace_for_each_container(node->sway_workspace, send_unfocus, seat);
574 view_set_activated(container->sway_view, false);
575 } else { 560 } else {
576 for (int i = 0; i < container->children->length; ++i) { 561 send_unfocus(node->sway_container, seat);
577 struct sway_container *child = container->children->items[i]; 562 container_for_each_child(node->sway_container, send_unfocus, seat);
578 seat_send_unfocus(child, seat);
579 }
580 } 563 }
581} 564}
582 565
@@ -586,26 +569,23 @@ static int handle_urgent_timeout(void *data) {
586 return 0; 569 return 0;
587} 570}
588 571
589void seat_set_focus_warp(struct sway_seat *seat, 572void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node,
590 struct sway_container *container, bool warp, bool notify) { 573 bool warp, bool notify) {
591 if (seat->focused_layer) { 574 if (seat->focused_layer) {
592 return; 575 return;
593 } 576 }
594 577
595 struct sway_container *last_focus = seat_get_focus(seat); 578 struct sway_node *last_focus = seat_get_focus(seat);
596 if (last_focus == container) { 579 if (last_focus == node) {
597 return; 580 return;
598 } 581 }
599 582
600 struct sway_container *last_workspace = last_focus; 583 struct sway_workspace *last_workspace = seat_get_focused_workspace(seat);
601 if (last_workspace && last_workspace->type != C_WORKSPACE) {
602 last_workspace = container_parent(last_workspace, C_WORKSPACE);
603 }
604 584
605 if (container == NULL) { 585 if (node == NULL) {
606 // Close any popups on the old focus 586 // Close any popups on the old focus
607 if (last_focus->type == C_VIEW) { 587 if (node_is_view(last_focus)) {
608 view_close_popups(last_focus->sway_view); 588 view_close_popups(last_focus->sway_container->view);
609 } 589 }
610 seat_send_unfocus(last_focus, seat); 590 seat_send_unfocus(last_focus, seat);
611 seat->has_focus = false; 591 seat->has_focus = false;
@@ -613,69 +593,70 @@ void seat_set_focus_warp(struct sway_seat *seat,
613 return; 593 return;
614 } 594 }
615 595
616 struct sway_container *new_workspace = container; 596 struct sway_workspace *new_workspace = node->type == N_WORKSPACE ?
617 if (new_workspace->type != C_WORKSPACE) { 597 node->sway_workspace : node->sway_container->workspace;
618 new_workspace = container_parent(new_workspace, C_WORKSPACE); 598 struct sway_container *container = node->type == N_CONTAINER ?
619 } 599 node->sway_container : NULL;
620 600
621 if (last_workspace == new_workspace 601 // Deny setting focus to a view which is hidden by a fullscreen container
622 && last_workspace->sway_workspace->fullscreen 602 if (new_workspace && new_workspace->fullscreen && container &&
623 && !container_is_fullscreen_or_child(container)) { 603 !container_is_fullscreen_or_child(container)) {
624 return; 604 return;
625 } 605 }
626 606
627 struct sway_container *last_output = last_focus; 607 struct sway_output *last_output = last_workspace ?
628 if (last_output && last_output->type != C_OUTPUT) { 608 last_workspace->output : NULL;
629 last_output = container_parent(last_output, C_OUTPUT); 609 struct sway_output *new_output = new_workspace->output;
630 }
631 struct sway_container *new_output = container;
632 if (new_output->type != C_OUTPUT) {
633 new_output = container_parent(new_output, C_OUTPUT);
634 }
635 610
636 // find new output's old workspace, which might have to be removed if empty 611 // find new output's old workspace, which might have to be removed if empty
637 struct sway_container *new_output_last_ws = NULL; 612 struct sway_workspace *new_output_last_ws = NULL;
638 if (new_output && last_output != new_output) { 613 if (new_output && last_output != new_output) {
639 new_output_last_ws = seat_get_active_child(seat, new_output); 614 new_output_last_ws = output_get_active_workspace(new_output);
640 } 615 }
641 616
642 if (container->parent) { 617 // Put the container parents on the focus stack, then the workspace, then
643 struct sway_seat_container *seat_con = 618 // the focused container.
644 seat_container_from_container(seat, container); 619 if (container) {
645 if (seat_con == NULL) { 620 struct sway_container *parent = container->parent;
646 return;
647 }
648
649 // put all the ancestors of this container on top of the focus stack
650 struct sway_seat_container *parent =
651 seat_container_from_container(seat, container->parent);
652 while (parent) { 621 while (parent) {
653 wl_list_remove(&parent->link); 622 struct sway_seat_node *seat_node =
654 wl_list_insert(&seat->focus_stack, &parent->link); 623 seat_node_from_node(seat, &parent->node);
655 container_set_dirty(parent->container); 624 wl_list_remove(&seat_node->link);
656 625 wl_list_insert(&seat->focus_stack, &seat_node->link);
657 parent = seat_container_from_container(seat, 626 node_set_dirty(&parent->node);
658 parent->container->parent); 627 parent = parent->parent;
659 } 628 }
660 629 }
661 wl_list_remove(&seat_con->link); 630 if (new_workspace) {
662 wl_list_insert(&seat->focus_stack, &seat_con->link); 631 struct sway_seat_node *seat_node =
632 seat_node_from_node(seat, &new_workspace->node);
633 wl_list_remove(&seat_node->link);
634 wl_list_insert(&seat->focus_stack, &seat_node->link);
635 node_set_dirty(&new_workspace->node);
636 }
637 if (container) {
638 struct sway_seat_node *seat_node =
639 seat_node_from_node(seat, &container->node);
640 wl_list_remove(&seat_node->link);
641 wl_list_insert(&seat->focus_stack, &seat_node->link);
642 node_set_dirty(&container->node);
663 643
664 if (last_focus) { 644 if (last_focus) {
665 seat_send_unfocus(last_focus, seat); 645 seat_send_unfocus(last_focus, seat);
666 container_set_dirty(last_focus); 646 node_set_dirty(last_focus);
647 struct sway_node *last_parent = node_get_parent(last_focus);
648 if (last_parent) {
649 node_set_dirty(last_parent);
650 }
667 } 651 }
668 seat_send_focus(container, seat); 652 seat_send_focus(&container->node, seat);
669
670 container_set_dirty(container);
671 container_set_dirty(container->parent); // for focused_inactive_child
672 } 653 }
673 654
674 // emit ipc events 655 // emit ipc events
675 if (notify && new_workspace && last_workspace != new_workspace) { 656 if (notify && new_workspace && last_workspace != new_workspace) {
676 ipc_event_workspace(last_workspace, new_workspace, "focus"); 657 ipc_event_workspace(last_workspace, new_workspace, "focus");
677 } 658 }
678 if (container->type == C_VIEW) { 659 if (container && container->view) {
679 ipc_event_window(container, "focus"); 660 ipc_event_window(container, "focus");
680 } 661 }
681 662
@@ -684,14 +665,14 @@ void seat_set_focus_warp(struct sway_seat *seat,
684 } 665 }
685 666
686 // Close any popups on the old focus 667 // Close any popups on the old focus
687 if (last_focus && last_focus->type == C_VIEW) { 668 if (last_focus && node_is_view(last_focus)) {
688 view_close_popups(last_focus->sway_view); 669 view_close_popups(last_focus->sway_container->view);
689 } 670 }
690 671
691 // If urgent, either unset the urgency or start a timer to unset it 672 // If urgent, either unset the urgency or start a timer to unset it
692 if (container->type == C_VIEW && view_is_urgent(container->sway_view) && 673 if (container && container->view && view_is_urgent(container->view) &&
693 !container->sway_view->urgent_timer) { 674 !container->view->urgent_timer) {
694 struct sway_view *view = container->sway_view; 675 struct sway_view *view = container->view;
695 if (last_workspace && last_workspace != new_workspace && 676 if (last_workspace && last_workspace != new_workspace &&
696 config->urgent_timeout > 0) { 677 config->urgent_timeout > 0) {
697 view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop, 678 view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop,
@@ -711,12 +692,15 @@ void seat_set_focus_warp(struct sway_seat *seat,
711 692
712 // If we've focused a floating container, bring it to the front. 693 // If we've focused a floating container, bring it to the front.
713 // We do this by putting it at the end of the floating list. 694 // We do this by putting it at the end of the floating list.
714 struct sway_container *floater = container; 695 if (container) {
715 while (floater->parent && floater->parent->type != C_WORKSPACE) { 696 struct sway_container *floater = container;
716 floater = floater->parent; 697 while (floater->parent) {
717 } 698 floater = floater->parent;
718 if (container_is_floating(floater)) { 699 }
719 list_move_to_end(floater->parent->sway_workspace->floating, floater); 700 if (container_is_floating(floater)) {
701 list_move_to_end(floater->workspace->floating, floater);
702 node_set_dirty(&floater->workspace->node);
703 }
720 } 704 }
721 705
722 if (last_focus) { 706 if (last_focus) {
@@ -727,11 +711,8 @@ void seat_set_focus_warp(struct sway_seat *seat,
727 if (config->mouse_warping && warp && new_output != last_output) { 711 if (config->mouse_warping && warp && new_output != last_output) {
728 double x = container->x + container->width / 2.0; 712 double x = container->x + container->width / 2.0;
729 double y = container->y + container->height / 2.0; 713 double y = container->y + container->height / 2.0;
730 struct wlr_output *wlr_output = 714 if (!wlr_output_layout_contains_point(root->output_layout,
731 new_output->sway_output->wlr_output; 715 new_output->wlr_output, seat->cursor->cursor->x,
732 if (!wlr_output_layout_contains_point(
733 root_container.sway_root->output_layout,
734 wlr_output, seat->cursor->cursor->x,
735 seat->cursor->cursor->y)) { 716 seat->cursor->cursor->y)) {
736 wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); 717 wlr_cursor_warp(seat->cursor->cursor, NULL, x, y);
737 cursor_send_pointer_motion(seat->cursor, 0, true); 718 cursor_send_pointer_motion(seat->cursor, 0, true);
@@ -744,9 +725,8 @@ void seat_set_focus_warp(struct sway_seat *seat,
744 update_debug_tree(); 725 update_debug_tree();
745} 726}
746 727
747void seat_set_focus(struct sway_seat *seat, 728void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
748 struct sway_container *container) { 729 seat_set_focus_warp(seat, node, true, true);
749 seat_set_focus_warp(seat, container, true, true);
750} 730}
751 731
752void seat_set_focus_surface(struct sway_seat *seat, 732void seat_set_focus_surface(struct sway_seat *seat,
@@ -755,12 +735,11 @@ void seat_set_focus_surface(struct sway_seat *seat,
755 return; 735 return;
756 } 736 }
757 if (seat->has_focus && unfocus) { 737 if (seat->has_focus && unfocus) {
758 struct sway_container *focus = seat_get_focus(seat); 738 struct sway_node *focus = seat_get_focus(seat);
759 seat_send_unfocus(focus, seat); 739 seat_send_unfocus(focus, seat);
760 seat->has_focus = false; 740 seat->has_focus = false;
761 } 741 }
762 struct wlr_keyboard *keyboard = 742 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
763 wlr_seat_get_keyboard(seat->wlr_seat);
764 if (keyboard) { 743 if (keyboard) {
765 wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, 744 wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface,
766 keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); 745 keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
@@ -773,11 +752,8 @@ void seat_set_focus_layer(struct sway_seat *seat,
773 struct wlr_layer_surface *layer) { 752 struct wlr_layer_surface *layer) {
774 if (!layer && seat->focused_layer) { 753 if (!layer && seat->focused_layer) {
775 seat->focused_layer = NULL; 754 seat->focused_layer = NULL;
776 struct sway_container *previous = 755 struct sway_node *previous = seat_get_focus_inactive(seat, &root->node);
777 seat_get_focus_inactive(seat, &root_container);
778 if (previous) { 756 if (previous) {
779 wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous,
780 container_type_to_str(previous->type), previous->name);
781 // Hack to get seat to re-focus the return value of get_focus 757 // Hack to get seat to re-focus the return value of get_focus
782 seat_set_focus(seat, NULL); 758 seat_set_focus(seat, NULL);
783 seat_set_focus(seat, previous); 759 seat_set_focus(seat, previous);
@@ -798,13 +774,9 @@ void seat_set_exclusive_client(struct sway_seat *seat,
798 seat->exclusive_client = client; 774 seat->exclusive_client = client;
799 // Triggers a refocus of the topmost surface layer if necessary 775 // Triggers a refocus of the topmost surface layer if necessary
800 // TODO: Make layer surface focus per-output based on cursor position 776 // TODO: Make layer surface focus per-output based on cursor position
801 for (int i = 0; i < root_container.children->length; ++i) { 777 for (int i = 0; i < root->outputs->length; ++i) {
802 struct sway_container *output = root_container.children->items[i]; 778 struct sway_output *output = root->outputs->items[i];
803 if (!sway_assert(output->type == C_OUTPUT, 779 arrange_layers(output);
804 "root container has non-output child")) {
805 continue;
806 }
807 arrange_layers(output->sway_output);
808 } 780 }
809 return; 781 return;
810 } 782 }
@@ -814,9 +786,9 @@ void seat_set_exclusive_client(struct sway_seat *seat,
814 } 786 }
815 } 787 }
816 if (seat->has_focus) { 788 if (seat->has_focus) {
817 struct sway_container *focus = seat_get_focus(seat); 789 struct sway_node *focus = seat_get_focus(seat);
818 if (focus->type == C_VIEW && wl_resource_get_client( 790 if (node_is_view(focus) && wl_resource_get_client(
819 focus->sway_view->surface->resource) != client) { 791 focus->sway_container->view->surface->resource) != client) {
820 seat_set_focus(seat, NULL); 792 seat_set_focus(seat, NULL);
821 } 793 }
822 } 794 }
@@ -837,79 +809,101 @@ void seat_set_exclusive_client(struct sway_seat *seat,
837 seat->exclusive_client = client; 809 seat->exclusive_client = client;
838} 810}
839 811
840struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, 812struct sway_node *seat_get_focus_inactive(struct sway_seat *seat,
841 struct sway_container *con) { 813 struct sway_node *node) {
842 if (con->type == C_WORKSPACE && !con->children->length && 814 if (node_is_view(node)) {
843 !con->sway_workspace->floating->length) { 815 return node;
844 return con;
845 }
846 if (con->type == C_VIEW) {
847 return con;
848 } 816 }
849 struct sway_seat_container *current; 817 struct sway_seat_node *current;
850 wl_list_for_each(current, &seat->focus_stack, link) { 818 wl_list_for_each(current, &seat->focus_stack, link) {
851 if (container_has_ancestor(current->container, con)) { 819 if (node_has_ancestor(current->node, node)) {
852 return current->container; 820 return current->node;
853 } 821 }
854 } 822 }
823 if (node->type == N_WORKSPACE) {
824 return node;
825 }
855 return NULL; 826 return NULL;
856} 827}
857 828
858struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat, 829struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat,
859 struct sway_container *ancestor) { 830 struct sway_workspace *workspace) {
860 if (ancestor->type == C_WORKSPACE && !ancestor->children->length) { 831 if (!workspace->tiling->length) {
861 return ancestor; 832 return NULL;
862 } 833 }
863 struct sway_seat_container *current; 834 struct sway_seat_node *current;
864 wl_list_for_each(current, &seat->focus_stack, link) { 835 wl_list_for_each(current, &seat->focus_stack, link) {
865 struct sway_container *con = current->container; 836 struct sway_node *node = current->node;
866 if (!container_is_floating_or_child(con) && 837 if (node->type == N_CONTAINER &&
867 container_has_ancestor(current->container, ancestor)) { 838 !container_is_floating_or_child(node->sway_container) &&
868 return con; 839 node->sway_container->workspace == workspace) {
840 return node->sway_container;
869 } 841 }
870 } 842 }
871 return NULL; 843 return NULL;
872} 844}
873 845
874struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat, 846struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat,
875 struct sway_container *ancestor) { 847 struct sway_workspace *workspace) {
876 if (ancestor->type == C_WORKSPACE && 848 if (!workspace->floating->length) {
877 !ancestor->sway_workspace->floating->length) {
878 return NULL; 849 return NULL;
879 } 850 }
880 struct sway_seat_container *current; 851 struct sway_seat_node *current;
881 wl_list_for_each(current, &seat->focus_stack, link) { 852 wl_list_for_each(current, &seat->focus_stack, link) {
882 struct sway_container *con = current->container; 853 struct sway_node *node = current->node;
883 if (container_is_floating_or_child(con) && 854 if (node->type == N_CONTAINER &&
884 container_has_ancestor(current->container, ancestor)) { 855 container_is_floating_or_child(node->sway_container) &&
885 return con; 856 node->sway_container->workspace == workspace) {
857 return node->sway_container;
886 } 858 }
887 } 859 }
888 return NULL; 860 return NULL;
889} 861}
890 862
891struct sway_container *seat_get_active_child(struct sway_seat *seat, 863struct sway_node *seat_get_active_child(struct sway_seat *seat,
892 struct sway_container *parent) { 864 struct sway_node *parent) {
893 if (parent->type == C_VIEW) { 865 if (node_is_view(parent)) {
894 return parent; 866 return parent;
895 } 867 }
896 struct sway_seat_container *current; 868 struct sway_seat_node *current;
897 wl_list_for_each(current, &seat->focus_stack, link) { 869 wl_list_for_each(current, &seat->focus_stack, link) {
898 struct sway_container *con = current->container; 870 struct sway_node *node = current->node;
899 if (con->parent == parent) { 871 if (node_get_parent(node) == parent) {
900 return con; 872 return node;
901 } 873 }
902 } 874 }
903 return NULL; 875 return NULL;
904} 876}
905 877
906struct sway_container *seat_get_focus(struct sway_seat *seat) { 878struct sway_node *seat_get_focus(struct sway_seat *seat) {
907 if (!seat->has_focus) { 879 if (!seat->has_focus) {
908 return NULL; 880 return NULL;
909 } 881 }
910 struct sway_seat_container *current = 882 struct sway_seat_node *current =
911 wl_container_of(seat->focus_stack.next, current, link); 883 wl_container_of(seat->focus_stack.next, current, link);
912 return current->container; 884 return current->node;
885}
886
887struct sway_workspace *seat_get_focused_workspace(struct sway_seat *seat) {
888 struct sway_node *focus = seat_get_focus(seat);
889 if (!focus) {
890 return NULL;
891 }
892 if (focus->type == N_CONTAINER) {
893 return focus->sway_container->workspace;
894 }
895 if (focus->type == N_WORKSPACE) {
896 return focus->sway_workspace;
897 }
898 return NULL; // unreachable
899}
900
901struct sway_container *seat_get_focused_container(struct sway_seat *seat) {
902 struct sway_node *focus = seat_get_focus(seat);
903 if (focus && focus->type == N_CONTAINER) {
904 return focus->sway_container;
905 }
906 return NULL;
913} 907}
914 908
915void seat_apply_config(struct sway_seat *seat, 909void seat_apply_config(struct sway_seat *seat,