diff options
author | Tony Crisci <tony@dubstepdish.com> | 2018-02-04 13:39:10 -0500 |
---|---|---|
committer | Tony Crisci <tony@dubstepdish.com> | 2018-02-04 14:08:54 -0500 |
commit | 515150229847c9ebdfd0cabb6f0026fca9d57a23 (patch) | |
tree | 8a50ce0ac8ce4dc2ec973c63c68dc45378c50737 | |
parent | Implement workspaces (diff) | |
download | sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.tar.gz sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.tar.zst sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.zip |
basic focus overhaul
-rw-r--r-- | include/sway/container.h | 6 | ||||
-rw-r--r-- | include/sway/input/seat.h | 16 | ||||
-rw-r--r-- | include/sway/layout.h | 6 | ||||
-rw-r--r-- | sway/commands.c | 5 | ||||
-rw-r--r-- | sway/commands/kill.c | 7 | ||||
-rw-r--r-- | sway/commands/workspace.c | 3 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 3 | ||||
-rw-r--r-- | sway/input/input-manager.c | 2 | ||||
-rw-r--r-- | sway/input/seat.c | 137 | ||||
-rw-r--r-- | sway/tree/container.c | 33 | ||||
-rw-r--r-- | sway/tree/layout.c | 30 | ||||
-rw-r--r-- | sway/tree/workspace.c | 17 |
12 files changed, 225 insertions, 40 deletions
diff --git a/include/sway/container.h b/include/sway/container.h index 0c66932d..997240bd 100644 --- a/include/sway/container.h +++ b/include/sway/container.h | |||
@@ -162,4 +162,10 @@ void container_map(swayc_t *container, | |||
162 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, | 162 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, |
163 | struct wlr_surface **surface, double *sx, double *sy); | 163 | struct wlr_surface **surface, double *sx, double *sy); |
164 | 164 | ||
165 | /** | ||
166 | * Get a list of containers that are descendents of the container in rendering | ||
167 | * order | ||
168 | */ | ||
169 | list_t *container_list_children(swayc_t *con); | ||
170 | |||
165 | #endif | 171 | #endif |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index b21cbccb..8d5d6b75 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -12,14 +12,26 @@ struct sway_seat_device { | |||
12 | struct wl_list link; // sway_seat::devices | 12 | struct wl_list link; // sway_seat::devices |
13 | }; | 13 | }; |
14 | 14 | ||
15 | struct sway_seat_container { | ||
16 | struct sway_seat *seat; | ||
17 | swayc_t *container; | ||
18 | |||
19 | struct wl_list link; // sway_seat::focus_stack | ||
20 | |||
21 | struct wl_listener destroy; | ||
22 | }; | ||
23 | |||
15 | struct sway_seat { | 24 | struct sway_seat { |
16 | struct wlr_seat *wlr_seat; | 25 | struct wlr_seat *wlr_seat; |
17 | struct seat_config *config; | 26 | struct seat_config *config; |
18 | struct sway_cursor *cursor; | 27 | struct sway_cursor *cursor; |
19 | struct sway_input_manager *input; | 28 | struct sway_input_manager *input; |
20 | swayc_t *focus; | 29 | |
30 | bool has_focus; | ||
31 | struct wl_list focus_stack; // list of containers in focus order | ||
21 | 32 | ||
22 | struct wl_listener focus_destroy; | 33 | struct wl_listener focus_destroy; |
34 | struct wl_listener new_container; | ||
23 | 35 | ||
24 | struct wl_list devices; // sway_seat_device::link | 36 | struct wl_list devices; // sway_seat_device::link |
25 | 37 | ||
@@ -44,6 +56,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat); | |||
44 | 56 | ||
45 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); | 57 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); |
46 | 58 | ||
59 | swayc_t *sway_seat_get_focus(struct sway_seat *seat, swayc_t *container); | ||
60 | |||
47 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); | 61 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); |
48 | 62 | ||
49 | #endif | 63 | #endif |
diff --git a/include/sway/layout.h b/include/sway/layout.h index af561453..69a66674 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _SWAY_LAYOUT_H | 2 | #define _SWAY_LAYOUT_H |
3 | 3 | ||
4 | #include <wlr/types/wlr_output_layout.h> | 4 | #include <wlr/types/wlr_output_layout.h> |
5 | #include "sway/container.h" | ||
5 | 6 | ||
6 | struct sway_container; | 7 | struct sway_container; |
7 | 8 | ||
@@ -11,10 +12,15 @@ struct sway_root { | |||
11 | struct wl_listener output_layout_change; | 12 | struct wl_listener output_layout_change; |
12 | 13 | ||
13 | struct wl_list unmanaged_views; // sway_view::unmanaged_view_link | 14 | struct wl_list unmanaged_views; // sway_view::unmanaged_view_link |
15 | |||
16 | struct { | ||
17 | struct wl_signal new_container; | ||
18 | } events; | ||
14 | }; | 19 | }; |
15 | 20 | ||
16 | void init_layout(void); | 21 | void init_layout(void); |
17 | void add_child(struct sway_container *parent, struct sway_container *child); | 22 | void add_child(struct sway_container *parent, struct sway_container *child); |
23 | swayc_t *add_sibling(swayc_t *parent, swayc_t *child); | ||
18 | struct sway_container *remove_child(struct sway_container *child); | 24 | struct sway_container *remove_child(struct sway_container *child); |
19 | enum swayc_layouts default_layout(struct sway_container *output); | 25 | enum swayc_layouts default_layout(struct sway_container *output); |
20 | void sort_workspaces(struct sway_container *output); | 26 | void sort_workspaces(struct sway_container *output); |
diff --git a/sway/commands.c b/sway/commands.c index 0d4aa104..6bb4db0b 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -281,7 +281,10 @@ struct cmd_results *handle_command(char *_exec) { | |||
281 | seat = sway_input_manager_get_default_seat(input_manager); | 281 | seat = sway_input_manager_get_default_seat(input_manager); |
282 | } | 282 | } |
283 | if (seat) { | 283 | if (seat) { |
284 | config->handler_context.current_container = seat->focus; | 284 | config->handler_context.current_container = |
285 | (seat->has_focus ? | ||
286 | sway_seat_get_focus(seat, &root_container) : | ||
287 | NULL); | ||
285 | struct cmd_results *res = handler->handle(argc-1, argv+1); | 288 | struct cmd_results *res = handler->handle(argc-1, argv+1); |
286 | if (res->status != CMD_SUCCESS) { | 289 | if (res->status != CMD_SUCCESS) { |
287 | free_argv(argc, argv); | 290 | free_argv(argc, argv); |
diff --git a/sway/commands/kill.c b/sway/commands/kill.c index cebf7f3c..4b3666be 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c | |||
@@ -10,11 +10,16 @@ struct cmd_results *cmd_kill(int argc, char **argv) { | |||
10 | return cmd_results_new(CMD_FAILURE, "kill", | 10 | return cmd_results_new(CMD_FAILURE, "kill", |
11 | "Command 'kill' cannot be used in the config file"); | 11 | "Command 'kill' cannot be used in the config file"); |
12 | } | 12 | } |
13 | if (config->handler_context.current_container == NULL) { | ||
14 | wlr_log(L_DEBUG, "no container to kill"); | ||
15 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
16 | } | ||
13 | enum swayc_types type = config->handler_context.current_container->type; | 17 | enum swayc_types type = config->handler_context.current_container->type; |
14 | if (type != C_VIEW || type != C_CONTAINER) { | 18 | if (type != C_VIEW && type != C_CONTAINER) { |
15 | return cmd_results_new(CMD_INVALID, NULL, | 19 | return cmd_results_new(CMD_INVALID, NULL, |
16 | "Can only kill views and containers with this command"); | 20 | "Can only kill views and containers with this command"); |
17 | } | 21 | } |
22 | |||
18 | // TODO close arbitrary containers without a view | 23 | // TODO close arbitrary containers without a view |
19 | struct sway_view *view = | 24 | struct sway_view *view = |
20 | config->handler_context.current_container->sway_view; | 25 | config->handler_context.current_container->sway_view; |
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 12984ed4..e7d6cc9f 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c | |||
@@ -90,7 +90,8 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | |||
90 | free(name); | 90 | free(name); |
91 | } | 91 | } |
92 | workspace_switch(ws); | 92 | workspace_switch(ws); |
93 | current_container = config->handler_context.seat->focus; | 93 | current_container = |
94 | sway_seat_get_focus(config->handler_context.seat, &root_container); | ||
94 | swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); | 95 | swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); |
95 | 96 | ||
96 | if (config->mouse_warping && old_output != new_output) { | 97 | if (config->mouse_warping && old_output != new_output) { |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index ca56a9c0..04d89015 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -135,7 +135,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
135 | wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); | 135 | wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); |
136 | 136 | ||
137 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 137 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
138 | swayc_t *cont = new_view(seat->focus, sway_view); | 138 | swayc_t *focus = sway_seat_get_focus(seat, &root_container); |
139 | swayc_t *cont = new_view(focus, sway_view); | ||
139 | sway_view->swayc = cont; | 140 | sway_view->swayc = cont; |
140 | 141 | ||
141 | arrange_windows(cont->parent, -1, -1); | 142 | arrange_windows(cont->parent, -1, -1); |
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index d789c7eb..a406636e 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -282,7 +282,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, | |||
282 | swayc_t *container) { | 282 | swayc_t *container) { |
283 | struct sway_seat *seat = NULL; | 283 | struct sway_seat *seat = NULL; |
284 | wl_list_for_each(seat, &input->seats, link) { | 284 | wl_list_for_each(seat, &input->seats, link) { |
285 | if (seat->focus == container) { | 285 | if (seat->has_focus && sway_seat_get_focus(seat, &root_container) == container) { |
286 | return true; | 286 | return true; |
287 | } | 287 | } |
288 | } | 288 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 5e87986d..cbf05abd 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -32,6 +32,44 @@ void sway_seat_destroy(struct sway_seat *seat) { | |||
32 | wlr_seat_destroy(seat->wlr_seat); | 32 | wlr_seat_destroy(seat->wlr_seat); |
33 | } | 33 | } |
34 | 34 | ||
35 | static void handle_seat_container_destroy(struct wl_listener *listener, | ||
36 | void *data) { | ||
37 | struct sway_seat_container *seat_con = | ||
38 | wl_container_of(listener, seat_con, destroy); | ||
39 | wl_list_remove(&seat_con->link); | ||
40 | wl_list_remove(&seat_con->destroy.link); | ||
41 | free(seat_con); | ||
42 | } | ||
43 | |||
44 | static struct sway_seat_container *seat_container_from_container( | ||
45 | struct sway_seat *seat, swayc_t *con) { | ||
46 | struct sway_seat_container *seat_con = NULL; | ||
47 | wl_list_for_each(seat_con, &seat->focus_stack, link) { | ||
48 | if (seat_con->container == con) { | ||
49 | return seat_con; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | seat_con = calloc(1, sizeof(struct sway_seat_container)); | ||
54 | if (seat_con == NULL) { | ||
55 | wlr_log(L_ERROR, "could not allocate seat container"); | ||
56 | return NULL; | ||
57 | } | ||
58 | |||
59 | seat_con->container = con; | ||
60 | wl_list_insert(seat->focus_stack.prev, &seat_con->link); | ||
61 | wl_signal_add(&con->events.destroy, &seat_con->destroy); | ||
62 | seat_con->destroy.notify = handle_seat_container_destroy; | ||
63 | |||
64 | return seat_con; | ||
65 | } | ||
66 | |||
67 | static void handle_new_container(struct wl_listener *listener, void *data) { | ||
68 | struct sway_seat *seat = wl_container_of(listener, seat, new_container); | ||
69 | swayc_t *con = data; | ||
70 | seat_container_from_container(seat, con); | ||
71 | } | ||
72 | |||
35 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | 73 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, |
36 | const char *seat_name) { | 74 | const char *seat_name) { |
37 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); | 75 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); |
@@ -52,6 +90,24 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, | |||
52 | return NULL; | 90 | return NULL; |
53 | } | 91 | } |
54 | 92 | ||
93 | // init the focus stack | ||
94 | wl_list_init(&seat->focus_stack); | ||
95 | list_t *containers = container_list_children(&root_container); | ||
96 | if (containers == NULL) { | ||
97 | wlr_seat_destroy(seat->wlr_seat); | ||
98 | free(seat); | ||
99 | return NULL; | ||
100 | } | ||
101 | for (int i = containers->length - 1; i >= 0; --i) { | ||
102 | swayc_t *con = containers->items[i]; | ||
103 | seat_container_from_container(seat, con); | ||
104 | } | ||
105 | free(containers); | ||
106 | |||
107 | wl_signal_add(&root_container.sway_root->events.new_container, | ||
108 | &seat->new_container); | ||
109 | seat->new_container.notify = handle_new_container; | ||
110 | |||
55 | seat->input = input; | 111 | seat->input = input; |
56 | wl_list_init(&seat->devices); | 112 | wl_list_init(&seat->devices); |
57 | 113 | ||
@@ -82,12 +138,15 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
82 | sway_keyboard_configure(seat_device->keyboard); | 138 | sway_keyboard_configure(seat_device->keyboard); |
83 | wlr_seat_set_keyboard(seat->wlr_seat, | 139 | wlr_seat_set_keyboard(seat->wlr_seat, |
84 | seat_device->input_device->wlr_device); | 140 | seat_device->input_device->wlr_device); |
85 | if (seat->focus && seat->focus->type == C_VIEW) { | 141 | if (seat->has_focus) { |
86 | // force notify reenter to pick up the new configuration | 142 | swayc_t *focus = sway_seat_get_focus(seat, &root_container); |
87 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); | 143 | if (focus && focus->type == C_VIEW) { |
88 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, | 144 | // force notify reenter to pick up the new configuration |
89 | seat->focus->sway_view->surface, wlr_keyboard->keycodes, | 145 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); |
90 | wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); | 146 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, |
147 | focus->sway_view->surface, wlr_keyboard->keycodes, | ||
148 | wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); | ||
149 | } | ||
91 | } | 150 | } |
92 | } | 151 | } |
93 | 152 | ||
@@ -211,35 +270,43 @@ static void handle_focus_destroy(struct wl_listener *listener, void *data) { | |||
211 | } | 270 | } |
212 | 271 | ||
213 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { | 272 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { |
214 | swayc_t *last_focus = seat->focus; | 273 | swayc_t *last_focus = |
274 | (seat->has_focus ? sway_seat_get_focus(seat, &root_container) : NULL); | ||
215 | 275 | ||
216 | if (last_focus == container) { | 276 | if (container && last_focus == container) { |
217 | return; | 277 | return; |
218 | } | 278 | } |
219 | 279 | ||
220 | if (last_focus && last_focus->type == C_VIEW) { | 280 | if (last_focus) { |
221 | wl_list_remove(&seat->focus_destroy.link); | 281 | wl_list_remove(&seat->focus_destroy.link); |
282 | seat->has_focus = false; | ||
222 | } | 283 | } |
223 | 284 | ||
224 | if (container && container->type == C_VIEW) { | 285 | if (container) { |
225 | struct sway_view *view = container->sway_view; | 286 | struct sway_seat_container *seat_con = |
226 | view_set_activated(view, true); | 287 | seat_container_from_container(seat, container); |
227 | wl_signal_add(&container->events.destroy, &seat->focus_destroy); | 288 | wl_signal_add(&container->events.destroy, &seat->focus_destroy); |
228 | seat->focus_destroy.notify = handle_focus_destroy; | 289 | seat->focus_destroy.notify = handle_focus_destroy; |
229 | 290 | seat->has_focus = true; | |
230 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); | 291 | |
231 | if (keyboard) { | 292 | wl_list_remove(&seat_con->link); |
232 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, | 293 | wl_list_insert(&seat->focus_stack, &seat_con->link); |
233 | keyboard->keycodes, keyboard->num_keycodes, | 294 | |
234 | &keyboard->modifiers); | 295 | if (container->type == C_VIEW) { |
235 | } else { | 296 | struct sway_view *view = container->sway_view; |
236 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, | 297 | view_set_activated(view, true); |
237 | NULL, 0, NULL); | 298 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); |
299 | if (keyboard) { | ||
300 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, | ||
301 | keyboard->keycodes, keyboard->num_keycodes, | ||
302 | &keyboard->modifiers); | ||
303 | } else { | ||
304 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, | ||
305 | NULL, 0, NULL); | ||
306 | } | ||
238 | } | 307 | } |
239 | } | 308 | } |
240 | 309 | ||
241 | seat->focus = container; | ||
242 | |||
243 | if (last_focus && last_focus->type == C_VIEW && | 310 | if (last_focus && last_focus->type == C_VIEW && |
244 | !sway_input_manager_has_focus(seat->input, last_focus)) { | 311 | !sway_input_manager_has_focus(seat->input, last_focus)) { |
245 | struct sway_view *view = last_focus->sway_view; | 312 | struct sway_view *view = last_focus->sway_view; |
@@ -247,6 +314,30 @@ void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { | |||
247 | } | 314 | } |
248 | } | 315 | } |
249 | 316 | ||
317 | swayc_t *sway_seat_get_focus(struct sway_seat *seat, swayc_t *container) { | ||
318 | struct sway_seat_container *current = NULL; | ||
319 | swayc_t *parent = NULL; | ||
320 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
321 | if (current->container->type < C_WORKSPACE) { | ||
322 | continue; | ||
323 | } | ||
324 | parent = current->container->parent; | ||
325 | |||
326 | if (current->container == container) { | ||
327 | return current->container; | ||
328 | } | ||
329 | |||
330 | while (parent) { | ||
331 | if (parent == container) { | ||
332 | return current->container; | ||
333 | } | ||
334 | parent = parent->parent; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | return NULL; | ||
339 | } | ||
340 | |||
250 | void sway_seat_set_config(struct sway_seat *seat, | 341 | void sway_seat_set_config(struct sway_seat *seat, |
251 | struct seat_config *seat_config) { | 342 | struct seat_config *seat_config) { |
252 | // clear configs | 343 | // clear configs |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 48aabd86..67fac5ee 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -158,12 +158,13 @@ swayc_t *new_output(struct sway_output *sway_output) { | |||
158 | // struct instead of trying to do focus semantics like this | 158 | // struct instead of trying to do focus semantics like this |
159 | struct sway_seat *seat = NULL; | 159 | struct sway_seat *seat = NULL; |
160 | wl_list_for_each(seat, &input_manager->seats, link) { | 160 | wl_list_for_each(seat, &input_manager->seats, link) { |
161 | if (!seat->focus) { | 161 | if (!seat->has_focus) { |
162 | seat->focus = ws; | 162 | sway_seat_set_focus(seat, ws); |
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | free(ws_name); | 166 | free(ws_name); |
167 | wl_signal_emit(&root_container.sway_root->events.new_container, output); | ||
167 | return output; | 168 | return output; |
168 | } | 169 | } |
169 | 170 | ||
@@ -185,6 +186,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { | |||
185 | 186 | ||
186 | add_child(output, workspace); | 187 | add_child(output, workspace); |
187 | sort_workspaces(output); | 188 | sort_workspaces(output); |
189 | wl_signal_emit(&root_container.sway_root->events.new_container, workspace); | ||
188 | return workspace; | 190 | return workspace; |
189 | } | 191 | } |
190 | 192 | ||
@@ -207,9 +209,9 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { | |||
207 | add_child(sibling, swayc); | 209 | add_child(sibling, swayc); |
208 | } else { | 210 | } else { |
209 | // Regular case, create as sibling of current container | 211 | // Regular case, create as sibling of current container |
210 | // TODO WLR | 212 | add_sibling(sibling, swayc); |
211 | //add_sibling(sibling, swayc); | ||
212 | } | 213 | } |
214 | wl_signal_emit(&root_container.sway_root->events.new_container, swayc); | ||
213 | return swayc; | 215 | return swayc; |
214 | } | 216 | } |
215 | 217 | ||
@@ -378,3 +380,26 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi | |||
378 | f(container, data); | 380 | f(container, data); |
379 | } | 381 | } |
380 | } | 382 | } |
383 | |||
384 | /** | ||
385 | * Get a list of containers that are descendents of the container in rendering | ||
386 | * order | ||
387 | */ | ||
388 | list_t *container_list_children(swayc_t *con) { | ||
389 | list_t *list = create_list(); | ||
390 | list_t *queue = create_list(); | ||
391 | |||
392 | list_add(queue, con); | ||
393 | |||
394 | swayc_t *current = NULL; | ||
395 | while (queue->length) { | ||
396 | current = queue->items[0]; | ||
397 | list_del(queue, 0); | ||
398 | list_add(list, current); | ||
399 | // TODO floating containers | ||
400 | list_cat(queue, current->children); | ||
401 | } | ||
402 | |||
403 | list_free(queue); | ||
404 | return list; | ||
405 | } | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 41ff81b2..45f8c3ae 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -48,10 +48,12 @@ void init_layout(void) { | |||
48 | root_container.layout = L_NONE; | 48 | root_container.layout = L_NONE; |
49 | root_container.name = strdup("root"); | 49 | root_container.name = strdup("root"); |
50 | root_container.children = create_list(); | 50 | root_container.children = create_list(); |
51 | wl_signal_init(&root_container.events.destroy); | ||
51 | 52 | ||
52 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | 53 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); |
53 | root_container.sway_root->output_layout = wlr_output_layout_create(); | 54 | root_container.sway_root->output_layout = wlr_output_layout_create(); |
54 | wl_list_init(&root_container.sway_root->unmanaged_views); | 55 | wl_list_init(&root_container.sway_root->unmanaged_views); |
56 | wl_signal_init(&root_container.sway_root->events.new_container); | ||
55 | 57 | ||
56 | root_container.sway_root->output_layout_change.notify = | 58 | root_container.sway_root->output_layout_change.notify = |
57 | output_layout_change_notify; | 59 | output_layout_change_notify; |
@@ -59,6 +61,34 @@ void init_layout(void) { | |||
59 | &root_container.sway_root->output_layout_change); | 61 | &root_container.sway_root->output_layout_change); |
60 | } | 62 | } |
61 | 63 | ||
64 | int index_child(const swayc_t *child) { | ||
65 | // TODO handle floating | ||
66 | swayc_t *parent = child->parent; | ||
67 | int i, len; | ||
68 | len = parent->children->length; | ||
69 | for (i = 0; i < len; ++i) { | ||
70 | if (parent->children->items[i] == child) { | ||
71 | break; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | if (!sway_assert(i < len, "Stray container")) { | ||
76 | return -1; | ||
77 | } | ||
78 | return i; | ||
79 | } | ||
80 | |||
81 | swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { | ||
82 | // TODO handle floating | ||
83 | swayc_t *parent = fixed->parent; | ||
84 | int i = index_child(fixed); | ||
85 | list_insert(parent->children, i + 1, active); | ||
86 | active->parent = parent; | ||
87 | // focus new child | ||
88 | parent->focused = active; | ||
89 | return active->parent; | ||
90 | } | ||
91 | |||
62 | void add_child(swayc_t *parent, swayc_t *child) { | 92 | void add_child(swayc_t *parent, swayc_t *child) { |
63 | wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", | 93 | wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", |
64 | child, child->type, child->width, child->height, | 94 | child, child->type, child->width, child->height, |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 23c630b6..ce5b425c 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -63,9 +63,10 @@ static bool _workspace_by_name(swayc_t *view, void *data) { | |||
63 | swayc_t *workspace_by_name(const char *name) { | 63 | swayc_t *workspace_by_name(const char *name) { |
64 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 64 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
65 | swayc_t *current_workspace = NULL, *current_output = NULL; | 65 | swayc_t *current_workspace = NULL, *current_output = NULL; |
66 | if (seat->focus) { | 66 | if (seat->has_focus) { |
67 | current_workspace = swayc_parent_by_type(seat->focus, C_WORKSPACE); | 67 | swayc_t *focus = sway_seat_get_focus(seat, &root_container); |
68 | current_output = swayc_parent_by_type(seat->focus, C_OUTPUT); | 68 | current_workspace = swayc_parent_by_type(focus, C_WORKSPACE); |
69 | current_output = swayc_parent_by_type(focus, C_OUTPUT); | ||
69 | } | 70 | } |
70 | if (strcmp(name, "prev") == 0) { | 71 | if (strcmp(name, "prev") == 0) { |
71 | return workspace_prev(current_workspace); | 72 | return workspace_prev(current_workspace); |
@@ -102,7 +103,8 @@ swayc_t *workspace_create(const char *name) { | |||
102 | } | 103 | } |
103 | // Otherwise create a new one | 104 | // Otherwise create a new one |
104 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 105 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
105 | parent = seat->focus; | 106 | swayc_t *focus = sway_seat_get_focus(seat, &root_container); |
107 | parent = focus; | ||
106 | parent = swayc_parent_by_type(parent, C_OUTPUT); | 108 | parent = swayc_parent_by_type(parent, C_OUTPUT); |
107 | return new_workspace(parent, name); | 109 | return new_workspace(parent, name); |
108 | } | 110 | } |
@@ -193,12 +195,13 @@ bool workspace_switch(swayc_t *workspace) { | |||
193 | return false; | 195 | return false; |
194 | } | 196 | } |
195 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 197 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
196 | if (!seat || !seat->focus) { | 198 | swayc_t *focus = sway_seat_get_focus(seat, &root_container); |
199 | if (!seat || !focus) { | ||
197 | return false; | 200 | return false; |
198 | } | 201 | } |
199 | swayc_t *active_ws = seat->focus; | 202 | swayc_t *active_ws = focus; |
200 | if (active_ws->type != C_WORKSPACE) { | 203 | if (active_ws->type != C_WORKSPACE) { |
201 | swayc_parent_by_type(seat->focus, C_WORKSPACE); | 204 | swayc_parent_by_type(focus, C_WORKSPACE); |
202 | } | 205 | } |
203 | 206 | ||
204 | if (config->auto_back_and_forth | 207 | if (config->auto_back_and_forth |