diff options
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 536 |
1 files changed, 269 insertions, 267 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index 4b7c7893..92d9d7ec 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 | ||
56 | static struct sway_seat_container *seat_container_from_container( | 56 | static 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 | ||
59 | static void seat_container_destroy(struct sway_seat_container *seat_con) { | 59 | static 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 | */ |
80 | static void seat_send_activate(struct sway_container *con, | 68 | static 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 | */ |
101 | static void seat_send_focus(struct sway_container *con, | 89 | static 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 | ||
126 | void seat_focus_inactive_children_for_each(struct sway_seat *seat, | 115 | void 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 | ||
140 | struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, | 123 | struct 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 | ||
155 | static void handle_seat_container_destroy(struct wl_listener *listener, | 139 | static 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 | ||
194 | static struct sway_seat_container *seat_container_from_container( | 179 | static 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 | ||
223 | static void handle_new_container(struct wl_listener *listener, void *data) { | 208 | static 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 | ||
229 | static void drag_icon_damage_whole(struct sway_drag_icon *icon) { | 214 | static 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 | ||
275 | static void drag_icon_handle_destroy(struct wl_listener *listener, | 260 | static 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 | ||
313 | static void collect_focus_iter(struct sway_container *con, void *data) { | 297 | static 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 | |||
307 | static void collect_focus_workspace_iter(struct sway_workspace *workspace, | ||
308 | void *data) { | ||
309 | collect_focus_iter(&workspace->node, data); | ||
310 | } | ||
311 | |||
312 | static void collect_focus_container_iter(struct sway_container *container, | ||
313 | void *data) { | ||
314 | collect_focus_iter(&container->node, data); | ||
322 | } | 315 | } |
323 | 316 | ||
324 | struct sway_seat *seat_create(struct sway_input_manager *input, | 317 | struct 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 | ||
462 | void seat_configure_device(struct sway_seat *seat, | 446 | void 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 | ||
513 | void seat_remove_device(struct sway_seat *seat, | 496 | void 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 | ||
549 | static 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`) |
570 | static void seat_send_unfocus(struct sway_container *container, | 556 | static 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 | ||
589 | void seat_set_focus_warp(struct sway_seat *seat, | 572 | void 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,71 @@ 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 | // Unfocus the previous focus |
643 | struct sway_seat_container *seat_con = | 618 | if (last_focus) { |
644 | seat_container_from_container(seat, container); | 619 | seat_send_unfocus(last_focus, seat); |
645 | if (seat_con == NULL) { | 620 | node_set_dirty(last_focus); |
646 | return; | 621 | struct sway_node *parent = node_get_parent(last_focus); |
622 | if (parent) { | ||
623 | node_set_dirty(parent); | ||
647 | } | 624 | } |
625 | } | ||
648 | 626 | ||
649 | // put all the ancestors of this container on top of the focus stack | 627 | // Put the container parents on the focus stack, then the workspace, then |
650 | struct sway_seat_container *parent = | 628 | // the focused container. |
651 | seat_container_from_container(seat, container->parent); | 629 | if (container) { |
630 | struct sway_container *parent = container->parent; | ||
652 | while (parent) { | 631 | while (parent) { |
653 | wl_list_remove(&parent->link); | 632 | struct sway_seat_node *seat_node = |
654 | wl_list_insert(&seat->focus_stack, &parent->link); | 633 | seat_node_from_node(seat, &parent->node); |
655 | container_set_dirty(parent->container); | 634 | wl_list_remove(&seat_node->link); |
656 | 635 | wl_list_insert(&seat->focus_stack, &seat_node->link); | |
657 | parent = seat_container_from_container(seat, | 636 | node_set_dirty(&parent->node); |
658 | parent->container->parent); | 637 | parent = parent->parent; |
659 | } | ||
660 | |||
661 | wl_list_remove(&seat_con->link); | ||
662 | wl_list_insert(&seat->focus_stack, &seat_con->link); | ||
663 | |||
664 | if (last_focus) { | ||
665 | seat_send_unfocus(last_focus, seat); | ||
666 | container_set_dirty(last_focus); | ||
667 | } | 638 | } |
668 | seat_send_focus(container, seat); | 639 | } |
669 | 640 | if (new_workspace) { | |
670 | container_set_dirty(container); | 641 | struct sway_seat_node *seat_node = |
671 | container_set_dirty(container->parent); // for focused_inactive_child | 642 | seat_node_from_node(seat, &new_workspace->node); |
643 | wl_list_remove(&seat_node->link); | ||
644 | wl_list_insert(&seat->focus_stack, &seat_node->link); | ||
645 | node_set_dirty(&new_workspace->node); | ||
646 | } | ||
647 | if (container) { | ||
648 | struct sway_seat_node *seat_node = | ||
649 | seat_node_from_node(seat, &container->node); | ||
650 | wl_list_remove(&seat_node->link); | ||
651 | wl_list_insert(&seat->focus_stack, &seat_node->link); | ||
652 | node_set_dirty(&container->node); | ||
653 | seat_send_focus(&container->node, seat); | ||
672 | } | 654 | } |
673 | 655 | ||
674 | // emit ipc events | 656 | // emit ipc events |
675 | if (notify && new_workspace && last_workspace != new_workspace) { | 657 | if (notify && new_workspace && last_workspace != new_workspace) { |
676 | ipc_event_workspace(last_workspace, new_workspace, "focus"); | 658 | ipc_event_workspace(last_workspace, new_workspace, "focus"); |
677 | } | 659 | } |
678 | if (container->type == C_VIEW) { | 660 | if (container && container->view) { |
679 | ipc_event_window(container, "focus"); | 661 | ipc_event_window(container, "focus"); |
680 | } | 662 | } |
681 | 663 | ||
@@ -684,14 +666,14 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
684 | } | 666 | } |
685 | 667 | ||
686 | // Close any popups on the old focus | 668 | // Close any popups on the old focus |
687 | if (last_focus && last_focus->type == C_VIEW) { | 669 | if (last_focus && node_is_view(last_focus)) { |
688 | view_close_popups(last_focus->sway_view); | 670 | view_close_popups(last_focus->sway_container->view); |
689 | } | 671 | } |
690 | 672 | ||
691 | // If urgent, either unset the urgency or start a timer to unset it | 673 | // 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) && | 674 | if (container && container->view && view_is_urgent(container->view) && |
693 | !container->sway_view->urgent_timer) { | 675 | !container->view->urgent_timer) { |
694 | struct sway_view *view = container->sway_view; | 676 | struct sway_view *view = container->view; |
695 | if (last_workspace && last_workspace != new_workspace && | 677 | if (last_workspace && last_workspace != new_workspace && |
696 | config->urgent_timeout > 0) { | 678 | config->urgent_timeout > 0) { |
697 | view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop, | 679 | view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop, |
@@ -711,12 +693,15 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
711 | 693 | ||
712 | // If we've focused a floating container, bring it to the front. | 694 | // 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. | 695 | // We do this by putting it at the end of the floating list. |
714 | struct sway_container *floater = container; | 696 | if (container) { |
715 | while (floater->parent && floater->parent->type != C_WORKSPACE) { | 697 | struct sway_container *floater = container; |
716 | floater = floater->parent; | 698 | while (floater->parent) { |
717 | } | 699 | floater = floater->parent; |
718 | if (container_is_floating(floater)) { | 700 | } |
719 | list_move_to_end(floater->parent->sway_workspace->floating, floater); | 701 | if (container_is_floating(floater)) { |
702 | list_move_to_end(floater->workspace->floating, floater); | ||
703 | node_set_dirty(&floater->workspace->node); | ||
704 | } | ||
720 | } | 705 | } |
721 | 706 | ||
722 | if (last_focus) { | 707 | if (last_focus) { |
@@ -725,16 +710,20 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
725 | } | 710 | } |
726 | 711 | ||
727 | if (config->mouse_warping && warp && new_output != last_output) { | 712 | if (config->mouse_warping && warp && new_output != last_output) { |
728 | double x = container->x + container->width / 2.0; | 713 | double x = 0; |
729 | double y = container->y + container->height / 2.0; | 714 | double y = 0; |
730 | struct wlr_output *wlr_output = | 715 | if (container) { |
731 | new_output->sway_output->wlr_output; | 716 | x = container->x + container->width / 2.0; |
732 | if (!wlr_output_layout_contains_point( | 717 | y = container->y + container->height / 2.0; |
733 | root_container.sway_root->output_layout, | 718 | } else { |
734 | wlr_output, seat->cursor->cursor->x, | 719 | x = new_workspace->x + new_workspace->width / 2.0; |
735 | seat->cursor->cursor->y)) { | 720 | y = new_workspace->y + new_workspace->height / 2.0; |
736 | wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); | 721 | } |
737 | cursor_send_pointer_motion(seat->cursor, 0, true); | 722 | if (!wlr_output_layout_contains_point(root->output_layout, |
723 | new_output->wlr_output, seat->cursor->cursor->x, | ||
724 | seat->cursor->cursor->y)) { | ||
725 | wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); | ||
726 | cursor_send_pointer_motion(seat->cursor, 0, true); | ||
738 | } | 727 | } |
739 | } | 728 | } |
740 | } | 729 | } |
@@ -744,9 +733,8 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
744 | update_debug_tree(); | 733 | update_debug_tree(); |
745 | } | 734 | } |
746 | 735 | ||
747 | void seat_set_focus(struct sway_seat *seat, | 736 | void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { |
748 | struct sway_container *container) { | 737 | seat_set_focus_warp(seat, node, true, true); |
749 | seat_set_focus_warp(seat, container, true, true); | ||
750 | } | 738 | } |
751 | 739 | ||
752 | void seat_set_focus_surface(struct sway_seat *seat, | 740 | void seat_set_focus_surface(struct sway_seat *seat, |
@@ -755,12 +743,11 @@ void seat_set_focus_surface(struct sway_seat *seat, | |||
755 | return; | 743 | return; |
756 | } | 744 | } |
757 | if (seat->has_focus && unfocus) { | 745 | if (seat->has_focus && unfocus) { |
758 | struct sway_container *focus = seat_get_focus(seat); | 746 | struct sway_node *focus = seat_get_focus(seat); |
759 | seat_send_unfocus(focus, seat); | 747 | seat_send_unfocus(focus, seat); |
760 | seat->has_focus = false; | 748 | seat->has_focus = false; |
761 | } | 749 | } |
762 | struct wlr_keyboard *keyboard = | 750 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); |
763 | wlr_seat_get_keyboard(seat->wlr_seat); | ||
764 | if (keyboard) { | 751 | if (keyboard) { |
765 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, | 752 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, |
766 | keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); | 753 | keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); |
@@ -773,11 +760,8 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
773 | struct wlr_layer_surface *layer) { | 760 | struct wlr_layer_surface *layer) { |
774 | if (!layer && seat->focused_layer) { | 761 | if (!layer && seat->focused_layer) { |
775 | seat->focused_layer = NULL; | 762 | seat->focused_layer = NULL; |
776 | struct sway_container *previous = | 763 | struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); |
777 | seat_get_focus_inactive(seat, &root_container); | ||
778 | if (previous) { | 764 | 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 | 765 | // Hack to get seat to re-focus the return value of get_focus |
782 | seat_set_focus(seat, NULL); | 766 | seat_set_focus(seat, NULL); |
783 | seat_set_focus(seat, previous); | 767 | seat_set_focus(seat, previous); |
@@ -798,13 +782,9 @@ void seat_set_exclusive_client(struct sway_seat *seat, | |||
798 | seat->exclusive_client = client; | 782 | seat->exclusive_client = client; |
799 | // Triggers a refocus of the topmost surface layer if necessary | 783 | // Triggers a refocus of the topmost surface layer if necessary |
800 | // TODO: Make layer surface focus per-output based on cursor position | 784 | // TODO: Make layer surface focus per-output based on cursor position |
801 | for (int i = 0; i < root_container.children->length; ++i) { | 785 | for (int i = 0; i < root->outputs->length; ++i) { |
802 | struct sway_container *output = root_container.children->items[i]; | 786 | struct sway_output *output = root->outputs->items[i]; |
803 | if (!sway_assert(output->type == C_OUTPUT, | 787 | arrange_layers(output); |
804 | "root container has non-output child")) { | ||
805 | continue; | ||
806 | } | ||
807 | arrange_layers(output->sway_output); | ||
808 | } | 788 | } |
809 | return; | 789 | return; |
810 | } | 790 | } |
@@ -814,9 +794,9 @@ void seat_set_exclusive_client(struct sway_seat *seat, | |||
814 | } | 794 | } |
815 | } | 795 | } |
816 | if (seat->has_focus) { | 796 | if (seat->has_focus) { |
817 | struct sway_container *focus = seat_get_focus(seat); | 797 | struct sway_node *focus = seat_get_focus(seat); |
818 | if (focus->type == C_VIEW && wl_resource_get_client( | 798 | if (node_is_view(focus) && wl_resource_get_client( |
819 | focus->sway_view->surface->resource) != client) { | 799 | focus->sway_container->view->surface->resource) != client) { |
820 | seat_set_focus(seat, NULL); | 800 | seat_set_focus(seat, NULL); |
821 | } | 801 | } |
822 | } | 802 | } |
@@ -837,79 +817,101 @@ void seat_set_exclusive_client(struct sway_seat *seat, | |||
837 | seat->exclusive_client = client; | 817 | seat->exclusive_client = client; |
838 | } | 818 | } |
839 | 819 | ||
840 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, | 820 | struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, |
841 | struct sway_container *con) { | 821 | struct sway_node *node) { |
842 | if (con->type == C_WORKSPACE && !con->children->length && | 822 | if (node_is_view(node)) { |
843 | !con->sway_workspace->floating->length) { | 823 | return node; |
844 | return con; | ||
845 | } | 824 | } |
846 | if (con->type == C_VIEW) { | 825 | struct sway_seat_node *current; |
847 | return con; | ||
848 | } | ||
849 | struct sway_seat_container *current; | ||
850 | wl_list_for_each(current, &seat->focus_stack, link) { | 826 | wl_list_for_each(current, &seat->focus_stack, link) { |
851 | if (container_has_ancestor(current->container, con)) { | 827 | if (node_has_ancestor(current->node, node)) { |
852 | return current->container; | 828 | return current->node; |
853 | } | 829 | } |
854 | } | 830 | } |
831 | if (node->type == N_WORKSPACE) { | ||
832 | return node; | ||
833 | } | ||
855 | return NULL; | 834 | return NULL; |
856 | } | 835 | } |
857 | 836 | ||
858 | struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat, | 837 | struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat, |
859 | struct sway_container *ancestor) { | 838 | struct sway_workspace *workspace) { |
860 | if (ancestor->type == C_WORKSPACE && !ancestor->children->length) { | 839 | if (!workspace->tiling->length) { |
861 | return ancestor; | 840 | return NULL; |
862 | } | 841 | } |
863 | struct sway_seat_container *current; | 842 | struct sway_seat_node *current; |
864 | wl_list_for_each(current, &seat->focus_stack, link) { | 843 | wl_list_for_each(current, &seat->focus_stack, link) { |
865 | struct sway_container *con = current->container; | 844 | struct sway_node *node = current->node; |
866 | if (!container_is_floating_or_child(con) && | 845 | if (node->type == N_CONTAINER && |
867 | container_has_ancestor(current->container, ancestor)) { | 846 | !container_is_floating_or_child(node->sway_container) && |
868 | return con; | 847 | node->sway_container->workspace == workspace) { |
848 | return node->sway_container; | ||
869 | } | 849 | } |
870 | } | 850 | } |
871 | return NULL; | 851 | return NULL; |
872 | } | 852 | } |
873 | 853 | ||
874 | struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat, | 854 | struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat, |
875 | struct sway_container *ancestor) { | 855 | struct sway_workspace *workspace) { |
876 | if (ancestor->type == C_WORKSPACE && | 856 | if (!workspace->floating->length) { |
877 | !ancestor->sway_workspace->floating->length) { | ||
878 | return NULL; | 857 | return NULL; |
879 | } | 858 | } |
880 | struct sway_seat_container *current; | 859 | struct sway_seat_node *current; |
881 | wl_list_for_each(current, &seat->focus_stack, link) { | 860 | wl_list_for_each(current, &seat->focus_stack, link) { |
882 | struct sway_container *con = current->container; | 861 | struct sway_node *node = current->node; |
883 | if (container_is_floating_or_child(con) && | 862 | if (node->type == N_CONTAINER && |
884 | container_has_ancestor(current->container, ancestor)) { | 863 | container_is_floating_or_child(node->sway_container) && |
885 | return con; | 864 | node->sway_container->workspace == workspace) { |
865 | return node->sway_container; | ||
886 | } | 866 | } |
887 | } | 867 | } |
888 | return NULL; | 868 | return NULL; |
889 | } | 869 | } |
890 | 870 | ||
891 | struct sway_container *seat_get_active_child(struct sway_seat *seat, | 871 | struct sway_node *seat_get_active_child(struct sway_seat *seat, |
892 | struct sway_container *parent) { | 872 | struct sway_node *parent) { |
893 | if (parent->type == C_VIEW) { | 873 | if (node_is_view(parent)) { |
894 | return parent; | 874 | return parent; |
895 | } | 875 | } |
896 | struct sway_seat_container *current; | 876 | struct sway_seat_node *current; |
897 | wl_list_for_each(current, &seat->focus_stack, link) { | 877 | wl_list_for_each(current, &seat->focus_stack, link) { |
898 | struct sway_container *con = current->container; | 878 | struct sway_node *node = current->node; |
899 | if (con->parent == parent) { | 879 | if (node_get_parent(node) == parent) { |
900 | return con; | 880 | return node; |
901 | } | 881 | } |
902 | } | 882 | } |
903 | return NULL; | 883 | return NULL; |
904 | } | 884 | } |
905 | 885 | ||
906 | struct sway_container *seat_get_focus(struct sway_seat *seat) { | 886 | struct sway_node *seat_get_focus(struct sway_seat *seat) { |
907 | if (!seat->has_focus) { | 887 | if (!seat->has_focus) { |
908 | return NULL; | 888 | return NULL; |
909 | } | 889 | } |
910 | struct sway_seat_container *current = | 890 | struct sway_seat_node *current = |
911 | wl_container_of(seat->focus_stack.next, current, link); | 891 | wl_container_of(seat->focus_stack.next, current, link); |
912 | return current->container; | 892 | return current->node; |
893 | } | ||
894 | |||
895 | struct sway_workspace *seat_get_focused_workspace(struct sway_seat *seat) { | ||
896 | struct sway_node *focus = seat_get_focus(seat); | ||
897 | if (!focus) { | ||
898 | return NULL; | ||
899 | } | ||
900 | if (focus->type == N_CONTAINER) { | ||
901 | return focus->sway_container->workspace; | ||
902 | } | ||
903 | if (focus->type == N_WORKSPACE) { | ||
904 | return focus->sway_workspace; | ||
905 | } | ||
906 | return NULL; // unreachable | ||
907 | } | ||
908 | |||
909 | struct sway_container *seat_get_focused_container(struct sway_seat *seat) { | ||
910 | struct sway_node *focus = seat_get_focus(seat); | ||
911 | if (focus && focus->type == N_CONTAINER) { | ||
912 | return focus->sway_container; | ||
913 | } | ||
914 | return NULL; | ||
913 | } | 915 | } |
914 | 916 | ||
915 | void seat_apply_config(struct sway_seat *seat, | 917 | void seat_apply_config(struct sway_seat *seat, |