aboutsummaryrefslogtreecommitdiffstats
path: root/swaynag/swaynag.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaynag/swaynag.c')
-rw-r--r--swaynag/swaynag.c153
1 files changed, 82 insertions, 71 deletions
diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c
index d9bec368..6ea739e3 100644
--- a/swaynag/swaynag.c
+++ b/swaynag/swaynag.c
@@ -28,10 +28,15 @@ static bool terminal_execute(char *terminal, char *command) {
28 fprintf(tmp, "#!/bin/sh\nrm %s\n%s", fname, command); 28 fprintf(tmp, "#!/bin/sh\nrm %s\n%s", fname, command);
29 fclose(tmp); 29 fclose(tmp);
30 chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR); 30 chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR);
31 char *cmd = malloc(sizeof(char) * (strlen(terminal) + strlen(" -e ") + strlen(fname) + 1)); 31 size_t cmd_size = strlen(terminal) + strlen(" -e ") + strlen(fname) + 1;
32 sprintf(cmd, "%s -e %s", terminal, fname); 32 char *cmd = malloc(cmd_size);
33 execl("/bin/sh", "/bin/sh", "-c", cmd, NULL); 33 if (!cmd) {
34 sway_log_errno(SWAY_ERROR, "Failed to run command, execl() returned."); 34 perror("malloc");
35 return false;
36 }
37 snprintf(cmd, cmd_size, "%s -e %s", terminal, fname);
38 execlp("sh", "sh", "-c", cmd, NULL);
39 sway_log_errno(SWAY_ERROR, "Failed to run command, execlp() returned.");
35 free(cmd); 40 free(cmd);
36 return false; 41 return false;
37} 42}
@@ -58,7 +63,7 @@ static void swaynag_button_execute(struct swaynag *swaynag,
58 } else if (pid == 0) { 63 } else if (pid == 0) {
59 // Child of the child. Will be reparented to the init process 64 // Child of the child. Will be reparented to the init process
60 char *terminal = getenv("TERMINAL"); 65 char *terminal = getenv("TERMINAL");
61 if (button->terminal && terminal && strlen(terminal)) { 66 if (button->terminal && terminal && *terminal) {
62 sway_log(SWAY_DEBUG, "Found $TERMINAL: %s", terminal); 67 sway_log(SWAY_DEBUG, "Found $TERMINAL: %s", terminal);
63 if (!terminal_execute(terminal, button->action)) { 68 if (!terminal_execute(terminal, button->action)) {
64 swaynag_destroy(swaynag); 69 swaynag_destroy(swaynag);
@@ -69,8 +74,8 @@ static void swaynag_button_execute(struct swaynag *swaynag,
69 sway_log(SWAY_DEBUG, 74 sway_log(SWAY_DEBUG,
70 "$TERMINAL not found. Running directly"); 75 "$TERMINAL not found. Running directly");
71 } 76 }
72 execl("/bin/sh", "/bin/sh", "-c", button->action, NULL); 77 execlp("sh", "sh", "-c", button->action, NULL);
73 sway_log_errno(SWAY_DEBUG, "execl failed"); 78 sway_log_errno(SWAY_DEBUG, "execlp failed");
74 _exit(EXIT_FAILURE); 79 _exit(EXIT_FAILURE);
75 } 80 }
76 } 81 }
@@ -103,7 +108,7 @@ static void layer_surface_closed(void *data,
103 swaynag_destroy(swaynag); 108 swaynag_destroy(swaynag);
104} 109}
105 110
106static struct zwlr_layer_surface_v1_listener layer_surface_listener = { 111static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
107 .configure = layer_surface_configure, 112 .configure = layer_surface_configure,
108 .closed = layer_surface_closed, 113 .closed = layer_surface_closed,
109}; 114};
@@ -124,7 +129,7 @@ static void surface_enter(void *data, struct wl_surface *surface,
124 }; 129 };
125} 130}
126 131
127static struct wl_surface_listener surface_listener = { 132static const struct wl_surface_listener surface_listener = {
128 .enter = surface_enter, 133 .enter = surface_enter,
129 .leave = nop, 134 .leave = nop,
130}; 135};
@@ -138,7 +143,7 @@ static void update_cursor(struct swaynag_seat *seat) {
138 const char *cursor_theme = getenv("XCURSOR_THEME"); 143 const char *cursor_theme = getenv("XCURSOR_THEME");
139 unsigned cursor_size = 24; 144 unsigned cursor_size = 24;
140 const char *env_cursor_size = getenv("XCURSOR_SIZE"); 145 const char *env_cursor_size = getenv("XCURSOR_SIZE");
141 if (env_cursor_size && strlen(env_cursor_size) > 0) { 146 if (env_cursor_size && *env_cursor_size) {
142 errno = 0; 147 errno = 0;
143 char *end; 148 char *end;
144 unsigned size = strtoul(env_cursor_size, &end, 10); 149 unsigned size = strtoul(env_cursor_size, &end, 10);
@@ -148,8 +153,15 @@ static void update_cursor(struct swaynag_seat *seat) {
148 } 153 }
149 pointer->cursor_theme = wl_cursor_theme_load( 154 pointer->cursor_theme = wl_cursor_theme_load(
150 cursor_theme, cursor_size * swaynag->scale, swaynag->shm); 155 cursor_theme, cursor_size * swaynag->scale, swaynag->shm);
151 struct wl_cursor *cursor = 156 if (!pointer->cursor_theme) {
152 wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); 157 sway_log(SWAY_ERROR, "Failed to load cursor theme");
158 return;
159 }
160 struct wl_cursor *cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "default");
161 if (!cursor) {
162 sway_log(SWAY_ERROR, "Failed to get default cursor from theme");
163 return;
164 }
153 pointer->cursor_image = cursor->images[0]; 165 pointer->cursor_image = cursor->images[0];
154 wl_surface_set_buffer_scale(pointer->cursor_surface, 166 wl_surface_set_buffer_scale(pointer->cursor_surface,
155 swaynag->scale); 167 swaynag->scale);
@@ -177,9 +189,22 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
177 uint32_t serial, struct wl_surface *surface, 189 uint32_t serial, struct wl_surface *surface,
178 wl_fixed_t surface_x, wl_fixed_t surface_y) { 190 wl_fixed_t surface_x, wl_fixed_t surface_y) {
179 struct swaynag_seat *seat = data; 191 struct swaynag_seat *seat = data;
192
180 struct swaynag_pointer *pointer = &seat->pointer; 193 struct swaynag_pointer *pointer = &seat->pointer;
181 pointer->serial = serial; 194 pointer->x = wl_fixed_to_int(surface_x);
182 update_cursor(seat); 195 pointer->y = wl_fixed_to_int(surface_y);
196
197 if (seat->swaynag->cursor_shape_manager) {
198 struct wp_cursor_shape_device_v1 *device =
199 wp_cursor_shape_manager_v1_get_pointer(
200 seat->swaynag->cursor_shape_manager, wl_pointer);
201 wp_cursor_shape_device_v1_set_shape(device, serial,
202 WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
203 wp_cursor_shape_device_v1_destroy(device);
204 } else {
205 pointer->serial = serial;
206 update_cursor(seat);
207 }
183} 208}
184 209
185static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, 210static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
@@ -198,8 +223,8 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
198 return; 223 return;
199 } 224 }
200 225
201 double x = seat->pointer.x * swaynag->scale; 226 double x = seat->pointer.x;
202 double y = seat->pointer.y * swaynag->scale; 227 double y = seat->pointer.y;
203 for (int i = 0; i < swaynag->buttons->length; i++) { 228 for (int i = 0; i < swaynag->buttons->length; i++) {
204 struct swaynag_button *nagbutton = swaynag->buttons->items[i]; 229 struct swaynag_button *nagbutton = swaynag->buttons->items[i];
205 if (x >= nagbutton->x 230 if (x >= nagbutton->x
@@ -263,7 +288,7 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
263 render_frame(swaynag); 288 render_frame(swaynag);
264} 289}
265 290
266static struct wl_pointer_listener pointer_listener = { 291static const struct wl_pointer_listener pointer_listener = {
267 .enter = wl_pointer_enter, 292 .enter = wl_pointer_enter,
268 .leave = nop, 293 .leave = nop,
269 .motion = wl_pointer_motion, 294 .motion = wl_pointer_motion,
@@ -289,7 +314,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
289 } 314 }
290} 315}
291 316
292const struct wl_seat_listener seat_listener = { 317static const struct wl_seat_listener seat_listener = {
293 .capabilities = seat_handle_capabilities, 318 .capabilities = seat_handle_capabilities,
294 .name = nop, 319 .name = nop,
295}; 320};
@@ -305,33 +330,25 @@ static void output_scale(void *data, struct wl_output *output,
305 } 330 }
306} 331}
307 332
308static struct wl_output_listener output_listener = { 333static void output_name(void *data, struct wl_output *output,
309 .geometry = nop, 334 const char *name) {
310 .mode = nop,
311 .done = nop,
312 .scale = output_scale,
313};
314
315static void xdg_output_handle_name(void *data,
316 struct zxdg_output_v1 *xdg_output, const char *name) {
317 struct swaynag_output *swaynag_output = data; 335 struct swaynag_output *swaynag_output = data;
318 char *outname = swaynag_output->swaynag->type->output; 336 swaynag_output->name = strdup(name);
319 sway_log(SWAY_DEBUG, "Checking against output %s for %s", name, outname); 337
320 if (!swaynag_output->swaynag->output && outname && name 338 const char *outname = swaynag_output->swaynag->type->output;
321 && strcmp(outname, name) == 0) { 339 if (!swaynag_output->swaynag->output && outname &&
340 strcmp(outname, name) == 0) {
322 sway_log(SWAY_DEBUG, "Using output %s", name); 341 sway_log(SWAY_DEBUG, "Using output %s", name);
323 swaynag_output->swaynag->output = swaynag_output; 342 swaynag_output->swaynag->output = swaynag_output;
324 } 343 }
325 swaynag_output->name = strdup(name);
326 zxdg_output_v1_destroy(xdg_output);
327 swaynag_output->swaynag->querying_outputs--;
328} 344}
329 345
330static struct zxdg_output_v1_listener xdg_output_listener = { 346static const struct wl_output_listener output_listener = {
331 .logical_position = nop, 347 .geometry = nop,
332 .logical_size = nop, 348 .mode = nop,
333 .done = nop, 349 .done = nop,
334 .name = xdg_output_handle_name, 350 .scale = output_scale,
351 .name = output_name,
335 .description = nop, 352 .description = nop,
336}; 353};
337 354
@@ -345,6 +362,7 @@ static void handle_global(void *data, struct wl_registry *registry,
345 struct swaynag_seat *seat = 362 struct swaynag_seat *seat =
346 calloc(1, sizeof(struct swaynag_seat)); 363 calloc(1, sizeof(struct swaynag_seat));
347 if (!seat) { 364 if (!seat) {
365 perror("calloc");
348 return; 366 return;
349 } 367 }
350 368
@@ -359,33 +377,28 @@ static void handle_global(void *data, struct wl_registry *registry,
359 } else if (strcmp(interface, wl_shm_interface.name) == 0) { 377 } else if (strcmp(interface, wl_shm_interface.name) == 0) {
360 swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); 378 swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
361 } else if (strcmp(interface, wl_output_interface.name) == 0) { 379 } else if (strcmp(interface, wl_output_interface.name) == 0) {
362 if (!swaynag->output && swaynag->xdg_output_manager) { 380 if (!swaynag->output) {
363 swaynag->querying_outputs++;
364 struct swaynag_output *output = 381 struct swaynag_output *output =
365 calloc(1, sizeof(struct swaynag_output)); 382 calloc(1, sizeof(struct swaynag_output));
383 if (!output) {
384 perror("calloc");
385 return;
386 }
366 output->wl_output = wl_registry_bind(registry, name, 387 output->wl_output = wl_registry_bind(registry, name,
367 &wl_output_interface, 3); 388 &wl_output_interface, 4);
368 output->wl_name = name; 389 output->wl_name = name;
369 output->scale = 1; 390 output->scale = 1;
370 output->swaynag = swaynag; 391 output->swaynag = swaynag;
371 wl_list_insert(&swaynag->outputs, &output->link); 392 wl_list_insert(&swaynag->outputs, &output->link);
372 wl_output_add_listener(output->wl_output, 393 wl_output_add_listener(output->wl_output,
373 &output_listener, output); 394 &output_listener, output);
374
375 struct zxdg_output_v1 *xdg_output;
376 xdg_output = zxdg_output_manager_v1_get_xdg_output(
377 swaynag->xdg_output_manager, output->wl_output);
378 zxdg_output_v1_add_listener(xdg_output,
379 &xdg_output_listener, output);
380 } 395 }
381 } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { 396 } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
382 swaynag->layer_shell = wl_registry_bind( 397 swaynag->layer_shell = wl_registry_bind(
383 registry, name, &zwlr_layer_shell_v1_interface, 1); 398 registry, name, &zwlr_layer_shell_v1_interface, 1);
384 } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 399 } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
385 && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { 400 swaynag->cursor_shape_manager = wl_registry_bind(
386 swaynag->xdg_output_manager = wl_registry_bind(registry, name, 401 registry, name, &wp_cursor_shape_manager_v1_interface, 1);
387 &zxdg_output_manager_v1_interface,
388 ZXDG_OUTPUT_V1_NAME_SINCE_VERSION);
389 } 402 }
390} 403}
391 404
@@ -451,12 +464,11 @@ void swaynag_setup(struct swaynag *swaynag) {
451 464
452 assert(swaynag->compositor && swaynag->layer_shell && swaynag->shm); 465 assert(swaynag->compositor && swaynag->layer_shell && swaynag->shm);
453 466
454 while (swaynag->querying_outputs > 0) { 467 // Second roundtrip to get wl_output properties
455 if (wl_display_roundtrip(swaynag->display) < 0) { 468 if (wl_display_roundtrip(swaynag->display) < 0) {
456 sway_log(SWAY_ERROR, "Error during outputs init."); 469 sway_log(SWAY_ERROR, "Error during outputs init.");
457 swaynag_destroy(swaynag); 470 swaynag_destroy(swaynag);
458 exit(EXIT_FAILURE); 471 exit(EXIT_FAILURE);
459 }
460 } 472 }
461 473
462 if (!swaynag->output && swaynag->type->output) { 474 if (!swaynag->output && swaynag->type->output) {
@@ -465,7 +477,9 @@ void swaynag_setup(struct swaynag *swaynag) {
465 exit(EXIT_FAILURE); 477 exit(EXIT_FAILURE);
466 } 478 }
467 479
468 swaynag_setup_cursors(swaynag); 480 if (!swaynag->cursor_shape_manager) {
481 swaynag_setup_cursors(swaynag);
482 }
469 483
470 swaynag->surface = wl_compositor_create_surface(swaynag->compositor); 484 swaynag->surface = wl_compositor_create_surface(swaynag->compositor);
471 assert(swaynag->surface); 485 assert(swaynag->surface);
@@ -474,7 +488,8 @@ void swaynag_setup(struct swaynag *swaynag) {
474 swaynag->layer_surface = zwlr_layer_shell_v1_get_layer_surface( 488 swaynag->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
475 swaynag->layer_shell, swaynag->surface, 489 swaynag->layer_shell, swaynag->surface,
476 swaynag->output ? swaynag->output->wl_output : NULL, 490 swaynag->output ? swaynag->output->wl_output : NULL,
477 ZWLR_LAYER_SHELL_V1_LAYER_TOP, "swaynag"); 491 swaynag->type->layer,
492 "swaynag");
478 assert(swaynag->layer_surface); 493 assert(swaynag->layer_surface);
479 zwlr_layer_surface_v1_add_listener(swaynag->layer_surface, 494 zwlr_layer_surface_v1_add_listener(swaynag->layer_surface,
480 &layer_surface_listener, swaynag); 495 &layer_surface_listener, swaynag);
@@ -491,10 +506,6 @@ void swaynag_run(struct swaynag *swaynag) {
491 && wl_display_dispatch(swaynag->display) != -1) { 506 && wl_display_dispatch(swaynag->display) != -1) {
492 // This is intentionally left blank 507 // This is intentionally left blank
493 } 508 }
494
495 if (swaynag->display) {
496 wl_display_disconnect(swaynag->display);
497 }
498} 509}
499 510
500void swaynag_destroy(struct swaynag *swaynag) { 511void swaynag_destroy(struct swaynag *swaynag) {
@@ -509,6 +520,7 @@ void swaynag_destroy(struct swaynag *swaynag) {
509 } 520 }
510 list_free(swaynag->buttons); 521 list_free(swaynag->buttons);
511 free(swaynag->details.message); 522 free(swaynag->details.message);
523 free(swaynag->details.details_text);
512 free(swaynag->details.button_up.text); 524 free(swaynag->details.button_up.text);
513 free(swaynag->details.button_down.text); 525 free(swaynag->details.button_down.text);
514 526
@@ -529,13 +541,8 @@ void swaynag_destroy(struct swaynag *swaynag) {
529 swaynag_seat_destroy(seat); 541 swaynag_seat_destroy(seat);
530 } 542 }
531 543
532 if (&swaynag->buffers[0]) { 544 destroy_buffer(&swaynag->buffers[0]);
533 destroy_buffer(&swaynag->buffers[0]); 545 destroy_buffer(&swaynag->buffers[1]);
534 }
535
536 if (&swaynag->buffers[1]) {
537 destroy_buffer(&swaynag->buffers[1]);
538 }
539 546
540 if (swaynag->outputs.prev || swaynag->outputs.next) { 547 if (swaynag->outputs.prev || swaynag->outputs.next) {
541 struct swaynag_output *output, *temp; 548 struct swaynag_output *output, *temp;
@@ -554,4 +561,8 @@ void swaynag_destroy(struct swaynag *swaynag) {
554 if (swaynag->shm) { 561 if (swaynag->shm) {
555 wl_shm_destroy(swaynag->shm); 562 wl_shm_destroy(swaynag->shm);
556 } 563 }
564
565 if (swaynag->display) {
566 wl_display_disconnect(swaynag->display);
567 }
557} 568}