aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-02-04 13:39:10 -0500
committerLibravatar Tony Crisci <tony@dubstepdish.com>2018-02-04 14:08:54 -0500
commit515150229847c9ebdfd0cabb6f0026fca9d57a23 (patch)
tree8a50ce0ac8ce4dc2ec973c63c68dc45378c50737 /sway
parentImplement workspaces (diff)
downloadsway-515150229847c9ebdfd0cabb6f0026fca9d57a23.tar.gz
sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.tar.zst
sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.zip
basic focus overhaul
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c5
-rw-r--r--sway/commands/kill.c7
-rw-r--r--sway/commands/workspace.c3
-rw-r--r--sway/desktop/xdg_shell_v6.c3
-rw-r--r--sway/input/input-manager.c2
-rw-r--r--sway/input/seat.c137
-rw-r--r--sway/tree/container.c33
-rw-r--r--sway/tree/layout.c30
-rw-r--r--sway/tree/workspace.c17
9 files changed, 198 insertions, 39 deletions
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
35static 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
44static 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
67static 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
35struct sway_seat *sway_seat_create(struct sway_input_manager *input, 73struct 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
213void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { 272void 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
317swayc_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
250void sway_seat_set_config(struct sway_seat *seat, 341void 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 */
388list_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
64int 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
81swayc_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
62void add_child(swayc_t *parent, swayc_t *child) { 92void 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) {
63swayc_t *workspace_by_name(const char *name) { 63swayc_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