diff options
author | Andri Yngvason <andri@yngvason.is> | 2020-01-03 14:37:30 +0000 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2020-01-05 19:57:05 +0100 |
commit | 4c29a53386d77251fa108294a1353e9567301d4f (patch) | |
tree | 986c6de0e26b9b63ec0d8e2ca009d5e495f7e609 /swaynag/swaynag.c | |
parent | Fix small typo in sway-input(5) (diff) | |
download | sway-4c29a53386d77251fa108294a1353e9567301d4f.tar.gz sway-4c29a53386d77251fa108294a1353e9567301d4f.tar.zst sway-4c29a53386d77251fa108294a1353e9567301d4f.zip |
swaynag: Add multi-seat support
This also adds cleanup for all seat resources
Diffstat (limited to 'swaynag/swaynag.c')
-rw-r--r-- | swaynag/swaynag.c | 123 |
1 files changed, 89 insertions, 34 deletions
diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index caa10ccd..e6fe9b21 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c | |||
@@ -124,10 +124,11 @@ static struct wl_surface_listener surface_listener = { | |||
124 | .leave = nop, | 124 | .leave = nop, |
125 | }; | 125 | }; |
126 | 126 | ||
127 | static void update_cursor(struct swaynag *swaynag) { | 127 | static void update_cursor(struct swaynag_seat *seat) { |
128 | struct swaynag_pointer *pointer = &swaynag->pointer; | 128 | struct swaynag_pointer *pointer = &seat->pointer; |
129 | if (swaynag->pointer.cursor_theme) { | 129 | struct swaynag *swaynag = seat->swaynag; |
130 | wl_cursor_theme_destroy(swaynag->pointer.cursor_theme); | 130 | if (pointer->cursor_theme) { |
131 | wl_cursor_theme_destroy(pointer->cursor_theme); | ||
131 | } | 132 | } |
132 | const char *cursor_theme = getenv("XCURSOR_THEME"); | 133 | const char *cursor_theme = getenv("XCURSOR_THEME"); |
133 | unsigned cursor_size = 24; | 134 | unsigned cursor_size = 24; |
@@ -158,32 +159,42 @@ static void update_cursor(struct swaynag *swaynag) { | |||
158 | wl_surface_commit(pointer->cursor_surface); | 159 | wl_surface_commit(pointer->cursor_surface); |
159 | } | 160 | } |
160 | 161 | ||
162 | void update_all_cursors(struct swaynag *swaynag) { | ||
163 | struct swaynag_seat *seat; | ||
164 | wl_list_for_each(seat, &swaynag->seats, link) { | ||
165 | if (seat->pointer.pointer) { | ||
166 | update_cursor(seat); | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
161 | static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, | 171 | static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, |
162 | uint32_t serial, struct wl_surface *surface, | 172 | uint32_t serial, struct wl_surface *surface, |
163 | wl_fixed_t surface_x, wl_fixed_t surface_y) { | 173 | wl_fixed_t surface_x, wl_fixed_t surface_y) { |
164 | struct swaynag *swaynag = data; | 174 | struct swaynag_seat *seat = data; |
165 | struct swaynag_pointer *pointer = &swaynag->pointer; | 175 | struct swaynag_pointer *pointer = &seat->pointer; |
166 | pointer->serial = serial; | 176 | pointer->serial = serial; |
167 | update_cursor(swaynag); | 177 | update_cursor(seat); |
168 | } | 178 | } |
169 | 179 | ||
170 | static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | 180 | static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, |
171 | uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { | 181 | uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { |
172 | struct swaynag *swaynag = data; | 182 | struct swaynag_seat *seat = data; |
173 | swaynag->pointer.x = wl_fixed_to_int(surface_x); | 183 | seat->pointer.x = wl_fixed_to_int(surface_x); |
174 | swaynag->pointer.y = wl_fixed_to_int(surface_y); | 184 | seat->pointer.y = wl_fixed_to_int(surface_y); |
175 | } | 185 | } |
176 | 186 | ||
177 | static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | 187 | static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, |
178 | uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { | 188 | uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { |
179 | struct swaynag *swaynag = data; | 189 | struct swaynag_seat *seat = data; |
190 | struct swaynag *swaynag = seat->swaynag; | ||
180 | 191 | ||
181 | if (state != WL_POINTER_BUTTON_STATE_PRESSED) { | 192 | if (state != WL_POINTER_BUTTON_STATE_PRESSED) { |
182 | return; | 193 | return; |
183 | } | 194 | } |
184 | 195 | ||
185 | double x = swaynag->pointer.x * swaynag->scale; | 196 | double x = seat->pointer.x * swaynag->scale; |
186 | double y = swaynag->pointer.y * swaynag->scale; | 197 | double y = seat->pointer.y * swaynag->scale; |
187 | for (int i = 0; i < swaynag->buttons->length; i++) { | 198 | for (int i = 0; i < swaynag->buttons->length; i++) { |
188 | struct swaynag_button *nagbutton = swaynag->buttons->items[i]; | 199 | struct swaynag_button *nagbutton = swaynag->buttons->items[i]; |
189 | if (x >= nagbutton->x | 200 | if (x >= nagbutton->x |
@@ -225,12 +236,13 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | |||
225 | 236 | ||
226 | static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | 237 | static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, |
227 | uint32_t time, uint32_t axis, wl_fixed_t value) { | 238 | uint32_t time, uint32_t axis, wl_fixed_t value) { |
228 | struct swaynag *swaynag = data; | 239 | struct swaynag_seat *seat = data; |
240 | struct swaynag *swaynag = seat->swaynag; | ||
229 | if (!swaynag->details.visible | 241 | if (!swaynag->details.visible |
230 | || swaynag->pointer.x < swaynag->details.x | 242 | || seat->pointer.x < swaynag->details.x |
231 | || swaynag->pointer.y < swaynag->details.y | 243 | || seat->pointer.y < swaynag->details.y |
232 | || swaynag->pointer.x >= swaynag->details.x + swaynag->details.width | 244 | || seat->pointer.x >= swaynag->details.x + swaynag->details.width |
233 | || swaynag->pointer.y >= swaynag->details.y + swaynag->details.height | 245 | || seat->pointer.y >= swaynag->details.y + swaynag->details.height |
234 | || swaynag->details.total_lines == swaynag->details.visible_lines) { | 246 | || swaynag->details.total_lines == swaynag->details.visible_lines) { |
235 | return; | 247 | return; |
236 | } | 248 | } |
@@ -260,15 +272,15 @@ static struct wl_pointer_listener pointer_listener = { | |||
260 | 272 | ||
261 | static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, | 273 | static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, |
262 | enum wl_seat_capability caps) { | 274 | enum wl_seat_capability caps) { |
263 | struct swaynag *swaynag = data; | 275 | struct swaynag_seat *seat = data; |
264 | bool cap_pointer = caps & WL_SEAT_CAPABILITY_POINTER; | 276 | bool cap_pointer = caps & WL_SEAT_CAPABILITY_POINTER; |
265 | if (cap_pointer && !swaynag->pointer.pointer) { | 277 | if (cap_pointer && !seat->pointer.pointer) { |
266 | swaynag->pointer.pointer = wl_seat_get_pointer(wl_seat); | 278 | seat->pointer.pointer = wl_seat_get_pointer(wl_seat); |
267 | wl_pointer_add_listener(swaynag->pointer.pointer, &pointer_listener, | 279 | wl_pointer_add_listener(seat->pointer.pointer, |
268 | swaynag); | 280 | &pointer_listener, seat); |
269 | } else if (!cap_pointer && swaynag->pointer.pointer) { | 281 | } else if (!cap_pointer && seat->pointer.pointer) { |
270 | wl_pointer_destroy(swaynag->pointer.pointer); | 282 | wl_pointer_destroy(seat->pointer.pointer); |
271 | swaynag->pointer.pointer = NULL; | 283 | seat->pointer.pointer = NULL; |
272 | } | 284 | } |
273 | } | 285 | } |
274 | 286 | ||
@@ -283,7 +295,7 @@ static void output_scale(void *data, struct wl_output *output, | |||
283 | swaynag_output->scale = factor; | 295 | swaynag_output->scale = factor; |
284 | if (swaynag_output->swaynag->output == swaynag_output) { | 296 | if (swaynag_output->swaynag->output == swaynag_output) { |
285 | swaynag_output->swaynag->scale = swaynag_output->scale; | 297 | swaynag_output->swaynag->scale = swaynag_output->scale; |
286 | update_cursor(swaynag_output->swaynag); | 298 | update_all_cursors(swaynag_output->swaynag); |
287 | render_frame(swaynag_output->swaynag); | 299 | render_frame(swaynag_output->swaynag); |
288 | } | 300 | } |
289 | } | 301 | } |
@@ -325,8 +337,20 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
325 | swaynag->compositor = wl_registry_bind(registry, name, | 337 | swaynag->compositor = wl_registry_bind(registry, name, |
326 | &wl_compositor_interface, 4); | 338 | &wl_compositor_interface, 4); |
327 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { | 339 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { |
328 | swaynag->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); | 340 | struct swaynag_seat *seat = |
329 | wl_seat_add_listener(swaynag->seat, &seat_listener, swaynag); | 341 | calloc(1, sizeof(struct swaynag_seat)); |
342 | if (!seat) { | ||
343 | return; | ||
344 | } | ||
345 | |||
346 | seat->swaynag = swaynag; | ||
347 | seat->wl_name = name; | ||
348 | seat->wl_seat = | ||
349 | wl_registry_bind(registry, name, &wl_seat_interface, 1); | ||
350 | |||
351 | wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); | ||
352 | |||
353 | wl_list_insert(&swaynag->seats, &seat->link); | ||
330 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | 354 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { |
331 | swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); | 355 | swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); |
332 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | 356 | } else if (strcmp(interface, wl_output_interface.name) == 0) { |
@@ -360,12 +384,31 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
360 | } | 384 | } |
361 | } | 385 | } |
362 | 386 | ||
387 | void swaynag_seat_destroy(struct swaynag_seat *seat) { | ||
388 | if (seat->pointer.cursor_theme) { | ||
389 | wl_cursor_theme_destroy(seat->pointer.cursor_theme); | ||
390 | } | ||
391 | if (seat->pointer.pointer) { | ||
392 | wl_pointer_destroy(seat->pointer.pointer); | ||
393 | } | ||
394 | wl_seat_destroy(seat->wl_seat); | ||
395 | wl_list_remove(&seat->link); | ||
396 | free(seat); | ||
397 | } | ||
398 | |||
363 | static void handle_global_remove(void *data, struct wl_registry *registry, | 399 | static void handle_global_remove(void *data, struct wl_registry *registry, |
364 | uint32_t name) { | 400 | uint32_t name) { |
365 | struct swaynag *swaynag = data; | 401 | struct swaynag *swaynag = data; |
366 | if (swaynag->output->wl_name == name) { | 402 | if (swaynag->output->wl_name == name) { |
367 | swaynag->run_display = false; | 403 | swaynag->run_display = false; |
368 | } | 404 | } |
405 | |||
406 | struct swaynag_seat *seat, *tmpseat; | ||
407 | wl_list_for_each_safe(seat, tmpseat, &swaynag->seats, link) { | ||
408 | if (seat->wl_name == name) { | ||
409 | swaynag_seat_destroy(seat); | ||
410 | } | ||
411 | } | ||
369 | } | 412 | } |
370 | 413 | ||
371 | static const struct wl_registry_listener registry_listener = { | 414 | static const struct wl_registry_listener registry_listener = { |
@@ -373,6 +416,18 @@ static const struct wl_registry_listener registry_listener = { | |||
373 | .global_remove = handle_global_remove, | 416 | .global_remove = handle_global_remove, |
374 | }; | 417 | }; |
375 | 418 | ||
419 | void swaynag_setup_cursors(struct swaynag *swaynag) { | ||
420 | struct swaynag_seat *seat; | ||
421 | |||
422 | wl_list_for_each(seat, &swaynag->seats, link) { | ||
423 | struct swaynag_pointer *p = &seat->pointer; | ||
424 | |||
425 | p->cursor_surface = | ||
426 | wl_compositor_create_surface(swaynag->compositor); | ||
427 | assert(p->cursor_surface); | ||
428 | } | ||
429 | } | ||
430 | |||
376 | void swaynag_setup(struct swaynag *swaynag) { | 431 | void swaynag_setup(struct swaynag *swaynag) { |
377 | swaynag->display = wl_display_connect(NULL); | 432 | swaynag->display = wl_display_connect(NULL); |
378 | if (!swaynag->display) { | 433 | if (!swaynag->display) { |
@@ -383,6 +438,7 @@ void swaynag_setup(struct swaynag *swaynag) { | |||
383 | 438 | ||
384 | swaynag->scale = 1; | 439 | swaynag->scale = 1; |
385 | wl_list_init(&swaynag->outputs); | 440 | wl_list_init(&swaynag->outputs); |
441 | wl_list_init(&swaynag->seats); | ||
386 | 442 | ||
387 | struct wl_registry *registry = wl_display_get_registry(swaynag->display); | 443 | struct wl_registry *registry = wl_display_get_registry(swaynag->display); |
388 | wl_registry_add_listener(registry, ®istry_listener, swaynag); | 444 | wl_registry_add_listener(registry, ®istry_listener, swaynag); |
@@ -399,9 +455,7 @@ void swaynag_setup(struct swaynag *swaynag) { | |||
399 | exit(EXIT_FAILURE); | 455 | exit(EXIT_FAILURE); |
400 | } | 456 | } |
401 | 457 | ||
402 | struct swaynag_pointer *pointer = &swaynag->pointer; | 458 | swaynag_setup_cursors(swaynag); |
403 | pointer->cursor_surface = wl_compositor_create_surface(swaynag->compositor); | ||
404 | assert(pointer->cursor_surface); | ||
405 | 459 | ||
406 | swaynag->surface = wl_compositor_create_surface(swaynag->compositor); | 460 | swaynag->surface = wl_compositor_create_surface(swaynag->compositor); |
407 | assert(swaynag->surface); | 461 | assert(swaynag->surface); |
@@ -460,8 +514,9 @@ void swaynag_destroy(struct swaynag *swaynag) { | |||
460 | wl_surface_destroy(swaynag->surface); | 514 | wl_surface_destroy(swaynag->surface); |
461 | } | 515 | } |
462 | 516 | ||
463 | if (swaynag->pointer.cursor_theme) { | 517 | struct swaynag_seat *seat, *tmpseat; |
464 | wl_cursor_theme_destroy(swaynag->pointer.cursor_theme); | 518 | wl_list_for_each_safe(seat, tmpseat, &swaynag->seats, link) { |
519 | swaynag_seat_destroy(seat); | ||
465 | } | 520 | } |
466 | 521 | ||
467 | if (&swaynag->buffers[0]) { | 522 | if (&swaynag->buffers[0]) { |