aboutsummaryrefslogtreecommitdiffstats
path: root/swaynag
diff options
context:
space:
mode:
authorLibravatar Andri Yngvason <andri@yngvason.is>2020-01-03 14:37:30 +0000
committerLibravatar Simon Ser <contact@emersion.fr>2020-01-05 19:57:05 +0100
commit4c29a53386d77251fa108294a1353e9567301d4f (patch)
tree986c6de0e26b9b63ec0d8e2ca009d5e495f7e609 /swaynag
parentFix small typo in sway-input(5) (diff)
downloadsway-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')
-rw-r--r--swaynag/swaynag.c123
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
127static void update_cursor(struct swaynag *swaynag) { 127static 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
162void 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
161static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, 171static 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
170static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, 180static 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
177static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, 187static 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
226static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, 237static 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
261static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, 273static 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
387void 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
363static void handle_global_remove(void *data, struct wl_registry *registry, 399static 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
371static const struct wl_registry_listener registry_listener = { 414static 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
419void 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
376void swaynag_setup(struct swaynag *swaynag) { 431void 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, &registry_listener, swaynag); 444 wl_registry_add_listener(registry, &registry_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]) {