diff options
Diffstat (limited to 'swaynag/swaynag.c')
-rw-r--r-- | swaynag/swaynag.c | 133 |
1 files changed, 70 insertions, 63 deletions
diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index dd17c0b0..50eea148 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <stdlib.h> | 1 | #include <stdlib.h> |
3 | #include <assert.h> | 2 | #include <assert.h> |
4 | #include <sys/stat.h> | 3 | #include <sys/stat.h> |
@@ -28,8 +27,13 @@ static bool terminal_execute(char *terminal, char *command) { | |||
28 | fprintf(tmp, "#!/bin/sh\nrm %s\n%s", fname, command); | 27 | fprintf(tmp, "#!/bin/sh\nrm %s\n%s", fname, command); |
29 | fclose(tmp); | 28 | fclose(tmp); |
30 | chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR); | 29 | chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR); |
31 | char *cmd = malloc(sizeof(char) * (strlen(terminal) + strlen(" -e ") + strlen(fname) + 1)); | 30 | size_t cmd_size = strlen(terminal) + strlen(" -e ") + strlen(fname) + 1; |
32 | sprintf(cmd, "%s -e %s", terminal, fname); | 31 | char *cmd = malloc(cmd_size); |
32 | if (!cmd) { | ||
33 | perror("malloc"); | ||
34 | return false; | ||
35 | } | ||
36 | snprintf(cmd, cmd_size, "%s -e %s", terminal, fname); | ||
33 | execlp("sh", "sh", "-c", cmd, NULL); | 37 | execlp("sh", "sh", "-c", cmd, NULL); |
34 | sway_log_errno(SWAY_ERROR, "Failed to run command, execlp() returned."); | 38 | sway_log_errno(SWAY_ERROR, "Failed to run command, execlp() returned."); |
35 | free(cmd); | 39 | free(cmd); |
@@ -58,7 +62,7 @@ static void swaynag_button_execute(struct swaynag *swaynag, | |||
58 | } else if (pid == 0) { | 62 | } else if (pid == 0) { |
59 | // Child of the child. Will be reparented to the init process | 63 | // Child of the child. Will be reparented to the init process |
60 | char *terminal = getenv("TERMINAL"); | 64 | char *terminal = getenv("TERMINAL"); |
61 | if (button->terminal && terminal && strlen(terminal)) { | 65 | if (button->terminal && terminal && *terminal) { |
62 | sway_log(SWAY_DEBUG, "Found $TERMINAL: %s", terminal); | 66 | sway_log(SWAY_DEBUG, "Found $TERMINAL: %s", terminal); |
63 | if (!terminal_execute(terminal, button->action)) { | 67 | if (!terminal_execute(terminal, button->action)) { |
64 | swaynag_destroy(swaynag); | 68 | swaynag_destroy(swaynag); |
@@ -138,7 +142,7 @@ static void update_cursor(struct swaynag_seat *seat) { | |||
138 | const char *cursor_theme = getenv("XCURSOR_THEME"); | 142 | const char *cursor_theme = getenv("XCURSOR_THEME"); |
139 | unsigned cursor_size = 24; | 143 | unsigned cursor_size = 24; |
140 | const char *env_cursor_size = getenv("XCURSOR_SIZE"); | 144 | const char *env_cursor_size = getenv("XCURSOR_SIZE"); |
141 | if (env_cursor_size && strlen(env_cursor_size) > 0) { | 145 | if (env_cursor_size && *env_cursor_size) { |
142 | errno = 0; | 146 | errno = 0; |
143 | char *end; | 147 | char *end; |
144 | unsigned size = strtoul(env_cursor_size, &end, 10); | 148 | unsigned size = strtoul(env_cursor_size, &end, 10); |
@@ -148,8 +152,15 @@ static void update_cursor(struct swaynag_seat *seat) { | |||
148 | } | 152 | } |
149 | pointer->cursor_theme = wl_cursor_theme_load( | 153 | pointer->cursor_theme = wl_cursor_theme_load( |
150 | cursor_theme, cursor_size * swaynag->scale, swaynag->shm); | 154 | cursor_theme, cursor_size * swaynag->scale, swaynag->shm); |
151 | struct wl_cursor *cursor = | 155 | if (!pointer->cursor_theme) { |
152 | wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); | 156 | sway_log(SWAY_ERROR, "Failed to load cursor theme"); |
157 | return; | ||
158 | } | ||
159 | struct wl_cursor *cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "default"); | ||
160 | if (!cursor) { | ||
161 | sway_log(SWAY_ERROR, "Failed to get default cursor from theme"); | ||
162 | return; | ||
163 | } | ||
153 | pointer->cursor_image = cursor->images[0]; | 164 | pointer->cursor_image = cursor->images[0]; |
154 | wl_surface_set_buffer_scale(pointer->cursor_surface, | 165 | wl_surface_set_buffer_scale(pointer->cursor_surface, |
155 | swaynag->scale); | 166 | swaynag->scale); |
@@ -177,11 +188,22 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, | |||
177 | uint32_t serial, struct wl_surface *surface, | 188 | uint32_t serial, struct wl_surface *surface, |
178 | wl_fixed_t surface_x, wl_fixed_t surface_y) { | 189 | wl_fixed_t surface_x, wl_fixed_t surface_y) { |
179 | struct swaynag_seat *seat = data; | 190 | struct swaynag_seat *seat = data; |
191 | |||
180 | struct swaynag_pointer *pointer = &seat->pointer; | 192 | struct swaynag_pointer *pointer = &seat->pointer; |
181 | pointer->x = wl_fixed_to_int(surface_x); | 193 | pointer->x = wl_fixed_to_int(surface_x); |
182 | pointer->y = wl_fixed_to_int(surface_y); | 194 | pointer->y = wl_fixed_to_int(surface_y); |
183 | pointer->serial = serial; | 195 | |
184 | update_cursor(seat); | 196 | if (seat->swaynag->cursor_shape_manager) { |
197 | struct wp_cursor_shape_device_v1 *device = | ||
198 | wp_cursor_shape_manager_v1_get_pointer( | ||
199 | seat->swaynag->cursor_shape_manager, wl_pointer); | ||
200 | wp_cursor_shape_device_v1_set_shape(device, serial, | ||
201 | WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT); | ||
202 | wp_cursor_shape_device_v1_destroy(device); | ||
203 | } else { | ||
204 | pointer->serial = serial; | ||
205 | update_cursor(seat); | ||
206 | } | ||
185 | } | 207 | } |
186 | 208 | ||
187 | static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | 209 | static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, |
@@ -200,8 +222,8 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | |||
200 | return; | 222 | return; |
201 | } | 223 | } |
202 | 224 | ||
203 | double x = seat->pointer.x * swaynag->scale; | 225 | double x = seat->pointer.x; |
204 | double y = seat->pointer.y * swaynag->scale; | 226 | double y = seat->pointer.y; |
205 | for (int i = 0; i < swaynag->buttons->length; i++) { | 227 | for (int i = 0; i < swaynag->buttons->length; i++) { |
206 | struct swaynag_button *nagbutton = swaynag->buttons->items[i]; | 228 | struct swaynag_button *nagbutton = swaynag->buttons->items[i]; |
207 | if (x >= nagbutton->x | 229 | if (x >= nagbutton->x |
@@ -307,33 +329,25 @@ static void output_scale(void *data, struct wl_output *output, | |||
307 | } | 329 | } |
308 | } | 330 | } |
309 | 331 | ||
310 | static const struct wl_output_listener output_listener = { | 332 | static void output_name(void *data, struct wl_output *output, |
311 | .geometry = nop, | 333 | const char *name) { |
312 | .mode = nop, | ||
313 | .done = nop, | ||
314 | .scale = output_scale, | ||
315 | }; | ||
316 | |||
317 | static void xdg_output_handle_name(void *data, | ||
318 | struct zxdg_output_v1 *xdg_output, const char *name) { | ||
319 | struct swaynag_output *swaynag_output = data; | 334 | struct swaynag_output *swaynag_output = data; |
320 | char *outname = swaynag_output->swaynag->type->output; | 335 | swaynag_output->name = strdup(name); |
321 | sway_log(SWAY_DEBUG, "Checking against output %s for %s", name, outname); | 336 | |
322 | if (!swaynag_output->swaynag->output && outname && name | 337 | const char *outname = swaynag_output->swaynag->type->output; |
323 | && strcmp(outname, name) == 0) { | 338 | if (!swaynag_output->swaynag->output && outname && |
339 | strcmp(outname, name) == 0) { | ||
324 | sway_log(SWAY_DEBUG, "Using output %s", name); | 340 | sway_log(SWAY_DEBUG, "Using output %s", name); |
325 | swaynag_output->swaynag->output = swaynag_output; | 341 | swaynag_output->swaynag->output = swaynag_output; |
326 | } | 342 | } |
327 | swaynag_output->name = strdup(name); | ||
328 | zxdg_output_v1_destroy(xdg_output); | ||
329 | swaynag_output->swaynag->querying_outputs--; | ||
330 | } | 343 | } |
331 | 344 | ||
332 | static const struct zxdg_output_v1_listener xdg_output_listener = { | 345 | static const struct wl_output_listener output_listener = { |
333 | .logical_position = nop, | 346 | .geometry = nop, |
334 | .logical_size = nop, | 347 | .mode = nop, |
335 | .done = nop, | 348 | .done = nop, |
336 | .name = xdg_output_handle_name, | 349 | .scale = output_scale, |
350 | .name = output_name, | ||
337 | .description = nop, | 351 | .description = nop, |
338 | }; | 352 | }; |
339 | 353 | ||
@@ -347,6 +361,7 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
347 | struct swaynag_seat *seat = | 361 | struct swaynag_seat *seat = |
348 | calloc(1, sizeof(struct swaynag_seat)); | 362 | calloc(1, sizeof(struct swaynag_seat)); |
349 | if (!seat) { | 363 | if (!seat) { |
364 | perror("calloc"); | ||
350 | return; | 365 | return; |
351 | } | 366 | } |
352 | 367 | ||
@@ -361,33 +376,28 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
361 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | 376 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { |
362 | swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); | 377 | swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); |
363 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | 378 | } else if (strcmp(interface, wl_output_interface.name) == 0) { |
364 | if (!swaynag->output && swaynag->xdg_output_manager) { | 379 | if (!swaynag->output) { |
365 | swaynag->querying_outputs++; | ||
366 | struct swaynag_output *output = | 380 | struct swaynag_output *output = |
367 | calloc(1, sizeof(struct swaynag_output)); | 381 | calloc(1, sizeof(struct swaynag_output)); |
382 | if (!output) { | ||
383 | perror("calloc"); | ||
384 | return; | ||
385 | } | ||
368 | output->wl_output = wl_registry_bind(registry, name, | 386 | output->wl_output = wl_registry_bind(registry, name, |
369 | &wl_output_interface, 3); | 387 | &wl_output_interface, 4); |
370 | output->wl_name = name; | 388 | output->wl_name = name; |
371 | output->scale = 1; | 389 | output->scale = 1; |
372 | output->swaynag = swaynag; | 390 | output->swaynag = swaynag; |
373 | wl_list_insert(&swaynag->outputs, &output->link); | 391 | wl_list_insert(&swaynag->outputs, &output->link); |
374 | wl_output_add_listener(output->wl_output, | 392 | wl_output_add_listener(output->wl_output, |
375 | &output_listener, output); | 393 | &output_listener, output); |
376 | |||
377 | struct zxdg_output_v1 *xdg_output; | ||
378 | xdg_output = zxdg_output_manager_v1_get_xdg_output( | ||
379 | swaynag->xdg_output_manager, output->wl_output); | ||
380 | zxdg_output_v1_add_listener(xdg_output, | ||
381 | &xdg_output_listener, output); | ||
382 | } | 394 | } |
383 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { | 395 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { |
384 | swaynag->layer_shell = wl_registry_bind( | 396 | swaynag->layer_shell = wl_registry_bind( |
385 | registry, name, &zwlr_layer_shell_v1_interface, 1); | 397 | registry, name, &zwlr_layer_shell_v1_interface, 1); |
386 | } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 | 398 | } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) { |
387 | && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { | 399 | swaynag->cursor_shape_manager = wl_registry_bind( |
388 | swaynag->xdg_output_manager = wl_registry_bind(registry, name, | 400 | registry, name, &wp_cursor_shape_manager_v1_interface, 1); |
389 | &zxdg_output_manager_v1_interface, | ||
390 | ZXDG_OUTPUT_V1_NAME_SINCE_VERSION); | ||
391 | } | 401 | } |
392 | } | 402 | } |
393 | 403 | ||
@@ -453,12 +463,11 @@ void swaynag_setup(struct swaynag *swaynag) { | |||
453 | 463 | ||
454 | assert(swaynag->compositor && swaynag->layer_shell && swaynag->shm); | 464 | assert(swaynag->compositor && swaynag->layer_shell && swaynag->shm); |
455 | 465 | ||
456 | while (swaynag->querying_outputs > 0) { | 466 | // Second roundtrip to get wl_output properties |
457 | if (wl_display_roundtrip(swaynag->display) < 0) { | 467 | if (wl_display_roundtrip(swaynag->display) < 0) { |
458 | sway_log(SWAY_ERROR, "Error during outputs init."); | 468 | sway_log(SWAY_ERROR, "Error during outputs init."); |
459 | swaynag_destroy(swaynag); | 469 | swaynag_destroy(swaynag); |
460 | exit(EXIT_FAILURE); | 470 | exit(EXIT_FAILURE); |
461 | } | ||
462 | } | 471 | } |
463 | 472 | ||
464 | if (!swaynag->output && swaynag->type->output) { | 473 | if (!swaynag->output && swaynag->type->output) { |
@@ -467,7 +476,9 @@ void swaynag_setup(struct swaynag *swaynag) { | |||
467 | exit(EXIT_FAILURE); | 476 | exit(EXIT_FAILURE); |
468 | } | 477 | } |
469 | 478 | ||
470 | swaynag_setup_cursors(swaynag); | 479 | if (!swaynag->cursor_shape_manager) { |
480 | swaynag_setup_cursors(swaynag); | ||
481 | } | ||
471 | 482 | ||
472 | swaynag->surface = wl_compositor_create_surface(swaynag->compositor); | 483 | swaynag->surface = wl_compositor_create_surface(swaynag->compositor); |
473 | assert(swaynag->surface); | 484 | assert(swaynag->surface); |
@@ -494,10 +505,6 @@ void swaynag_run(struct swaynag *swaynag) { | |||
494 | && wl_display_dispatch(swaynag->display) != -1) { | 505 | && wl_display_dispatch(swaynag->display) != -1) { |
495 | // This is intentionally left blank | 506 | // This is intentionally left blank |
496 | } | 507 | } |
497 | |||
498 | if (swaynag->display) { | ||
499 | wl_display_disconnect(swaynag->display); | ||
500 | } | ||
501 | } | 508 | } |
502 | 509 | ||
503 | void swaynag_destroy(struct swaynag *swaynag) { | 510 | void swaynag_destroy(struct swaynag *swaynag) { |
@@ -512,6 +519,7 @@ void swaynag_destroy(struct swaynag *swaynag) { | |||
512 | } | 519 | } |
513 | list_free(swaynag->buttons); | 520 | list_free(swaynag->buttons); |
514 | free(swaynag->details.message); | 521 | free(swaynag->details.message); |
522 | free(swaynag->details.details_text); | ||
515 | free(swaynag->details.button_up.text); | 523 | free(swaynag->details.button_up.text); |
516 | free(swaynag->details.button_down.text); | 524 | free(swaynag->details.button_down.text); |
517 | 525 | ||
@@ -532,13 +540,8 @@ void swaynag_destroy(struct swaynag *swaynag) { | |||
532 | swaynag_seat_destroy(seat); | 540 | swaynag_seat_destroy(seat); |
533 | } | 541 | } |
534 | 542 | ||
535 | if (&swaynag->buffers[0]) { | 543 | destroy_buffer(&swaynag->buffers[0]); |
536 | destroy_buffer(&swaynag->buffers[0]); | 544 | destroy_buffer(&swaynag->buffers[1]); |
537 | } | ||
538 | |||
539 | if (&swaynag->buffers[1]) { | ||
540 | destroy_buffer(&swaynag->buffers[1]); | ||
541 | } | ||
542 | 545 | ||
543 | if (swaynag->outputs.prev || swaynag->outputs.next) { | 546 | if (swaynag->outputs.prev || swaynag->outputs.next) { |
544 | struct swaynag_output *output, *temp; | 547 | struct swaynag_output *output, *temp; |
@@ -557,4 +560,8 @@ void swaynag_destroy(struct swaynag *swaynag) { | |||
557 | if (swaynag->shm) { | 560 | if (swaynag->shm) { |
558 | wl_shm_destroy(swaynag->shm); | 561 | wl_shm_destroy(swaynag->shm); |
559 | } | 562 | } |
563 | |||
564 | if (swaynag->display) { | ||
565 | wl_display_disconnect(swaynag->display); | ||
566 | } | ||
560 | } | 567 | } |