diff options
-rw-r--r-- | include/sway/container.h | 10 | ||||
-rw-r--r-- | include/sway/input/seat.h | 21 | ||||
-rw-r--r-- | include/sway/layout.h | 20 | ||||
-rw-r--r-- | include/sway/workspace.h | 10 | ||||
-rw-r--r-- | sway/commands.c | 3 | ||||
-rw-r--r-- | sway/commands/kill.c | 7 | ||||
-rw-r--r-- | sway/commands/workspace.c | 3 | ||||
-rw-r--r-- | sway/desktop/output.c | 10 | ||||
-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 | 183 | ||||
-rw-r--r-- | sway/ipc-json.c | 4 | ||||
-rw-r--r-- | sway/tree/container.c | 33 | ||||
-rw-r--r-- | sway/tree/layout.c | 208 | ||||
-rw-r--r-- | sway/tree/workspace.c | 37 |
15 files changed, 480 insertions, 74 deletions
diff --git a/include/sway/container.h b/include/sway/container.h index 0c66932d..48363be6 100644 --- a/include/sway/container.h +++ b/include/sway/container.h | |||
@@ -106,10 +106,6 @@ struct sway_container { | |||
106 | * The parent of this container. NULL for the root container. | 106 | * The parent of this container. NULL for the root container. |
107 | */ | 107 | */ |
108 | struct sway_container *parent; | 108 | struct sway_container *parent; |
109 | /** | ||
110 | * Which of this container's children has focus. | ||
111 | */ | ||
112 | struct sway_container *focused; | ||
113 | 109 | ||
114 | /** | 110 | /** |
115 | * Number of master views in auto layouts. | 111 | * Number of master views in auto layouts. |
@@ -162,4 +158,10 @@ void container_map(swayc_t *container, | |||
162 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, | 158 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, |
163 | struct wlr_surface **surface, double *sx, double *sy); | 159 | struct wlr_surface **surface, double *sx, double *sy); |
164 | 160 | ||
161 | /** | ||
162 | * Apply the function for each child of the container breadth first. | ||
163 | */ | ||
164 | void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), | ||
165 | void *data); | ||
166 | |||
165 | #endif | 167 | #endif |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index b21cbccb..f9244f43 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,13 @@ 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); | ||
60 | |||
61 | swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container); | ||
62 | |||
63 | swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, | ||
64 | enum swayc_types type); | ||
65 | |||
47 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); | 66 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); |
48 | 67 | ||
49 | #endif | 68 | #endif |
diff --git a/include/sway/layout.h b/include/sway/layout.h index af561453..e82c4442 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h | |||
@@ -2,6 +2,19 @@ | |||
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" | ||
6 | |||
7 | enum movement_direction { | ||
8 | MOVE_LEFT, | ||
9 | MOVE_RIGHT, | ||
10 | MOVE_UP, | ||
11 | MOVE_DOWN, | ||
12 | MOVE_PARENT, | ||
13 | MOVE_CHILD, | ||
14 | MOVE_NEXT, | ||
15 | MOVE_PREV, | ||
16 | MOVE_FIRST | ||
17 | }; | ||
5 | 18 | ||
6 | struct sway_container; | 19 | struct sway_container; |
7 | 20 | ||
@@ -11,13 +24,20 @@ struct sway_root { | |||
11 | struct wl_listener output_layout_change; | 24 | struct wl_listener output_layout_change; |
12 | 25 | ||
13 | struct wl_list unmanaged_views; // sway_view::unmanaged_view_link | 26 | struct wl_list unmanaged_views; // sway_view::unmanaged_view_link |
27 | |||
28 | struct { | ||
29 | struct wl_signal new_container; | ||
30 | } events; | ||
14 | }; | 31 | }; |
15 | 32 | ||
16 | void init_layout(void); | 33 | void init_layout(void); |
17 | void add_child(struct sway_container *parent, struct sway_container *child); | 34 | void add_child(struct sway_container *parent, struct sway_container *child); |
35 | swayc_t *add_sibling(swayc_t *parent, swayc_t *child); | ||
18 | struct sway_container *remove_child(struct sway_container *child); | 36 | struct sway_container *remove_child(struct sway_container *child); |
19 | enum swayc_layouts default_layout(struct sway_container *output); | 37 | enum swayc_layouts default_layout(struct sway_container *output); |
20 | void sort_workspaces(struct sway_container *output); | 38 | void sort_workspaces(struct sway_container *output); |
21 | void arrange_windows(struct sway_container *container, double width, double height); | 39 | void arrange_windows(struct sway_container *container, double width, double height); |
40 | swayc_t *get_swayc_in_direction(swayc_t *container, | ||
41 | struct sway_seat *seat, enum movement_direction dir); | ||
22 | 42 | ||
23 | #endif | 43 | #endif |
diff --git a/include/sway/workspace.h b/include/sway/workspace.h index 30bbdaa8..ca6f9bdb 100644 --- a/include/sway/workspace.h +++ b/include/sway/workspace.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef _SWAY_WORKSPACE_H | 1 | #ifndef _SWAY_WORKSPACE_H |
2 | #define _SWAY_WORKSPACE_H | 2 | #define _SWAY_WORKSPACE_H |
3 | 3 | ||
4 | struct sway_container; | 4 | #include <sway/container.h> |
5 | 5 | ||
6 | extern char *prev_workspace_name; | 6 | extern char *prev_workspace_name; |
7 | 7 | ||
@@ -12,9 +12,9 @@ bool workspace_switch(swayc_t *workspace); | |||
12 | struct sway_container *workspace_by_number(const char* name); | 12 | struct sway_container *workspace_by_number(const char* name); |
13 | swayc_t *workspace_by_name(const char*); | 13 | swayc_t *workspace_by_name(const char*); |
14 | 14 | ||
15 | struct sway_container *workspace_output_next(struct sway_container *current); | 15 | struct sway_container *workspace_output_next(swayc_t *current); |
16 | struct sway_container *workspace_next(struct sway_container *current); | 16 | struct sway_container *workspace_next(swayc_t *current); |
17 | struct sway_container *workspace_output_prev(struct sway_container *current); | 17 | struct sway_container *workspace_output_prev(swayc_t *current); |
18 | struct sway_container *workspace_prev(struct sway_container *current); | 18 | struct sway_container *workspace_prev(swayc_t *current); |
19 | 19 | ||
20 | #endif | 20 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index 0d4aa104..d8d29a1c 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -281,7 +281,8 @@ 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 | sway_seat_get_focus(seat); | ||
285 | struct cmd_results *res = handler->handle(argc-1, argv+1); | 286 | struct cmd_results *res = handler->handle(argc-1, argv+1); |
286 | if (res->status != CMD_SUCCESS) { | 287 | if (res->status != CMD_SUCCESS) { |
287 | free_argv(argc, argv); | 288 | 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..fa891398 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); | ||
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/output.c b/sway/desktop/output.c index a66601b5..e250d450 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -220,12 +220,18 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
220 | struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); | 220 | struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); |
221 | wlr_renderer_clear(renderer, &clear_color); | 221 | wlr_renderer_clear(renderer, &clear_color); |
222 | 222 | ||
223 | wlr_renderer_clear(renderer, &clear_color); | ||
224 | |||
223 | int buffer_age = -1; | 225 | int buffer_age = -1; |
224 | wlr_output_make_current(wlr_output, &buffer_age); | 226 | wlr_output_make_current(wlr_output, &buffer_age); |
225 | wlr_renderer_begin(server->renderer, wlr_output); | ||
226 | wlr_renderer_begin(server->renderer, wlr_output); | 227 | wlr_renderer_begin(server->renderer, wlr_output); |
227 | 228 | ||
228 | swayc_t *workspace = soutput->swayc->focused; | 229 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
230 | swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); | ||
231 | swayc_t *workspace = (focus->type == C_WORKSPACE ? | ||
232 | focus : | ||
233 | swayc_parent_by_type(focus, C_WORKSPACE)); | ||
234 | |||
229 | swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); | 235 | swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); |
230 | 236 | ||
231 | // render unmanaged views on top | 237 | // render unmanaged views on top |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index ca56a9c0..b44d9e54 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_inactive(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 f59daea3..e6708bad 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -281,7 +281,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, | |||
281 | swayc_t *container) { | 281 | swayc_t *container) { |
282 | struct sway_seat *seat = NULL; | 282 | struct sway_seat *seat = NULL; |
283 | wl_list_for_each(seat, &input->seats, link) { | 283 | wl_list_for_each(seat, &input->seats, link) { |
284 | if (seat->focus == container) { | 284 | if (sway_seat_get_focus(seat) == container) { |
285 | return true; | 285 | return true; |
286 | } | 286 | } |
287 | } | 287 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 5e87986d..648e7914 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -32,6 +32,81 @@ 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 | struct sway_seat *seat = seat_con->seat; | ||
40 | swayc_t *con = seat_con->container; | ||
41 | |||
42 | bool is_focus = (sway_seat_get_focus(seat) == con); | ||
43 | |||
44 | wl_list_remove(&seat_con->link); | ||
45 | |||
46 | if (is_focus) { | ||
47 | // pick next focus | ||
48 | sway_seat_set_focus(seat, NULL); | ||
49 | swayc_t *next = sway_seat_get_focus_inactive(seat, con->parent); | ||
50 | if (next == NULL) { | ||
51 | next = con->parent; | ||
52 | } | ||
53 | sway_seat_set_focus(seat, next); | ||
54 | } | ||
55 | |||
56 | wl_list_remove(&seat_con->destroy.link); | ||
57 | |||
58 | free(seat_con); | ||
59 | } | ||
60 | |||
61 | static struct sway_seat_container *seat_container_from_container( | ||
62 | struct sway_seat *seat, swayc_t *con) { | ||
63 | if (con->type < C_WORKSPACE) { | ||
64 | // these don't get seat containers ever | ||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | struct sway_seat_container *seat_con = NULL; | ||
69 | wl_list_for_each(seat_con, &seat->focus_stack, link) { | ||
70 | if (seat_con->container == con) { | ||
71 | return seat_con; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | seat_con = calloc(1, sizeof(struct sway_seat_container)); | ||
76 | if (seat_con == NULL) { | ||
77 | wlr_log(L_ERROR, "could not allocate seat container"); | ||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | seat_con->container = con; | ||
82 | seat_con->seat = seat; | ||
83 | wl_list_insert(seat->focus_stack.prev, &seat_con->link); | ||
84 | wl_signal_add(&con->events.destroy, &seat_con->destroy); | ||
85 | seat_con->destroy.notify = handle_seat_container_destroy; | ||
86 | |||
87 | return seat_con; | ||
88 | } | ||
89 | |||
90 | static void handle_new_container(struct wl_listener *listener, void *data) { | ||
91 | struct sway_seat *seat = wl_container_of(listener, seat, new_container); | ||
92 | swayc_t *con = data; | ||
93 | seat_container_from_container(seat, con); | ||
94 | } | ||
95 | |||
96 | static void collect_focus_iter(swayc_t *con, void *data) { | ||
97 | struct sway_seat *seat = data; | ||
98 | if (con->type > C_WORKSPACE) { | ||
99 | return; | ||
100 | } | ||
101 | struct sway_seat_container *seat_con = | ||
102 | seat_container_from_container(seat, con); | ||
103 | if (!seat_con) { | ||
104 | return; | ||
105 | } | ||
106 | wl_list_remove(&seat_con->link); | ||
107 | wl_list_insert(&seat->focus_stack, &seat_con->link); | ||
108 | } | ||
109 | |||
35 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | 110 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, |
36 | const char *seat_name) { | 111 | const char *seat_name) { |
37 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); | 112 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); |
@@ -52,6 +127,15 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, | |||
52 | return NULL; | 127 | return NULL; |
53 | } | 128 | } |
54 | 129 | ||
130 | // init the focus stack | ||
131 | wl_list_init(&seat->focus_stack); | ||
132 | |||
133 | container_for_each_bfs(&root_container, collect_focus_iter, seat); | ||
134 | |||
135 | wl_signal_add(&root_container.sway_root->events.new_container, | ||
136 | &seat->new_container); | ||
137 | seat->new_container.notify = handle_new_container; | ||
138 | |||
55 | seat->input = input; | 139 | seat->input = input; |
56 | wl_list_init(&seat->devices); | 140 | wl_list_init(&seat->devices); |
57 | 141 | ||
@@ -81,13 +165,14 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
81 | struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; | 165 | struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; |
82 | sway_keyboard_configure(seat_device->keyboard); | 166 | sway_keyboard_configure(seat_device->keyboard); |
83 | wlr_seat_set_keyboard(seat->wlr_seat, | 167 | wlr_seat_set_keyboard(seat->wlr_seat, |
84 | seat_device->input_device->wlr_device); | 168 | seat_device->input_device->wlr_device); |
85 | if (seat->focus && seat->focus->type == C_VIEW) { | 169 | swayc_t *focus = sway_seat_get_focus(seat); |
170 | if (focus && focus->type == C_VIEW) { | ||
86 | // force notify reenter to pick up the new configuration | 171 | // force notify reenter to pick up the new configuration |
87 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); | 172 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); |
88 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, | 173 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, |
89 | seat->focus->sway_view->surface, wlr_keyboard->keycodes, | 174 | focus->sway_view->surface, wlr_keyboard->keycodes, |
90 | wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); | 175 | wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); |
91 | } | 176 | } |
92 | } | 177 | } |
93 | 178 | ||
@@ -204,47 +289,83 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { | |||
204 | seat->cursor->cursor->y); | 289 | seat->cursor->cursor->y); |
205 | } | 290 | } |
206 | 291 | ||
207 | static void handle_focus_destroy(struct wl_listener *listener, void *data) { | ||
208 | struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); | ||
209 | swayc_t *container = data; | ||
210 | sway_seat_set_focus(seat, container->parent); | ||
211 | } | ||
212 | |||
213 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { | 292 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { |
214 | swayc_t *last_focus = seat->focus; | 293 | swayc_t *last_focus = sway_seat_get_focus(seat); |
215 | 294 | ||
216 | if (last_focus == container) { | 295 | if (container && last_focus == container) { |
217 | return; | 296 | return; |
218 | } | 297 | } |
219 | 298 | ||
220 | if (last_focus && last_focus->type == C_VIEW) { | 299 | if (container) { |
221 | wl_list_remove(&seat->focus_destroy.link); | 300 | struct sway_seat_container *seat_con = |
222 | } | 301 | seat_container_from_container(seat, container); |
302 | if (!seat_con) { | ||
303 | return; | ||
304 | } | ||
223 | 305 | ||
224 | if (container && container->type == C_VIEW) { | 306 | wl_list_remove(&seat_con->link); |
225 | struct sway_view *view = container->sway_view; | 307 | wl_list_insert(&seat->focus_stack, &seat_con->link); |
226 | view_set_activated(view, true); | 308 | |
227 | wl_signal_add(&container->events.destroy, &seat->focus_destroy); | 309 | if (container->type == C_VIEW) { |
228 | seat->focus_destroy.notify = handle_focus_destroy; | 310 | struct sway_view *view = container->sway_view; |
229 | 311 | view_set_activated(view, true); | |
230 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); | 312 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); |
231 | if (keyboard) { | 313 | if (keyboard) { |
232 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, | 314 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, |
233 | keyboard->keycodes, keyboard->num_keycodes, | 315 | keyboard->keycodes, keyboard->num_keycodes, |
234 | &keyboard->modifiers); | 316 | &keyboard->modifiers); |
235 | } else { | 317 | } else { |
236 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, | 318 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, |
237 | NULL, 0, NULL); | 319 | NULL, 0, NULL); |
320 | } | ||
238 | } | 321 | } |
239 | } | 322 | } |
240 | 323 | ||
241 | seat->focus = container; | ||
242 | |||
243 | if (last_focus && last_focus->type == C_VIEW && | 324 | if (last_focus && last_focus->type == C_VIEW && |
244 | !sway_input_manager_has_focus(seat->input, last_focus)) { | 325 | !sway_input_manager_has_focus(seat->input, last_focus)) { |
245 | struct sway_view *view = last_focus->sway_view; | 326 | struct sway_view *view = last_focus->sway_view; |
246 | view_set_activated(view, false); | 327 | view_set_activated(view, false); |
247 | } | 328 | } |
329 | |||
330 | seat->has_focus = (container != NULL); | ||
331 | } | ||
332 | |||
333 | swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container) { | ||
334 | struct sway_seat_container *current = NULL; | ||
335 | swayc_t *parent = NULL; | ||
336 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
337 | parent = current->container->parent; | ||
338 | |||
339 | if (current->container == container) { | ||
340 | return current->container; | ||
341 | } | ||
342 | |||
343 | while (parent) { | ||
344 | if (parent == container) { | ||
345 | return current->container; | ||
346 | } | ||
347 | parent = parent->parent; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | return NULL; | ||
352 | } | ||
353 | |||
354 | swayc_t *sway_seat_get_focus(struct sway_seat *seat) { | ||
355 | if (!seat->has_focus) { | ||
356 | return NULL; | ||
357 | } | ||
358 | return sway_seat_get_focus_inactive(seat, &root_container); | ||
359 | } | ||
360 | |||
361 | swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, | ||
362 | enum swayc_types type) { | ||
363 | swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); | ||
364 | if (focus->type == type) { | ||
365 | return focus; | ||
366 | } | ||
367 | |||
368 | return swayc_parent_by_type(focus, type); | ||
248 | } | 369 | } |
249 | 370 | ||
250 | void sway_seat_set_config(struct sway_seat *seat, | 371 | void sway_seat_set_config(struct sway_seat *seat, |
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index bab9a201..f0afdc9f 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -74,8 +74,8 @@ static void ipc_json_describe_output(swayc_t *container, json_object *object) { | |||
74 | json_object_object_add(object, "refresh", json_object_new_int(wlr_output->refresh)); | 74 | json_object_object_add(object, "refresh", json_object_new_int(wlr_output->refresh)); |
75 | json_object_object_add(object, "transform", | 75 | json_object_object_add(object, "transform", |
76 | json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); | 76 | json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); |
77 | json_object_object_add(object, "current_workspace", | 77 | // TODO WLR need to set "current_workspace" to the currently focused |
78 | (container->focused) ? json_object_new_string(container->focused->name) : NULL); | 78 | // workspace in a way that makes sense with multiseat |
79 | } | 79 | } |
80 | 80 | ||
81 | static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { | 81 | static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 1a468c19..a6268133 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -151,19 +151,19 @@ swayc_t *new_output(struct sway_output *sway_output) { | |||
151 | char *ws_name = workspace_next_name(output->name); | 151 | char *ws_name = workspace_next_name(output->name); |
152 | wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); | 152 | wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); |
153 | swayc_t *ws = new_workspace(output, ws_name); | 153 | swayc_t *ws = new_workspace(output, ws_name); |
154 | output->focused = ws; | ||
155 | // Set each seat's focus if not already set | 154 | // Set each seat's focus if not already set |
156 | // TODO FOCUS: this is probably stupid, we shouldn't define focus in two | 155 | // TODO FOCUS: this is probably stupid, we shouldn't define focus in two |
157 | // places. We should probably put the active workspace on the sway_output | 156 | // places. We should probably put the active workspace on the sway_output |
158 | // struct instead of trying to do focus semantics like this | 157 | // struct instead of trying to do focus semantics like this |
159 | struct sway_seat *seat = NULL; | 158 | struct sway_seat *seat = NULL; |
160 | wl_list_for_each(seat, &input_manager->seats, link) { | 159 | wl_list_for_each(seat, &input_manager->seats, link) { |
161 | if (!seat->focus) { | 160 | if (!seat->has_focus) { |
162 | seat->focus = ws; | 161 | sway_seat_set_focus(seat, ws); |
163 | } | 162 | } |
164 | } | 163 | } |
165 | 164 | ||
166 | free(ws_name); | 165 | free(ws_name); |
166 | wl_signal_emit(&root_container.sway_root->events.new_container, output); | ||
167 | return output; | 167 | return output; |
168 | } | 168 | } |
169 | 169 | ||
@@ -185,6 +185,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { | |||
185 | 185 | ||
186 | add_child(output, workspace); | 186 | add_child(output, workspace); |
187 | sort_workspaces(output); | 187 | sort_workspaces(output); |
188 | wl_signal_emit(&root_container.sway_root->events.new_container, workspace); | ||
188 | return workspace; | 189 | return workspace; |
189 | } | 190 | } |
190 | 191 | ||
@@ -207,9 +208,9 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { | |||
207 | add_child(sibling, swayc); | 208 | add_child(sibling, swayc); |
208 | } else { | 209 | } else { |
209 | // Regular case, create as sibling of current container | 210 | // Regular case, create as sibling of current container |
210 | // TODO WLR | 211 | add_sibling(sibling, swayc); |
211 | //add_sibling(sibling, swayc); | ||
212 | } | 212 | } |
213 | wl_signal_emit(&root_container.sway_root->events.new_container, swayc); | ||
213 | return swayc; | 214 | return swayc; |
214 | } | 215 | } |
215 | 216 | ||
@@ -380,3 +381,25 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi | |||
380 | f(container, data); | 381 | f(container, data); |
381 | } | 382 | } |
382 | } | 383 | } |
384 | |||
385 | void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), | ||
386 | void *data) { | ||
387 | list_t *queue = create_list(); | ||
388 | if (queue == NULL) { | ||
389 | wlr_log(L_ERROR, "could not allocate list"); | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | list_add(queue, con); | ||
394 | |||
395 | swayc_t *current = NULL; | ||
396 | while (queue->length) { | ||
397 | current = queue->items[0]; | ||
398 | list_del(queue, 0); | ||
399 | f(current, data); | ||
400 | // TODO floating containers | ||
401 | list_cat(queue, current->children); | ||
402 | } | ||
403 | |||
404 | list_free(queue); | ||
405 | } | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 41ff81b2..205f42eb 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "sway/layout.h" | 10 | #include "sway/layout.h" |
11 | #include "sway/output.h" | 11 | #include "sway/output.h" |
12 | #include "sway/view.h" | 12 | #include "sway/view.h" |
13 | #include "sway/input/seat.h" | ||
13 | #include "list.h" | 14 | #include "list.h" |
14 | #include "log.h" | 15 | #include "log.h" |
15 | 16 | ||
@@ -48,10 +49,12 @@ void init_layout(void) { | |||
48 | root_container.layout = L_NONE; | 49 | root_container.layout = L_NONE; |
49 | root_container.name = strdup("root"); | 50 | root_container.name = strdup("root"); |
50 | root_container.children = create_list(); | 51 | root_container.children = create_list(); |
52 | wl_signal_init(&root_container.events.destroy); | ||
51 | 53 | ||
52 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | 54 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); |
53 | root_container.sway_root->output_layout = wlr_output_layout_create(); | 55 | root_container.sway_root->output_layout = wlr_output_layout_create(); |
54 | wl_list_init(&root_container.sway_root->unmanaged_views); | 56 | wl_list_init(&root_container.sway_root->unmanaged_views); |
57 | wl_signal_init(&root_container.sway_root->events.new_container); | ||
55 | 58 | ||
56 | root_container.sway_root->output_layout_change.notify = | 59 | root_container.sway_root->output_layout_change.notify = |
57 | output_layout_change_notify; | 60 | output_layout_change_notify; |
@@ -59,6 +62,32 @@ void init_layout(void) { | |||
59 | &root_container.sway_root->output_layout_change); | 62 | &root_container.sway_root->output_layout_change); |
60 | } | 63 | } |
61 | 64 | ||
65 | static int index_child(const swayc_t *child) { | ||
66 | // TODO handle floating | ||
67 | swayc_t *parent = child->parent; | ||
68 | int i, len; | ||
69 | len = parent->children->length; | ||
70 | for (i = 0; i < len; ++i) { | ||
71 | if (parent->children->items[i] == child) { | ||
72 | break; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | if (!sway_assert(i < len, "Stray container")) { | ||
77 | return -1; | ||
78 | } | ||
79 | return i; | ||
80 | } | ||
81 | |||
82 | swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { | ||
83 | // TODO handle floating | ||
84 | swayc_t *parent = fixed->parent; | ||
85 | int i = index_child(fixed); | ||
86 | list_insert(parent->children, i + 1, active); | ||
87 | active->parent = parent; | ||
88 | return active->parent; | ||
89 | } | ||
90 | |||
62 | void add_child(swayc_t *parent, swayc_t *child) { | 91 | void add_child(swayc_t *parent, swayc_t *child) { |
63 | wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", | 92 | wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", |
64 | child, child->type, child->width, child->height, | 93 | child, child->type, child->width, child->height, |
@@ -66,9 +95,6 @@ void add_child(swayc_t *parent, swayc_t *child) { | |||
66 | list_add(parent->children, child); | 95 | list_add(parent->children, child); |
67 | child->parent = parent; | 96 | child->parent = parent; |
68 | // set focus for this container | 97 | // set focus for this container |
69 | if (!parent->focused) { | ||
70 | parent->focused = child; | ||
71 | } | ||
72 | /* TODO WLR | 98 | /* TODO WLR |
73 | if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { | 99 | if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { |
74 | child = new_container(child, parent->workspace_layout); | 100 | child = new_container(child, parent->workspace_layout); |
@@ -321,3 +347,179 @@ void apply_vert_layout(swayc_t *container, | |||
321 | */ | 347 | */ |
322 | } | 348 | } |
323 | } | 349 | } |
350 | |||
351 | /** | ||
352 | * Get swayc in the direction of newly entered output. | ||
353 | */ | ||
354 | static swayc_t *get_swayc_in_output_direction(swayc_t *output, | ||
355 | enum movement_direction dir, struct sway_seat *seat) { | ||
356 | // XXX is this really a seat function or can we do it with the default | ||
357 | // seat? | ||
358 | if (!output) { | ||
359 | return NULL; | ||
360 | } | ||
361 | |||
362 | swayc_t *ws = sway_seat_get_focus_inactive(seat, output); | ||
363 | if (ws->type != C_WORKSPACE) { | ||
364 | ws = swayc_parent_by_type(ws, C_WORKSPACE); | ||
365 | } | ||
366 | |||
367 | if (ws && ws->children->length > 0) { | ||
368 | switch (dir) { | ||
369 | case MOVE_LEFT: | ||
370 | // get most right child of new output | ||
371 | return ws->children->items[ws->children->length-1]; | ||
372 | case MOVE_RIGHT: | ||
373 | // get most left child of new output | ||
374 | return ws->children->items[0]; | ||
375 | case MOVE_UP: | ||
376 | case MOVE_DOWN: | ||
377 | { | ||
378 | swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); | ||
379 | if (focused && focused->parent) { | ||
380 | swayc_t *parent = focused->parent; | ||
381 | if (parent->layout == L_VERT) { | ||
382 | if (dir == MOVE_UP) { | ||
383 | // get child furthest down on new output | ||
384 | return parent->children->items[parent->children->length-1]; | ||
385 | } else if (dir == MOVE_DOWN) { | ||
386 | // get child furthest up on new output | ||
387 | return parent->children->items[0]; | ||
388 | } | ||
389 | } | ||
390 | return focused; | ||
391 | } | ||
392 | break; | ||
393 | } | ||
394 | default: | ||
395 | break; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | return output; | ||
400 | } | ||
401 | |||
402 | static void get_absolute_center_position(swayc_t *container, int *x, int *y) { | ||
403 | *x = container->x + container->width/2; | ||
404 | *y = container->y + container->height/2; | ||
405 | } | ||
406 | |||
407 | static swayc_t *get_swayc_in_direction_under(swayc_t *container, | ||
408 | enum movement_direction dir, struct sway_seat *seat, swayc_t *limit) { | ||
409 | if (dir == MOVE_CHILD) { | ||
410 | return sway_seat_get_focus_inactive(seat, container); | ||
411 | } | ||
412 | |||
413 | swayc_t *parent = container->parent; | ||
414 | if (dir == MOVE_PARENT) { | ||
415 | if (parent->type == C_OUTPUT) { | ||
416 | return NULL; | ||
417 | } else { | ||
418 | return parent; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | if (dir == MOVE_PREV || dir == MOVE_NEXT) { | ||
423 | int focused_idx = index_child(container); | ||
424 | if (focused_idx == -1) { | ||
425 | return NULL; | ||
426 | } else { | ||
427 | int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) % | ||
428 | parent->children->length; | ||
429 | if (desired < 0) { | ||
430 | desired += parent->children->length; | ||
431 | } | ||
432 | return parent->children->items[desired]; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | // If moving to an adjacent output we need a starting position (since this | ||
437 | // output might border to multiple outputs). | ||
438 | //struct wlc_point abs_pos; | ||
439 | //get_absolute_center_position(container, &abs_pos); | ||
440 | |||
441 | |||
442 | // TODO WLR fullscreen | ||
443 | /* | ||
444 | if (container->type == C_VIEW && swayc_is_fullscreen(container)) { | ||
445 | wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); | ||
446 | container = swayc_parent_by_type(container, C_OUTPUT); | ||
447 | get_absolute_center_position(container, &abs_pos); | ||
448 | swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); | ||
449 | return get_swayc_in_output_direction(output, dir); | ||
450 | } | ||
451 | if (container->type == C_WORKSPACE && container->fullscreen) { | ||
452 | sway_log(L_DEBUG, "Moving to fullscreen view"); | ||
453 | return container->fullscreen; | ||
454 | } | ||
455 | */ | ||
456 | |||
457 | swayc_t *wrap_candidate = NULL; | ||
458 | while (true) { | ||
459 | // Test if we can even make a difference here | ||
460 | bool can_move = false; | ||
461 | int desired; | ||
462 | int idx = index_child(container); | ||
463 | if (parent->type == C_ROOT) { | ||
464 | // TODO | ||
465 | /* | ||
466 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | ||
467 | wlr_output_layout_adjacent_output(layout, container->sway_output->wlr_output); | ||
468 | //swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); | ||
469 | if (!output || output == container) { | ||
470 | return wrap_candidate; | ||
471 | } | ||
472 | wlr_log(L_DEBUG, "Moving between outputs"); | ||
473 | return get_swayc_in_output_direction(output, dir, seat); | ||
474 | */ | ||
475 | } else { | ||
476 | if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { | ||
477 | if (parent->layout == L_HORIZ || parent->layout == L_TABBED) { | ||
478 | can_move = true; | ||
479 | desired = idx + (dir == MOVE_LEFT ? -1 : 1); | ||
480 | } | ||
481 | } else { | ||
482 | if (parent->layout == L_VERT || parent->layout == L_STACKED) { | ||
483 | can_move = true; | ||
484 | desired = idx + (dir == MOVE_UP ? -1 : 1); | ||
485 | } | ||
486 | } | ||
487 | } | ||
488 | |||
489 | if (can_move) { | ||
490 | // TODO handle floating | ||
491 | if (desired < 0 || desired >= parent->children->length) { | ||
492 | can_move = false; | ||
493 | int len = parent->children->length; | ||
494 | if (!wrap_candidate && len > 1) { | ||
495 | if (desired < 0) { | ||
496 | wrap_candidate = parent->children->items[len-1]; | ||
497 | } else { | ||
498 | wrap_candidate = parent->children->items[0]; | ||
499 | } | ||
500 | if (config->force_focus_wrapping) { | ||
501 | return wrap_candidate; | ||
502 | } | ||
503 | } | ||
504 | } else { | ||
505 | wlr_log(L_DEBUG, "%s cont %d-%p dir %i sibling %d: %p", __func__, | ||
506 | idx, container, dir, desired, parent->children->items[desired]); | ||
507 | return parent->children->items[desired]; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | if (!can_move) { | ||
512 | container = parent; | ||
513 | parent = parent->parent; | ||
514 | if (!parent || container == limit) { | ||
515 | // wrapping is the last chance | ||
516 | return wrap_candidate; | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | |||
522 | swayc_t *get_swayc_in_direction(swayc_t *container, struct sway_seat *seat, | ||
523 | enum movement_direction dir) { | ||
524 | return get_swayc_in_direction_under(container, dir, seat, NULL); | ||
525 | } | ||
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 23c630b6..861fda4d 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 | swayc_t *focus = sway_seat_get_focus(seat); |
67 | current_workspace = swayc_parent_by_type(seat->focus, C_WORKSPACE); | 67 | if (focus) { |
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_inactive(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 | } |
@@ -118,9 +120,15 @@ swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { | |||
118 | return NULL; | 120 | return NULL; |
119 | } | 121 | } |
120 | 122 | ||
123 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
124 | swayc_t *focus = sway_seat_get_focus_inactive(seat, output); | ||
125 | swayc_t *workspace = (focus->type == C_WORKSPACE ? | ||
126 | focus : | ||
127 | swayc_parent_by_type(focus, C_WORKSPACE)); | ||
128 | |||
121 | int i; | 129 | int i; |
122 | for (i = 0; i < output->children->length; i++) { | 130 | for (i = 0; i < output->children->length; i++) { |
123 | if (output->children->items[i] == output->focused) { | 131 | if (output->children->items[i] == workspace) { |
124 | return output->children->items[ | 132 | return output->children->items[ |
125 | wrap(i + (next ? 1 : -1), output->children->length)]; | 133 | wrap(i + (next ? 1 : -1), output->children->length)]; |
126 | } | 134 | } |
@@ -193,12 +201,13 @@ bool workspace_switch(swayc_t *workspace) { | |||
193 | return false; | 201 | return false; |
194 | } | 202 | } |
195 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 203 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
196 | if (!seat || !seat->focus) { | 204 | swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); |
205 | if (!seat || !focus) { | ||
197 | return false; | 206 | return false; |
198 | } | 207 | } |
199 | swayc_t *active_ws = seat->focus; | 208 | swayc_t *active_ws = focus; |
200 | if (active_ws->type != C_WORKSPACE) { | 209 | if (active_ws->type != C_WORKSPACE) { |
201 | swayc_parent_by_type(seat->focus, C_WORKSPACE); | 210 | swayc_parent_by_type(focus, C_WORKSPACE); |
202 | } | 211 | } |
203 | 212 | ||
204 | if (config->auto_back_and_forth | 213 | if (config->auto_back_and_forth |
@@ -222,16 +231,12 @@ bool workspace_switch(swayc_t *workspace) { | |||
222 | // TODO: Deal with sticky containers | 231 | // TODO: Deal with sticky containers |
223 | 232 | ||
224 | wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); | 233 | wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); |
225 | // TODO FOCUS: Focus the last view this seat had focused on this workspace | 234 | swayc_t *next = sway_seat_get_focus_inactive(seat, workspace); |
226 | if (workspace->children->length) { | 235 | if (next == NULL) { |
227 | // TODO FOCUS: This is really fucking stupid | 236 | next = workspace; |
228 | sway_seat_set_focus(seat, workspace->children->items[0]); | ||
229 | } else { | ||
230 | sway_seat_set_focus(seat, workspace); | ||
231 | } | 237 | } |
238 | sway_seat_set_focus(seat, next); | ||
232 | swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); | 239 | swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); |
233 | // TODO FOCUS: take a look at this | ||
234 | output->focused = workspace; | ||
235 | arrange_windows(output, -1, -1); | 240 | arrange_windows(output, -1, -1); |
236 | return true; | 241 | return true; |
237 | } | 242 | } |