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 @@ #endif #include "swaybar/bar.h" #include "swaybar/config.h" -#include "swaybar/event_loop.h" #include "swaybar/i3bar.h" #include "swaybar/ipc.h" #include "swaybar/status_line.h" @@ -26,15 +25,28 @@ #include "ipc-client.h" #include "list.h" #include "log.h" +#include "loop.h" #include "pool-buffer.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h" static void bar_init(struct swaybar *bar) { bar->config = init_config(); + bar->visible = true; wl_list_init(&bar->outputs); } +void free_hotspots(struct wl_list *list) { + struct swaybar_hotspot *hotspot, *tmp; + wl_list_for_each_safe(hotspot, tmp, list, link) { + wl_list_remove(&hotspot->link); + if (hotspot->destroy) { + hotspot->destroy(hotspot->data); + } + free(hotspot); + } +} + void free_workspaces(struct wl_list *list) { struct swaybar_workspace *ws, *tmp; wl_list_for_each_safe(ws, tmp, list, link) { @@ -59,14 +71,8 @@ static void swaybar_output_free(struct swaybar_output *output) { wl_output_destroy(output->output); destroy_buffer(&output->buffers[0]); destroy_buffer(&output->buffers[1]); + free_hotspots(&output->hotspots); free_workspaces(&output->workspaces); - struct swaybar_hotspot *hotspot, *hotspot_tmp; - wl_list_for_each_safe(hotspot, hotspot_tmp, &output->hotspots, link) { - if (hotspot->destroy) { - hotspot->destroy(hotspot->data); - } - free(hotspot); - } wl_list_remove(&output->link); free(output->name); free(output); @@ -75,9 +81,7 @@ static void swaybar_output_free(struct swaybar_output *output) { static void set_output_dirty(struct swaybar_output *output) { if (output->frame_scheduled) { output->dirty = true; - return; - } - if (output->surface) { + } else if (output->surface) { render_frame(output); } } @@ -335,21 +339,68 @@ const struct wl_seat_listener seat_listener = { }; static void add_layer_surface(struct swaybar_output *output) { - if (output->surface != NULL) { + if (output->layer_surface) { return; } struct swaybar *bar = output->bar; - output->surface = wl_compositor_create_surface(bar->compositor); - assert(output->surface); + struct swaybar_config *config = bar->config; + bool hidden = strcmp(config->mode, "hide") == 0; output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( bar->layer_shell, output->surface, output->output, + hidden ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); assert(output->layer_surface); zwlr_layer_surface_v1_add_listener(output->layer_surface, &layer_surface_listener, output); - zwlr_layer_surface_v1_set_anchor(output->layer_surface, - bar->config->position); + + zwlr_layer_surface_v1_set_anchor(output->layer_surface, config->position); + if (hidden) { + zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1); + } +} + +static void destroy_layer_surface(struct swaybar_output *output) { + if (!output->layer_surface) { + return; + } + zwlr_layer_surface_v1_destroy(output->layer_surface); + wl_surface_attach(output->surface, NULL, 0, 0); // detach buffer + output->layer_surface = NULL; + output->width = 0; + output->frame_scheduled = false; +} + +bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) { + struct swaybar_config *config = bar->config; + bool visible = !(strcmp(config->mode, "invisible") == 0 || + (strcmp(config->mode, config->hidden_state) == 0 // both "hide" + && !bar->visible_by_modifier && !bar->visible_by_urgency)); + + struct swaybar_output *output; + if (visible == bar->visible) { + if (visible && moving_layer) { + // need to destroy layer surface to move to a different layer + wl_list_for_each(output, &bar->outputs, link) { + destroy_layer_surface(output); + add_layer_surface(output); + } + } + } else { + bar->visible = visible; + wl_list_for_each(output, &bar->outputs, link) { + if (visible) { + add_layer_surface(output); + } else { + destroy_layer_surface(output); + } + } + wlr_log(WLR_DEBUG, "Sending %s signal to status command", + visible ? "cont" : "stop"); + kill(bar->status->pid, + visible ? bar->status->cont_signal : bar->status->stop_signal); + } + return visible; } static bool bar_uses_output(struct swaybar *bar, const char *name) { @@ -420,8 +471,11 @@ static void xdg_output_handle_done(void *data, wl_list_remove(&output->link); wl_list_insert(&bar->outputs, &output->link); - add_layer_surface(output); - set_output_dirty(output); + output->surface = wl_compositor_create_surface(bar->compositor); + assert(output->surface); + if (bar->visible) { + add_layer_surface(output); + } } } @@ -517,22 +571,26 @@ static void set_bar_dirty(struct swaybar *bar) { } } -bool bar_setup(struct swaybar *bar, - const char *socket_path, const char *bar_id) { +bool bar_setup(struct swaybar *bar, const char *socket_path) { bar_init(bar); - init_event_loop(); + bar->eventloop = loop_create(); bar->ipc_socketfd = ipc_open_socket(socket_path); bar->ipc_event_socketfd = ipc_open_socket(socket_path); - if (!ipc_initialize(bar, bar_id)) { + if (!ipc_initialize(bar)) { return false; } if (bar->config->status_command) { bar->status = status_line_init(bar->config->status_command); + bar->status->bar = bar; } bar->display = wl_display_connect(NULL); - assert(bar->display); + if (!bar->display) { + sway_abort("Unable to connect to the compositor. " + "If your compositor is running, check or set the " + "WAYLAND_DISPLAY environment variable."); + } struct wl_registry *registry = wl_display_get_registry(bar->display); wl_registry_add_listener(registry, ®istry_listener, bar); @@ -565,8 +623,11 @@ bool bar_setup(struct swaybar *bar, pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); assert(pointer->cursor_surface); - ipc_get_workspaces(bar); - set_bar_dirty(bar); + if (bar->config->workspace_buttons) { + if (ipc_get_workspaces(bar)) { + set_bar_dirty(bar); + } + } return true; } @@ -590,21 +651,23 @@ static void status_in(int fd, short mask, void *data) { if (mask & (POLLHUP | POLLERR)) { status_error(bar->status, "[error reading from status command]"); set_bar_dirty(bar); - remove_event(fd); + loop_remove_fd(bar->eventloop, fd); } else if (status_handle_readable(bar->status)) { set_bar_dirty(bar); } } void bar_run(struct swaybar *bar) { - add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); - add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar); + loop_add_fd(bar->eventloop, wl_display_get_fd(bar->display), POLLIN, + display_in, bar); + loop_add_fd(bar->eventloop, bar->ipc_event_socketfd, POLLIN, ipc_in, bar); if (bar->status) { - add_event(bar->status->read_fd, POLLIN, status_in, bar); + loop_add_fd(bar->eventloop, bar->status->read_fd, POLLIN, + status_in, bar); } while (1) { wl_display_flush(bar->display); - event_loop_poll(); + loop_poll(bar->eventloop); } } @@ -625,4 +688,6 @@ void bar_teardown(struct swaybar *bar) { if (bar->status) { status_line_free(bar->status); } + free(bar->id); + free(bar->mode); } |