aboutsummaryrefslogtreecommitdiffstats
path: root/swaynag/swaynag.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaynag/swaynag.c')
-rw-r--r--swaynag/swaynag.c133
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
187static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, 209static 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
310static const struct wl_output_listener output_listener = { 332static 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
317static 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
332static const struct zxdg_output_v1_listener xdg_output_listener = { 345static 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
503void swaynag_destroy(struct swaynag *swaynag) { 510void 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}