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 /sway/input/seat.c | |
parent | Implement workspaces (diff) | |
download | sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.tar.gz sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.tar.zst sway-515150229847c9ebdfd0cabb6f0026fca9d57a23.zip |
basic focus overhaul
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 137 |
1 files changed, 114 insertions, 23 deletions
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 |