diff options
Diffstat (limited to 'swaybar/bar.c')
-rw-r--r-- | swaybar/bar.c | 125 |
1 files changed, 95 insertions, 30 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c index 5b7fea71..0deba72d 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #endif | 18 | #endif |
19 | #include "swaybar/bar.h" | 19 | #include "swaybar/bar.h" |
20 | #include "swaybar/config.h" | 20 | #include "swaybar/config.h" |
21 | #include "swaybar/event_loop.h" | ||
22 | #include "swaybar/i3bar.h" | 21 | #include "swaybar/i3bar.h" |
23 | #include "swaybar/ipc.h" | 22 | #include "swaybar/ipc.h" |
24 | #include "swaybar/status_line.h" | 23 | #include "swaybar/status_line.h" |
@@ -26,15 +25,28 @@ | |||
26 | #include "ipc-client.h" | 25 | #include "ipc-client.h" |
27 | #include "list.h" | 26 | #include "list.h" |
28 | #include "log.h" | 27 | #include "log.h" |
28 | #include "loop.h" | ||
29 | #include "pool-buffer.h" | 29 | #include "pool-buffer.h" |
30 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | 30 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" |
31 | #include "xdg-output-unstable-v1-client-protocol.h" | 31 | #include "xdg-output-unstable-v1-client-protocol.h" |
32 | 32 | ||
33 | static void bar_init(struct swaybar *bar) { | 33 | static void bar_init(struct swaybar *bar) { |
34 | bar->config = init_config(); | 34 | bar->config = init_config(); |
35 | bar->visible = true; | ||
35 | wl_list_init(&bar->outputs); | 36 | wl_list_init(&bar->outputs); |
36 | } | 37 | } |
37 | 38 | ||
39 | void free_hotspots(struct wl_list *list) { | ||
40 | struct swaybar_hotspot *hotspot, *tmp; | ||
41 | wl_list_for_each_safe(hotspot, tmp, list, link) { | ||
42 | wl_list_remove(&hotspot->link); | ||
43 | if (hotspot->destroy) { | ||
44 | hotspot->destroy(hotspot->data); | ||
45 | } | ||
46 | free(hotspot); | ||
47 | } | ||
48 | } | ||
49 | |||
38 | void free_workspaces(struct wl_list *list) { | 50 | void free_workspaces(struct wl_list *list) { |
39 | struct swaybar_workspace *ws, *tmp; | 51 | struct swaybar_workspace *ws, *tmp; |
40 | wl_list_for_each_safe(ws, tmp, list, link) { | 52 | wl_list_for_each_safe(ws, tmp, list, link) { |
@@ -59,14 +71,8 @@ static void swaybar_output_free(struct swaybar_output *output) { | |||
59 | wl_output_destroy(output->output); | 71 | wl_output_destroy(output->output); |
60 | destroy_buffer(&output->buffers[0]); | 72 | destroy_buffer(&output->buffers[0]); |
61 | destroy_buffer(&output->buffers[1]); | 73 | destroy_buffer(&output->buffers[1]); |
74 | free_hotspots(&output->hotspots); | ||
62 | free_workspaces(&output->workspaces); | 75 | free_workspaces(&output->workspaces); |
63 | struct swaybar_hotspot *hotspot, *hotspot_tmp; | ||
64 | wl_list_for_each_safe(hotspot, hotspot_tmp, &output->hotspots, link) { | ||
65 | if (hotspot->destroy) { | ||
66 | hotspot->destroy(hotspot->data); | ||
67 | } | ||
68 | free(hotspot); | ||
69 | } | ||
70 | wl_list_remove(&output->link); | 76 | wl_list_remove(&output->link); |
71 | free(output->name); | 77 | free(output->name); |
72 | free(output); | 78 | free(output); |
@@ -75,9 +81,7 @@ static void swaybar_output_free(struct swaybar_output *output) { | |||
75 | static void set_output_dirty(struct swaybar_output *output) { | 81 | static void set_output_dirty(struct swaybar_output *output) { |
76 | if (output->frame_scheduled) { | 82 | if (output->frame_scheduled) { |
77 | output->dirty = true; | 83 | output->dirty = true; |
78 | return; | 84 | } else if (output->surface) { |
79 | } | ||
80 | if (output->surface) { | ||
81 | render_frame(output); | 85 | render_frame(output); |
82 | } | 86 | } |
83 | } | 87 | } |
@@ -335,21 +339,68 @@ const struct wl_seat_listener seat_listener = { | |||
335 | }; | 339 | }; |
336 | 340 | ||
337 | static void add_layer_surface(struct swaybar_output *output) { | 341 | static void add_layer_surface(struct swaybar_output *output) { |
338 | if (output->surface != NULL) { | 342 | if (output->layer_surface) { |
339 | return; | 343 | return; |
340 | } | 344 | } |
341 | struct swaybar *bar = output->bar; | 345 | struct swaybar *bar = output->bar; |
342 | 346 | ||
343 | output->surface = wl_compositor_create_surface(bar->compositor); | 347 | struct swaybar_config *config = bar->config; |
344 | assert(output->surface); | 348 | bool hidden = strcmp(config->mode, "hide") == 0; |
345 | output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( | 349 | output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( |
346 | bar->layer_shell, output->surface, output->output, | 350 | bar->layer_shell, output->surface, output->output, |
351 | hidden ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : | ||
347 | ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); | 352 | ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); |
348 | assert(output->layer_surface); | 353 | assert(output->layer_surface); |
349 | zwlr_layer_surface_v1_add_listener(output->layer_surface, | 354 | zwlr_layer_surface_v1_add_listener(output->layer_surface, |
350 | &layer_surface_listener, output); | 355 | &layer_surface_listener, output); |
351 | zwlr_layer_surface_v1_set_anchor(output->layer_surface, | 356 | |
352 | bar->config->position); | 357 | zwlr_layer_surface_v1_set_anchor(output->layer_surface, config->position); |
358 | if (hidden) { | ||
359 | zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | static void destroy_layer_surface(struct swaybar_output *output) { | ||
364 | if (!output->layer_surface) { | ||
365 | return; | ||
366 | } | ||
367 | zwlr_layer_surface_v1_destroy(output->layer_surface); | ||
368 | wl_surface_attach(output->surface, NULL, 0, 0); // detach buffer | ||
369 | output->layer_surface = NULL; | ||
370 | output->width = 0; | ||
371 | output->frame_scheduled = false; | ||
372 | } | ||
373 | |||
374 | bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) { | ||
375 | struct swaybar_config *config = bar->config; | ||
376 | bool visible = !(strcmp(config->mode, "invisible") == 0 || | ||
377 | (strcmp(config->mode, config->hidden_state) == 0 // both "hide" | ||
378 | && !bar->visible_by_modifier && !bar->visible_by_urgency)); | ||
379 | |||
380 | struct swaybar_output *output; | ||
381 | if (visible == bar->visible) { | ||
382 | if (visible && moving_layer) { | ||
383 | // need to destroy layer surface to move to a different layer | ||
384 | wl_list_for_each(output, &bar->outputs, link) { | ||
385 | destroy_layer_surface(output); | ||
386 | add_layer_surface(output); | ||
387 | } | ||
388 | } | ||
389 | } else { | ||
390 | bar->visible = visible; | ||
391 | wl_list_for_each(output, &bar->outputs, link) { | ||
392 | if (visible) { | ||
393 | add_layer_surface(output); | ||
394 | } else { | ||
395 | destroy_layer_surface(output); | ||
396 | } | ||
397 | } | ||
398 | wlr_log(WLR_DEBUG, "Sending %s signal to status command", | ||
399 | visible ? "cont" : "stop"); | ||
400 | kill(bar->status->pid, | ||
401 | visible ? bar->status->cont_signal : bar->status->stop_signal); | ||
402 | } | ||
403 | return visible; | ||
353 | } | 404 | } |
354 | 405 | ||
355 | static bool bar_uses_output(struct swaybar *bar, const char *name) { | 406 | static bool bar_uses_output(struct swaybar *bar, const char *name) { |
@@ -420,8 +471,11 @@ static void xdg_output_handle_done(void *data, | |||
420 | wl_list_remove(&output->link); | 471 | wl_list_remove(&output->link); |
421 | wl_list_insert(&bar->outputs, &output->link); | 472 | wl_list_insert(&bar->outputs, &output->link); |
422 | 473 | ||
423 | add_layer_surface(output); | 474 | output->surface = wl_compositor_create_surface(bar->compositor); |
424 | set_output_dirty(output); | 475 | assert(output->surface); |
476 | if (bar->visible) { | ||
477 | add_layer_surface(output); | ||
478 | } | ||
425 | } | 479 | } |
426 | } | 480 | } |
427 | 481 | ||
@@ -517,22 +571,26 @@ static void set_bar_dirty(struct swaybar *bar) { | |||
517 | } | 571 | } |
518 | } | 572 | } |
519 | 573 | ||
520 | bool bar_setup(struct swaybar *bar, | 574 | bool bar_setup(struct swaybar *bar, const char *socket_path) { |
521 | const char *socket_path, const char *bar_id) { | ||
522 | bar_init(bar); | 575 | bar_init(bar); |
523 | init_event_loop(); | 576 | bar->eventloop = loop_create(); |
524 | 577 | ||
525 | bar->ipc_socketfd = ipc_open_socket(socket_path); | 578 | bar->ipc_socketfd = ipc_open_socket(socket_path); |
526 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); | 579 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); |
527 | if (!ipc_initialize(bar, bar_id)) { | 580 | if (!ipc_initialize(bar)) { |
528 | return false; | 581 | return false; |
529 | } | 582 | } |
530 | if (bar->config->status_command) { | 583 | if (bar->config->status_command) { |
531 | bar->status = status_line_init(bar->config->status_command); | 584 | bar->status = status_line_init(bar->config->status_command); |
585 | bar->status->bar = bar; | ||
532 | } | 586 | } |
533 | 587 | ||
534 | bar->display = wl_display_connect(NULL); | 588 | bar->display = wl_display_connect(NULL); |
535 | assert(bar->display); | 589 | if (!bar->display) { |
590 | sway_abort("Unable to connect to the compositor. " | ||
591 | "If your compositor is running, check or set the " | ||
592 | "WAYLAND_DISPLAY environment variable."); | ||
593 | } | ||
536 | 594 | ||
537 | struct wl_registry *registry = wl_display_get_registry(bar->display); | 595 | struct wl_registry *registry = wl_display_get_registry(bar->display); |
538 | wl_registry_add_listener(registry, ®istry_listener, bar); | 596 | wl_registry_add_listener(registry, ®istry_listener, bar); |
@@ -565,8 +623,11 @@ bool bar_setup(struct swaybar *bar, | |||
565 | pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); | 623 | pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); |
566 | assert(pointer->cursor_surface); | 624 | assert(pointer->cursor_surface); |
567 | 625 | ||
568 | ipc_get_workspaces(bar); | 626 | if (bar->config->workspace_buttons) { |
569 | set_bar_dirty(bar); | 627 | if (ipc_get_workspaces(bar)) { |
628 | set_bar_dirty(bar); | ||
629 | } | ||
630 | } | ||
570 | return true; | 631 | return true; |
571 | } | 632 | } |
572 | 633 | ||
@@ -590,21 +651,23 @@ static void status_in(int fd, short mask, void *data) { | |||
590 | if (mask & (POLLHUP | POLLERR)) { | 651 | if (mask & (POLLHUP | POLLERR)) { |
591 | status_error(bar->status, "[error reading from status command]"); | 652 | status_error(bar->status, "[error reading from status command]"); |
592 | set_bar_dirty(bar); | 653 | set_bar_dirty(bar); |
593 | remove_event(fd); | 654 | loop_remove_fd(bar->eventloop, fd); |
594 | } else if (status_handle_readable(bar->status)) { | 655 | } else if (status_handle_readable(bar->status)) { |
595 | set_bar_dirty(bar); | 656 | set_bar_dirty(bar); |
596 | } | 657 | } |
597 | } | 658 | } |
598 | 659 | ||
599 | void bar_run(struct swaybar *bar) { | 660 | void bar_run(struct swaybar *bar) { |
600 | add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); | 661 | loop_add_fd(bar->eventloop, wl_display_get_fd(bar->display), POLLIN, |
601 | add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar); | 662 | display_in, bar); |
663 | loop_add_fd(bar->eventloop, bar->ipc_event_socketfd, POLLIN, ipc_in, bar); | ||
602 | if (bar->status) { | 664 | if (bar->status) { |
603 | add_event(bar->status->read_fd, POLLIN, status_in, bar); | 665 | loop_add_fd(bar->eventloop, bar->status->read_fd, POLLIN, |
666 | status_in, bar); | ||
604 | } | 667 | } |
605 | while (1) { | 668 | while (1) { |
606 | wl_display_flush(bar->display); | 669 | wl_display_flush(bar->display); |
607 | event_loop_poll(); | 670 | loop_poll(bar->eventloop); |
608 | } | 671 | } |
609 | } | 672 | } |
610 | 673 | ||
@@ -625,4 +688,6 @@ void bar_teardown(struct swaybar *bar) { | |||
625 | if (bar->status) { | 688 | if (bar->status) { |
626 | status_line_free(bar->status); | 689 | status_line_free(bar->status); |
627 | } | 690 | } |
691 | free(bar->id); | ||
692 | free(bar->mode); | ||
628 | } | 693 | } |