diff options
Diffstat (limited to 'swaynag/swaynag.c')
-rw-r--r-- | swaynag/swaynag.c | 153 |
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 | ||
106 | static struct zwlr_layer_surface_v1_listener layer_surface_listener = { | 111 | static 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 | ||
127 | static struct wl_surface_listener surface_listener = { | 132 | static 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 | ||
185 | static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | 210 | static 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 | ||
266 | static struct wl_pointer_listener pointer_listener = { | 291 | static 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 | ||
292 | const struct wl_seat_listener seat_listener = { | 317 | static 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 | ||
308 | static struct wl_output_listener output_listener = { | 333 | static 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 | |||
315 | static 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 | ||
330 | static struct zxdg_output_v1_listener xdg_output_listener = { | 346 | static 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 | ||
500 | void swaynag_destroy(struct swaynag *swaynag) { | 511 | void 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 | } |