From cab1352801b62d1b8a12ca1c995cb24445ce4bc9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 23:04:20 -0400 Subject: Start port of swaybar to layer shell This starts up the event loop and wayland display and shims out the basic top level rendering concepts. Also includes some changes to incorporate pango into the 1.x codebase properly. --- swaybar/bar.c | 444 +++++++++++++--------------------------------------------- 1 file changed, 100 insertions(+), 344 deletions(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index f12923a8..e1d594b4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -1,390 +1,146 @@ #define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include #include -#include #include -#include -#include #include -#include -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif -#ifdef ENABLE_TRAY -#include -#include "swaybar/tray/sni_watcher.h" -#include "swaybar/tray/tray.h" -#include "swaybar/tray/sni.h" -#endif -#include "swaybar/ipc.h" +#include +#include +#include #include "swaybar/render.h" #include "swaybar/config.h" -#include "swaybar/status_line.h" #include "swaybar/event_loop.h" #include "swaybar/bar.h" -#include "ipc-client.h" #include "list.h" -#include "log.h" +#include "pango.h" +#include "pool-buffer.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" -static void bar_init(struct bar *bar) { +static void bar_init(struct swaybar *bar) { bar->config = init_config(); - bar->status = init_status_line(); - bar->outputs = create_list(); + wl_list_init(&bar->outputs); } -static void spawn_status_cmd_proc(struct bar *bar) { - if (bar->config->status_command) { - int pipe_read_fd[2]; - int pipe_write_fd[2]; - - if (pipe(pipe_read_fd) != 0) { - sway_log(L_ERROR, "Unable to create pipes for status_command fork"); - return; - } - if (pipe(pipe_write_fd) != 0) { - sway_log(L_ERROR, "Unable to create pipe for status_command fork (write)"); - close(pipe_read_fd[0]); - close(pipe_read_fd[1]); - return; - } - - bar->status_command_pid = fork(); - if (bar->status_command_pid == 0) { - close(pipe_read_fd[0]); - dup2(pipe_read_fd[1], STDOUT_FILENO); - close(pipe_read_fd[1]); - - dup2(pipe_write_fd[0], STDIN_FILENO); - close(pipe_write_fd[0]); - close(pipe_write_fd[1]); - - char *const cmd[] = { - "sh", - "-c", - bar->config->status_command, - NULL, - }; - execvp(cmd[0], cmd); - return; - } - - close(pipe_read_fd[1]); - bar->status_read_fd = pipe_read_fd[0]; - fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK); - - close(pipe_write_fd[0]); - bar->status_write_fd = pipe_write_fd[1]; - fcntl(bar->status_write_fd, F_SETFL, O_NONBLOCK); - } -} - -struct output *new_output(const char *name) { - struct output *output = malloc(sizeof(struct output)); +struct swaybar_output *new_output(const char *name) { + struct swaybar_output *output = malloc(sizeof(struct swaybar_output)); output->name = strdup(name); - output->window = NULL; - output->registry = NULL; - output->workspaces = create_list(); -#ifdef ENABLE_TRAY - output->items = create_list(); -#endif return output; } -static void mouse_button_notify(struct window *window, int x, int y, - uint32_t button, uint32_t state_w) { - sway_log(L_DEBUG, "Mouse button %d clicked at %d %d %d", button, x, y, state_w); - if (!state_w) { - return; - } - - struct output *clicked_output = NULL; - for (int i = 0; i < swaybar.outputs->length; i++) { - struct output *output = swaybar.outputs->items[i]; - if (window == output->window) { - clicked_output = output; - break; - } - } - - if (!sway_assert(clicked_output != NULL, "Got pointer event for non-existing output")) { - return; - } - - double button_x = 0.5; - for (int i = 0; i < clicked_output->workspaces->length; i++) { - struct workspace *workspace = clicked_output->workspaces->items[i]; - int button_width, button_height; - - workspace_button_size(window, workspace->name, &button_width, &button_height); - - button_x += button_width; - if (x <= button_x) { - ipc_send_workspace_command(workspace->name); - break; - } - } - - switch (button) { - case BTN_LEFT: - status_line_mouse_event(&swaybar, x, y, 1); - break; - case BTN_MIDDLE: - status_line_mouse_event(&swaybar, x, y, 2); - break; - case BTN_RIGHT: - status_line_mouse_event(&swaybar, x, y, 3); - break; - } - -#ifdef ENABLE_TRAY - tray_mouse_event(clicked_output, x, y, button, state_w); -#endif - +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct swaybar_output *output = data; + output->width = width; + output->height = height; + zwlr_layer_surface_v1_ack_configure(surface, serial); + render_frame(output->bar, output); } -static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) { - sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down"); - - // If there are status blocks and click_events are enabled - // check if the position is within the status area and if so - // tell the status line to output the event and skip workspace - // switching below. - int num_blocks = swaybar.status->block_line->length; - if (swaybar.status->click_events && num_blocks > 0) { - struct status_block *first_block = swaybar.status->block_line->items[0]; - int x = window->pointer_input.last_x; - int y = window->pointer_input.last_y; - if (x > first_block->x) { - if (direction == SCROLL_UP) { - status_line_mouse_event(&swaybar, x, y, 4); - } else { - status_line_mouse_event(&swaybar, x, y, 5); - } - return; - } - } +static void layer_surface_closed(void *_output, + struct zwlr_layer_surface_v1 *surface) { + // TODO: Deal with hotplugging + struct swaybar_output *output = output; + zwlr_layer_surface_v1_destroy(output->layer_surface); + wl_surface_destroy(output->surface); +} - if (!swaybar.config->wrap_scroll) { - // Find output this window lives on - int i; - struct output *output = NULL; - for (i = 0; i < swaybar.outputs->length; ++i) { - output = swaybar.outputs->items[i]; - if (output->window == window) { - break; - } - } - if (!sway_assert(i != swaybar.outputs->length, "Unknown window in scroll event")) { - return; - } - int focused = -1; - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - if (ws->focused) { - focused = i; - break; - } - } - if (!sway_assert(focused != -1, "Scroll wheel event received on inactive output")) { - return; - } - if ((focused == 0 && direction == SCROLL_UP) || - (focused == output->workspaces->length - 1 && direction == SCROLL_DOWN)) { - // Do not wrap - return; - } +struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + struct swaybar *bar = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + bar->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + bar->shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + static int idx = 0; + struct swaybar_output *output = + calloc(1, sizeof(struct swaybar_output)); + output->bar = bar; + output->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + output->idx = idx++; + wl_list_insert(&bar->outputs, &output->link); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + bar->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); } +} - const char *workspace_name = direction == SCROLL_UP ? "prev_on_output" : "next_on_output"; - ipc_send_workspace_command(workspace_name); +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares } -void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { - /* initialize bar with default values */ - bar_init(bar); +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; - /* Initialize event loop lists */ +void bar_setup(struct swaybar *bar, + const char *socket_path, const char *bar_id) { + bar_init(bar); init_event_loop(); - /* connect to sway ipc */ - bar->ipc_socketfd = ipc_open_socket(socket_path); - bar->ipc_event_socketfd = ipc_open_socket(socket_path); - - ipc_bar_init(bar, bar_id); - - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *bar_output = bar->outputs->items[i]; - - bar_output->registry = registry_poll(); - - if (!bar_output->registry->desktop_shell) { - sway_abort("swaybar requires the compositor to support the desktop-shell extension."); - } - - struct output_state *output = bar_output->registry->outputs->items[bar_output->idx]; - - bar_output->window = window_setup(bar_output->registry, - output->width / output->scale, 30, output->scale, false); - if (!bar_output->window) { - sway_abort("Failed to create window."); - } - desktop_shell_set_panel(bar_output->registry->desktop_shell, - output->output, bar_output->window->surface); - desktop_shell_set_panel_position(bar_output->registry->desktop_shell, + assert(bar->display = wl_display_connect(NULL)); + + struct wl_registry *registry = wl_display_get_registry(bar->display); + wl_registry_add_listener(registry, ®istry_listener, bar); + wl_display_roundtrip(bar->display); + assert(bar->compositor && bar->layer_shell && bar->shm); + + // TODO: we might not necessarily be meant to do all of the outputs + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + assert(output->surface = wl_compositor_create_surface(bar->compositor)); + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + bar->layer_shell, output->surface, output->output, + 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); - - window_make_shell(bar_output->window); - - /* set font */ - bar_output->window->font = bar->config->font; - - /* set mouse event callbacks */ - bar_output->window->pointer_input.notify_button = mouse_button_notify; - bar_output->window->pointer_input.notify_scroll = mouse_scroll_notify; - - /* set window height */ - set_window_height(bar_output->window, bar->config->height); + render_frame(bar, output); } - /* spawn status command */ - spawn_status_cmd_proc(bar); - -#ifdef ENABLE_TRAY - init_tray(bar); -#endif } -bool dirty = true; - -static void respond_ipc(int fd, short mask, void *_bar) { - struct bar *bar = (struct bar *)_bar; - sway_log(L_DEBUG, "Got IPC event."); - dirty = handle_ipc_event(bar); -} - -static void respond_command(int fd, short mask, void *_bar) { - struct bar *bar = (struct bar *)_bar; - dirty = handle_status_line(bar); -} - -static void respond_output(int fd, short mask, void *_output) { - struct output *output = (struct output *)_output; - if (wl_display_dispatch(output->registry->display) == -1) { - sway_log(L_ERROR, "failed to dispatch wl: %d", errno); +static void display_in(int fd, short mask, void *_bar) { + struct swaybar *bar = (struct swaybar *)_bar; + if (wl_display_dispatch(bar->display) == -1) { + wlr_log(L_ERROR, "failed to dispatch wl: %d", errno); } } -void bar_run(struct bar *bar) { - add_event(bar->ipc_event_socketfd, POLLIN, respond_ipc, bar); - add_event(bar->status_read_fd, POLLIN, respond_command, bar); - - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - add_event(wl_display_get_fd(output->registry->display), - POLLIN, respond_output, output); - } - +void bar_run(struct swaybar *bar) { + add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); while (1) { - if (dirty) { - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - if (window_prerender(output->window) && output->window->cairo) { - render(output, bar->config, bar->status); - window_render(output->window); - wl_display_flush(output->registry->display); - } - } - } - - dirty = false; - event_loop_poll(); -#ifdef ENABLE_TRAY - dispatch_dbus(); -#endif } } -void free_workspaces(list_t *workspaces) { - int i; - for (i = 0; i < workspaces->length; ++i) { - struct workspace *ws = workspaces->items[i]; - free(ws->name); - free(ws); +static void free_outputs(struct wl_list *list) { + struct swaybar_output *output, *tmp; + wl_list_for_each_safe(output, tmp, list, link) { + wl_list_remove(&output->link); + free(output->name); + free(output); } - list_free(workspaces); } -static void free_output(struct output *output) { - window_teardown(output->window); - if (output->registry) { - registry_teardown(output->registry); - } - - free(output->name); - - if (output->workspaces) { - free_workspaces(output->workspaces); - } - - free(output); -} - -static void free_outputs(list_t *outputs) { - int i; - for (i = 0; i < outputs->length; ++i) { - free_output(outputs->items[i]); - } - list_free(outputs); -} - -static void terminate_status_command(pid_t pid) { - if (pid) { - // terminate status_command process - int ret = kill(pid, SIGTERM); - if (ret != 0) { - sway_log(L_ERROR, "Unable to terminate status_command [pid: %d]", pid); - } else { - int status; - waitpid(pid, &status, 0); - } - } -} - -void bar_teardown(struct bar *bar) { +void bar_teardown(struct swaybar *bar) { + free_outputs(&bar->outputs); if (bar->config) { free_config(bar->config); } - - if (bar->outputs) { - free_outputs(bar->outputs); - } - - if (bar->status) { - free_status_line(bar->status); - } - - /* close sockets/pipes */ - if (bar->status_read_fd) { - close(bar->status_read_fd); - } - - if (bar->status_write_fd) { - close(bar->status_write_fd); - } - - if (bar->ipc_socketfd) { - close(bar->ipc_socketfd); - } - - if (bar->ipc_event_socketfd) { - close(bar->ipc_event_socketfd); - } - - /* terminate status command process */ - terminate_status_command(bar->status_command_pid); } -- cgit v1.2.3 From 5c9ad035db1bebba3f1954dd1f4328c6421776d4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 23:56:02 -0400 Subject: Wire up basic IPC support --- include/swaybar/bar.h | 3 + include/swaybar/config.h | 17 ++-- include/swaybar/ipc.h | 5 +- swaybar/bar.c | 11 +++ swaybar/config.c | 14 +--- swaybar/ipc.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++ swaybar/meson.build | 1 + 7 files changed, 225 insertions(+), 25 deletions(-) create mode 100644 swaybar/ipc.c (limited to 'swaybar/bar.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 3ae8c0b3..df685f47 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -17,6 +17,9 @@ struct swaybar { struct swaybar_config *config; struct swaybar_output *focused_output; + int ipc_event_socketfd; + int ipc_socketfd; + struct wl_list outputs; }; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 1bfe4843..4b3b5b34 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -2,21 +2,20 @@ #define _SWAYBAR_CONFIG_H #include #include -#include "list.h" +#include #include "util.h" -/** - * Colors for a box with background, border and text colors. - */ struct box_colors { uint32_t border; uint32_t background; uint32_t text; }; -/** - * Swaybar config. - */ +struct config_output { + struct wl_list link; + char *name; +}; + struct swaybar_config { char *status_command; bool pango_markup; @@ -28,8 +27,7 @@ struct swaybar_config { bool binding_mode_indicator; bool wrap_scroll; bool workspace_buttons; - bool all_outputs; - list_t *outputs; + struct wl_list outputs; int height; struct { @@ -51,5 +49,6 @@ struct swaybar_config { struct swaybar_config *init_config(); void free_config(struct swaybar_config *config); +uint32_t parse_position(const char *position); #endif diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 57a1b925..7f71a506 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -2,8 +2,7 @@ #define _SWAYBAR_IPC_H #include "swaybar/bar.h" -void ipc_bar_init(struct swaybar *bar, const char *bar_id); -bool handle_ipc_event(struct swaybar *bar); -void ipc_send_workspace_command(const char *workspace_name); +void ipc_get_config(struct swaybar *bar, const char *bar_id); +void handle_ipc_event(struct swaybar *bar); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index e1d594b4..433e2948 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -14,6 +14,8 @@ #include "swaybar/config.h" #include "swaybar/event_loop.h" #include "swaybar/bar.h" +#include "swaybar/ipc.h" +#include "ipc-client.h" #include "list.h" #include "pango.h" #include "pool-buffer.h" @@ -92,6 +94,10 @@ void bar_setup(struct swaybar *bar, bar_init(bar); init_event_loop(); + bar->ipc_socketfd = ipc_open_socket(socket_path); + bar->ipc_event_socketfd = ipc_open_socket(socket_path); + ipc_get_config(bar, bar_id); + assert(bar->display = wl_display_connect(NULL)); struct wl_registry *registry = wl_display_get_registry(bar->display); @@ -122,6 +128,11 @@ static void display_in(int fd, short mask, void *_bar) { } } +static void ipc_in(int fd, short mask, void *_bar) { + struct swaybar *bar = (struct swaybar *)_bar; + handle_ipc_event(bar); +} + void bar_run(struct swaybar *bar) { add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); while (1) { diff --git a/swaybar/config.c b/swaybar/config.c index 0c2b57e0..83cf2309 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -22,17 +22,6 @@ uint32_t parse_position(const char *position) { } } -char *parse_font(const char *font) { - char *new_font = NULL; - if (strncmp("pango:", font, 6) == 0) { - font += 6; - } - - new_font = strdup(font); - - return new_font; -} - struct swaybar_config *init_config() { struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); config->status_command = NULL; @@ -45,8 +34,7 @@ struct swaybar_config *init_config() { config->binding_mode_indicator = true; config->wrap_scroll = false; config->workspace_buttons = true; - config->all_outputs = false; - config->outputs = create_list(); + wl_list_init(&config->outputs); /* height */ config->height = 0; diff --git a/swaybar/ipc.c b/swaybar/ipc.c new file mode 100644 index 00000000..cef784d0 --- /dev/null +++ b/swaybar/ipc.c @@ -0,0 +1,199 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include "swaybar/config.h" +#include "swaybar/ipc.h" +#include "ipc-client.h" + +char *parse_font(const char *font) { + char *new_font = NULL; + if (strncmp("pango:", font, 6) == 0) { + font += 6; + } + new_font = strdup(font); + return new_font; +} + +static void ipc_parse_colors( + struct swaybar_config *config, json_object *colors) { + json_object *background, *statusline, *separator; + json_object *focused_background, *focused_statusline, *focused_separator; + json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text; + json_object *inactive_workspace_border, *inactive_workspace_bg, *inactive_workspace_text; + json_object *active_workspace_border, *active_workspace_bg, *active_workspace_text; + json_object *urgent_workspace_border, *urgent_workspace_bg, *urgent_workspace_text; + json_object *binding_mode_border, *binding_mode_bg, *binding_mode_text; + json_object_object_get_ex(colors, "background", &background); + json_object_object_get_ex(colors, "statusline", &statusline); + json_object_object_get_ex(colors, "separator", &separator); + json_object_object_get_ex(colors, "focused_background", &focused_background); + json_object_object_get_ex(colors, "focused_statusline", &focused_statusline); + json_object_object_get_ex(colors, "focused_separator", &focused_separator); + json_object_object_get_ex(colors, "focused_workspace_border", &focused_workspace_border); + json_object_object_get_ex(colors, "focused_workspace_bg", &focused_workspace_bg); + json_object_object_get_ex(colors, "focused_workspace_text", &focused_workspace_text); + json_object_object_get_ex(colors, "active_workspace_border", &active_workspace_border); + json_object_object_get_ex(colors, "active_workspace_bg", &active_workspace_bg); + json_object_object_get_ex(colors, "active_workspace_text", &active_workspace_text); + json_object_object_get_ex(colors, "inactive_workspace_border", &inactive_workspace_border); + json_object_object_get_ex(colors, "inactive_workspace_bg", &inactive_workspace_bg); + json_object_object_get_ex(colors, "inactive_workspace_text", &inactive_workspace_text); + json_object_object_get_ex(colors, "urgent_workspace_border", &urgent_workspace_border); + json_object_object_get_ex(colors, "urgent_workspace_bg", &urgent_workspace_bg); + json_object_object_get_ex(colors, "urgent_workspace_text", &urgent_workspace_text); + json_object_object_get_ex(colors, "binding_mode_border", &binding_mode_border); + json_object_object_get_ex(colors, "binding_mode_bg", &binding_mode_bg); + json_object_object_get_ex(colors, "binding_mode_text", &binding_mode_text); + if (background) { + config->colors.background = parse_color(json_object_get_string(background)); + } + if (statusline) { + config->colors.statusline = parse_color(json_object_get_string(statusline)); + } + if (separator) { + config->colors.separator = parse_color(json_object_get_string(separator)); + } + if (focused_background) { + config->colors.focused_background = parse_color(json_object_get_string(focused_background)); + } + if (focused_statusline) { + config->colors.focused_statusline = parse_color(json_object_get_string(focused_statusline)); + } + if (focused_separator) { + config->colors.focused_separator = parse_color(json_object_get_string(focused_separator)); + } + if (focused_workspace_border) { + config->colors.focused_workspace.border = parse_color(json_object_get_string(focused_workspace_border)); + } + if (focused_workspace_bg) { + config->colors.focused_workspace.background = parse_color(json_object_get_string(focused_workspace_bg)); + } + if (focused_workspace_text) { + config->colors.focused_workspace.text = parse_color(json_object_get_string(focused_workspace_text)); + } + if (active_workspace_border) { + config->colors.active_workspace.border = parse_color(json_object_get_string(active_workspace_border)); + } + if (active_workspace_bg) { + config->colors.active_workspace.background = parse_color(json_object_get_string(active_workspace_bg)); + } + if (active_workspace_text) { + config->colors.active_workspace.text = parse_color(json_object_get_string(active_workspace_text)); + } + if (inactive_workspace_border) { + config->colors.inactive_workspace.border = parse_color(json_object_get_string(inactive_workspace_border)); + } + if (inactive_workspace_bg) { + config->colors.inactive_workspace.background = parse_color(json_object_get_string(inactive_workspace_bg)); + } + if (inactive_workspace_text) { + config->colors.inactive_workspace.text = parse_color(json_object_get_string(inactive_workspace_text)); + } + if (binding_mode_border) { + config->colors.binding_mode.border = parse_color(json_object_get_string(binding_mode_border)); + } + if (binding_mode_bg) { + config->colors.binding_mode.background = parse_color(json_object_get_string(binding_mode_bg)); + } + if (binding_mode_text) { + config->colors.binding_mode.text = parse_color(json_object_get_string(binding_mode_text)); + } +} + +static void ipc_parse_config( + struct swaybar_config *config, const char *payload) { + json_object *bar_config = json_tokener_parse(payload); + json_object *markup, *mode, *hidden_bar, *position, *status_command; + json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; + json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; + json_object_object_get_ex(bar_config, "mode", &mode); + json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); + json_object_object_get_ex(bar_config, "position", &position); + json_object_object_get_ex(bar_config, "status_command", &status_command); + json_object_object_get_ex(bar_config, "font", &font); + json_object_object_get_ex(bar_config, "bar_height", &bar_height); + json_object_object_get_ex(bar_config, "wrap_scroll", &wrap_scroll); + json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons); + json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers); + json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator); + json_object_object_get_ex(bar_config, "verbose", &verbose); + json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol); + json_object_object_get_ex(bar_config, "colors", &colors); + json_object_object_get_ex(bar_config, "outputs", &outputs); + json_object_object_get_ex(bar_config, "pango_markup", &markup); + if (status_command) { + free(config->status_command); + config->status_command = strdup(json_object_get_string(status_command)); + } + if (position) { + config->position = parse_position(json_object_get_string(position)); + } + if (font) { + free(config->font); + config->font = parse_font(json_object_get_string(font)); + } + if (sep_symbol) { + free(config->sep_symbol); + config->sep_symbol = strdup(json_object_get_string(sep_symbol)); + } + if (strip_workspace_numbers) { + config->strip_workspace_numbers = json_object_get_boolean(strip_workspace_numbers); + } + if (binding_mode_indicator) { + config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator); + } + if (wrap_scroll) { + config->wrap_scroll = json_object_get_boolean(wrap_scroll); + } + if (workspace_buttons) { + config->workspace_buttons = json_object_get_boolean(workspace_buttons); + } + if (bar_height) { + config->height = json_object_get_int(bar_height); + } + if (markup) { + config->pango_markup = json_object_get_boolean(markup); + } + + struct config_output *output, *tmp; + wl_list_for_each_safe(output, tmp, &config->outputs, link) { + wl_list_remove(&output->link); + free(output->name); + free(output); + } + if (outputs) { + int length = json_object_array_length(outputs); + for (int i = 0; i < length; ++i) { + json_object *output = json_object_array_get_idx(outputs, i); + const char *name = json_object_get_string(output); + if (strcmp("*", name) == 0) { + // TODO: do we need to clear out the list here or something + break; + } + struct config_output *coutput = calloc( + 1, sizeof(struct config_output)); + coutput->name = strdup(name); + wl_list_insert(&config->outputs, &coutput->link); + } + } + + if (colors) { + ipc_parse_colors(config, colors); + } + + json_object_put(bar_config); +} + +void ipc_get_config(struct swaybar *bar, const char *bar_id) { + uint32_t len = strlen(bar_id); + char *res = ipc_single_command(bar->ipc_socketfd, + IPC_GET_BAR_CONFIG, bar_id, &len); + ipc_parse_config(bar->config, res); + free(res); +} + +void handle_ipc_event(struct swaybar *bar) { + struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); + free_ipc_response(resp); +} diff --git a/swaybar/meson.build b/swaybar/meson.build index fd87e51d..6dc7c564 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -4,6 +4,7 @@ executable( 'bar.c', 'config.c', 'event_loop.c', + 'ipc.c', 'main.c', 'render.c', ], -- cgit v1.2.3 From e5e8094dc3119584ae611c3197b38243b6c016c9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 00:07:35 -0400 Subject: Only utilize the configured outputs --- include/swaybar/bar.h | 2 +- include/swaybar/config.h | 1 + swaybar/bar.c | 32 ++++++++++++++++++++------------ swaybar/ipc.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 13 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index df685f47..6e1ab66d 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -31,7 +31,7 @@ struct swaybar_output { struct zwlr_layer_surface_v1 *layer_surface; char *name; - int idx; + size_t index; bool focused; uint32_t width, height; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 4b3b5b34..6bcefe64 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -14,6 +14,7 @@ struct box_colors { struct config_output { struct wl_list link; char *name; + size_t index; }; struct swaybar_config { diff --git a/swaybar/bar.c b/swaybar/bar.c index 433e2948..a6e3b780 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -65,13 +65,13 @@ static void handle_global(void *data, struct wl_registry *registry, bar->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { - static int idx = 0; + static size_t index = 0; struct swaybar_output *output = calloc(1, sizeof(struct swaybar_output)); output->bar = bar; output->output = wl_registry_bind(registry, name, &wl_output_interface, 1); - output->idx = idx++; + output->index = index++; wl_list_insert(&bar->outputs, &output->link); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( @@ -108,16 +108,24 @@ void bar_setup(struct swaybar *bar, // TODO: we might not necessarily be meant to do all of the outputs struct swaybar_output *output; wl_list_for_each(output, &bar->outputs, link) { - assert(output->surface = wl_compositor_create_surface(bar->compositor)); - output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - bar->layer_shell, output->surface, output->output, - 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); - render_frame(bar, output); + struct config_output *coutput; + wl_list_for_each(coutput, &bar->config->outputs, link) { + if (coutput->index != output->index) { + continue; + } + assert(output->surface = wl_compositor_create_surface( + bar->compositor)); + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + bar->layer_shell, output->surface, output->output, + 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); + render_frame(bar, output); + break; + } } } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index cef784d0..d3ee170c 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 500 +#include #include #include #include @@ -174,6 +175,7 @@ static void ipc_parse_config( struct config_output *coutput = calloc( 1, sizeof(struct config_output)); coutput->name = strdup(name); + coutput->index = SIZE_MAX; wl_list_insert(&config->outputs, &coutput->link); } } @@ -185,12 +187,47 @@ static void ipc_parse_config( json_object_put(bar_config); } +static void ipc_get_outputs(struct swaybar *bar) { + uint32_t len = 0; + char *res = ipc_single_command(bar->ipc_socketfd, + IPC_GET_OUTPUTS, NULL, &len); + json_object *outputs = json_tokener_parse(res); + for (size_t i = 0; i < json_object_array_length(outputs); ++i) { + json_object *output = json_object_array_get_idx(outputs, i); + json_object *output_name, *output_active; + json_object_object_get_ex(output, "name", &output_name); + json_object_object_get_ex(output, "active", &output_active); + const char *name = json_object_get_string(output_name); + bool active = json_object_get_boolean(output_active); + if (!active) { + continue; + } + if (wl_list_empty(&bar->config->outputs)) { + struct config_output *coutput = calloc( + 1, sizeof(struct config_output)); + coutput->name = strdup(name); + coutput->index = i; + wl_list_insert(&bar->config->outputs, &coutput->link); + } else { + struct config_output *coutput; + wl_list_for_each(coutput, &bar->config->outputs, link) { + if (strcmp(name, coutput->name) == 0) { + coutput->index = i; + break; + } + } + } + } + free(res); +} + void ipc_get_config(struct swaybar *bar, const char *bar_id) { uint32_t len = strlen(bar_id); char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); ipc_parse_config(bar->config, res); free(res); + ipc_get_outputs(bar); } void handle_ipc_event(struct swaybar *bar) { -- cgit v1.2.3 From 3399ad9840f0d3d42b377f4404115d887f65e18a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 00:21:05 -0400 Subject: Round up workspaces on each output --- include/swaybar/bar.h | 16 +++++++++++-- include/swaybar/ipc.h | 3 ++- swaybar/bar.c | 9 ++++++-- swaybar/ipc.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 85 insertions(+), 6 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 6e1ab66d..c89aa61c 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -30,6 +30,8 @@ struct swaybar_output { struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; + struct wl_list workspaces; + char *name; size_t index; bool focused; @@ -39,9 +41,19 @@ struct swaybar_output { struct pool_buffer *current_buffer; }; +struct swaybar_workspace { + struct wl_list link; + int num; + char *name; + bool focused; + bool visible; + bool urgent; +}; + +// TODO: Rename stuff to match wlroots conventions (init/create/etc) void bar_setup(struct swaybar *bar, - const char *socket_path, - const char *bar_id); + const char *socket_path, + const char *bar_id); void bar_run(struct swaybar *bar); void bar_teardown(struct swaybar *bar); diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 7f71a506..f3881bd0 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -2,7 +2,8 @@ #define _SWAYBAR_IPC_H #include "swaybar/bar.h" -void ipc_get_config(struct swaybar *bar, const char *bar_id); +void ipc_initialize(struct swaybar *bar, const char *bar_id); void handle_ipc_event(struct swaybar *bar); +void ipc_get_workspaces(struct swaybar *bar); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index a6e3b780..68dea408 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -72,6 +72,7 @@ static void handle_global(void *data, struct wl_registry *registry, output->output = wl_registry_bind(registry, name, &wl_output_interface, 1); output->index = index++; + wl_list_init(&output->workspaces); wl_list_insert(&bar->outputs, &output->link); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( @@ -96,7 +97,7 @@ void bar_setup(struct swaybar *bar, bar->ipc_socketfd = ipc_open_socket(socket_path); bar->ipc_event_socketfd = ipc_open_socket(socket_path); - ipc_get_config(bar, bar_id); + ipc_initialize(bar, bar_id); assert(bar->display = wl_display_connect(NULL)); @@ -113,6 +114,7 @@ void bar_setup(struct swaybar *bar, if (coutput->index != output->index) { continue; } + output->name = strdup(coutput->name); assert(output->surface = wl_compositor_create_surface( bar->compositor)); output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( @@ -123,10 +125,13 @@ void bar_setup(struct swaybar *bar, &layer_surface_listener, output); zwlr_layer_surface_v1_set_anchor(output->layer_surface, bar->config->position); - render_frame(bar, output); break; } } + ipc_get_workspaces(bar); + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } } static void display_in(int fd, short mask, void *_bar) { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index d3ee170c..6b832070 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -187,6 +187,65 @@ static void ipc_parse_config( json_object_put(bar_config); } +static void free_workspaces(struct wl_list *list) { + struct swaybar_workspace *ws, *tmp; + wl_list_for_each_safe(ws, tmp, list, link) { + wl_list_remove(&ws->link); + free(ws->name); + free(ws); + } +} + +void ipc_get_workspaces(struct swaybar *bar) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + free_workspaces(&output->workspaces); + } + uint32_t len = 0; + char *res = ipc_single_command(bar->ipc_socketfd, + IPC_GET_WORKSPACES, NULL, &len); + json_object *results = json_tokener_parse(res); + if (!results) { + free(res); + return; + } + size_t length = json_object_array_length(results); + json_object *ws_json; + json_object *num, *name, *visible, *focused, *out, *urgent; + for (size_t i = 0; i < length; ++i) { + ws_json = json_object_array_get_idx(results, i); + + json_object_object_get_ex(ws_json, "num", &num); + json_object_object_get_ex(ws_json, "name", &name); + json_object_object_get_ex(ws_json, "visible", &visible); + json_object_object_get_ex(ws_json, "focused", &focused); + json_object_object_get_ex(ws_json, "output", &out); + json_object_object_get_ex(ws_json, "urgent", &urgent); + + wl_list_for_each(output, &bar->outputs, link) { + const char *ws_output = json_object_get_string(out); + if (strcmp(ws_output, output->name) == 0) { + struct swaybar_workspace *ws = + calloc(1, sizeof(struct swaybar_workspace)); + ws->num = json_object_get_int(num); + ws->name = strdup(json_object_get_string(name)); + ws->visible = json_object_get_boolean(visible); + ws->focused = json_object_get_boolean(focused); + if (ws->focused) { + if (bar->focused_output) { + bar->focused_output->focused = false; + } + bar->focused_output = output; + output->focused = true; + } + ws->urgent = json_object_get_boolean(urgent); + wl_list_insert(&output->workspaces, &ws->link); + } + } + } + free(res); +} + static void ipc_get_outputs(struct swaybar *bar) { uint32_t len = 0; char *res = ipc_single_command(bar->ipc_socketfd, @@ -218,16 +277,18 @@ static void ipc_get_outputs(struct swaybar *bar) { } } } + json_object_put(outputs); free(res); } -void ipc_get_config(struct swaybar *bar, const char *bar_id) { +void ipc_initialize(struct swaybar *bar, const char *bar_id) { uint32_t len = strlen(bar_id); char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); ipc_parse_config(bar->config, res); free(res); ipc_get_outputs(bar); + // TODO: subscribe to stuff } void handle_ipc_event(struct swaybar *bar) { -- cgit v1.2.3 From 86ba0fc15d7615b09f0279616d538af5c23bc551 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 10:38:17 -0400 Subject: Re-render bar on IPC updates --- include/swaybar/ipc.h | 3 ++- swaybar/bar.c | 8 +++++++- swaybar/ipc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 4 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index f3881bd0..278baef0 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -1,9 +1,10 @@ #ifndef _SWAYBAR_IPC_H #define _SWAYBAR_IPC_H +#include #include "swaybar/bar.h" void ipc_initialize(struct swaybar *bar, const char *bar_id); -void handle_ipc_event(struct swaybar *bar); +bool handle_ipc_event(struct swaybar *bar); void ipc_get_workspaces(struct swaybar *bar); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index 68dea408..90fd5ad4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -143,11 +143,17 @@ static void display_in(int fd, short mask, void *_bar) { static void ipc_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; - handle_ipc_event(bar); + if (handle_ipc_event(bar)) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } + } } 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); while (1) { event_loop_poll(); } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 6b832070..75f17953 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "swaybar/config.h" #include "swaybar/ipc.h" #include "ipc-client.h" @@ -288,10 +289,51 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id) { ipc_parse_config(bar->config, res); free(res); ipc_get_outputs(bar); - // TODO: subscribe to stuff + + const char *subscribe = "[ \"workspace\", \"mode\" ]"; + len = strlen(subscribe); + free(ipc_single_command(bar->ipc_event_socketfd, + IPC_SUBSCRIBE, subscribe, &len)); } -void handle_ipc_event(struct swaybar *bar) { +bool handle_ipc_event(struct swaybar *bar) { struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); + if (!resp) { + return false; + } + switch (resp->type) { + case IPC_EVENT_WORKSPACE: + ipc_get_workspaces(bar); + break; + case IPC_EVENT_MODE: { + json_object *result = json_tokener_parse(resp->payload); + if (!result) { + free_ipc_response(resp); + wlr_log(L_ERROR, "failed to parse payload as json"); + return false; + } + json_object *json_change; + if (json_object_object_get_ex(result, "change", &json_change)) { + const char *change = json_object_get_string(json_change); + free(bar->config->mode); + if (strcmp(change, "default") == 0) { + bar->config->mode = NULL; + } else { + bar->config->mode = strdup(change); + } + } else { + wlr_log(L_ERROR, "failed to parse response"); + json_object_put(result); + free_ipc_response(resp); + return false; + } + json_object_put(result); + break; + } + default: + free_ipc_response(resp); + return false; + } free_ipc_response(resp); + return true; } -- cgit v1.2.3 From 0d0ab7c5ce148bce841fa0682d04bc7b6c21b902 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 15:16:12 -0400 Subject: Implement status line Does not yet support i3bar json protocol --- include/swaybar/bar.h | 1 + include/swaybar/status_line.h | 65 ++++++++++-------------------------- swaybar/bar.c | 26 ++++++++++++--- swaybar/config.c | 1 + swaybar/meson.build | 1 + swaybar/render.c | 56 +++++++++++++++++++++++++++++++ swaybar/status_line.c | 78 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 176 insertions(+), 52 deletions(-) create mode 100644 swaybar/status_line.c (limited to 'swaybar/bar.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index c89aa61c..1bf2ea2d 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -16,6 +16,7 @@ struct swaybar { struct swaybar_config *config; struct swaybar_output *focused_output; + struct status_line *status; int ipc_event_socketfd; int ipc_socketfd; diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 0664ddee..6c595df0 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -1,61 +1,30 @@ #ifndef _SWAYBAR_STATUS_LINE_H #define _SWAYBAR_STATUS_LINE_H - #include +#include #include - -#include "list.h" #include "bar.h" -typedef enum {UNDEF, TEXT, I3BAR} command_protocol; +enum status_protocol { + PROTOCOL_UNDEF, + PROTOCOL_TEXT, + PROTOCOL_I3BAR, +}; struct status_line { - list_t *block_line; - const char *text_line; - command_protocol protocol; - bool click_events; -}; + pid_t pid; + int read_fd, write_fd; + FILE *read, *write; -struct status_block { - char *full_text, *short_text, *align; - bool urgent; - uint32_t color; - int min_width; - char *name, *instance; - bool separator; - int separator_block_width; - bool markup; - // Airblader features - uint32_t background; - uint32_t border; - int border_top; - int border_bottom; - int border_left; - int border_right; + enum status_protocol protocol; + const char *text; - // Set during rendering - int x; - int width; + char *buffer; + size_t buffer_size; }; -/** - * Initialize status line struct. - */ -struct status_line *init_status_line(); - -/** - * handle status line activity. - */ -bool handle_status_line(struct bar *bar); - -/** - * Handle mouse clicks. - */ -bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button); - -/** - * Free status line struct. - */ -void free_status_line(struct status_line *line); +struct status_line *status_line_init(char *cmd); +void status_line_free(struct status_line *status); +bool handle_status_readable(struct status_line *status); -#endif /* _SWAYBAR_STATUS_LINE_H */ +#endif diff --git a/swaybar/bar.c b/swaybar/bar.c index 90fd5ad4..72c4be8f 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -13,6 +13,7 @@ #include "swaybar/render.h" #include "swaybar/config.h" #include "swaybar/event_loop.h" +#include "swaybar/status_line.h" #include "swaybar/bar.h" #include "swaybar/ipc.h" #include "ipc-client.h" @@ -98,6 +99,9 @@ void bar_setup(struct swaybar *bar, bar->ipc_socketfd = ipc_open_socket(socket_path); bar->ipc_event_socketfd = ipc_open_socket(socket_path); ipc_initialize(bar, bar_id); + if (bar->config->status_command) { + bar->status = status_line_init(bar->config->status_command); + } assert(bar->display = wl_display_connect(NULL)); @@ -134,6 +138,13 @@ void bar_setup(struct swaybar *bar, } } +static void render_all_frames(struct swaybar *bar) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } +} + static void display_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; if (wl_display_dispatch(bar->display) == -1) { @@ -144,16 +155,23 @@ static void display_in(int fd, short mask, void *_bar) { static void ipc_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; if (handle_ipc_event(bar)) { - struct swaybar_output *output; - wl_list_for_each(output, &bar->outputs, link) { - render_frame(bar, output); - } + render_all_frames(bar); + } +} + +static void status_in(int fd, short mask, void *_bar) { + struct swaybar *bar = (struct swaybar *)_bar; + if (handle_status_readable(bar->status)) { + render_all_frames(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); + if (bar->status) { + add_event(bar->status->read_fd, POLLIN, status_in, bar); + } while (1) { event_loop_poll(); } diff --git a/swaybar/config.c b/swaybar/config.c index 802d0779..9169ad27 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -43,6 +43,7 @@ struct swaybar_config *init_config() { config->colors.background = 0x000000FF; config->colors.focused_background = 0x000000FF; config->colors.statusline = 0xFFFFFFFF; + config->colors.focused_statusline = 0xFFFFFFFF; config->colors.separator = 0x666666FF; config->colors.focused_workspace.border = 0x4C7899FF; diff --git a/swaybar/meson.build b/swaybar/meson.build index 6dc7c564..d15e8b5c 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -7,6 +7,7 @@ executable( 'ipc.c', 'main.c', 'render.c', + 'status_line.c', ], include_directories: [sway_inc], dependencies: [ diff --git a/swaybar/render.c b/swaybar/render.c index f797873c..ec1239a1 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -9,12 +9,59 @@ #include "swaybar/bar.h" #include "swaybar/config.h" #include "swaybar/render.h" +#include "swaybar/status_line.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" static const int ws_horizontal_padding = 5; static const double ws_vertical_padding = 1.5; static const double border_width = 1; +static uint32_t render_status_line_text(cairo_t *cairo, + struct swaybar_config *config, struct status_line *status, + bool focused, uint32_t width, uint32_t height) { + if (!status->text) { + return 0; + } + //wlr_log(L_DEBUG, "focused %d", focused); + cairo_set_source_u32(cairo, focused ? + config->colors.focused_statusline : config->colors.statusline); + static const int margin = 3; + int text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, config->pango_markup, "%s", status->text); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + height = ideal_height; + } + double text_y = height / 2.0 - text_height / 2.0; + cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, config->pango_markup, + "%s", status->text); + return ideal_height; +} + +static uint32_t render_status_line_i3bar(cairo_t *cairo, + struct swaybar_config *config, struct status_line *status, + bool focused, uint32_t width, uint32_t height) { + // TODO + return 0; +} + +static uint32_t render_status_line(cairo_t *cairo, + struct swaybar_config *config, struct status_line *status, + bool focused, uint32_t width, uint32_t height) { + switch (status->protocol) { + case PROTOCOL_TEXT: + return render_status_line_text(cairo, + config, status, focused, width, height); + case PROTOCOL_I3BAR: + return render_status_line_i3bar(cairo, + config, status, focused, width, height); + default: + return 0; + } +} + static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_config *config, const char *mode, double x, uint32_t height) { @@ -148,6 +195,11 @@ static uint32_t render_to_cairo(cairo_t *cairo, cairo, config, config->mode, x, output->height); max_height = h > max_height ? h : max_height; } + if (bar->status) { + uint32_t h = render_status_line(cairo, config, bar->status, + output->focused, output->width, output->height); + max_height = h > max_height ? h : max_height; + } return max_height > output->height ? max_height : output->height; } @@ -157,6 +209,10 @@ void render_frame(struct swaybar *bar, cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); + cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + cairo_paint(cairo); + cairo_restore(cairo); uint32_t height = render_to_cairo(cairo, bar, output); if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) { height = bar->config->height; diff --git a/swaybar/status_line.c b/swaybar/status_line.c new file mode 100644 index 00000000..ff668c9c --- /dev/null +++ b/swaybar/status_line.c @@ -0,0 +1,78 @@ +#define _POSIX_C_SOURCE +#include +#include +#include +#include +#include +#include +#include "swaybar/config.h" +#include "swaybar/status_line.h" +#include "readline.h" + +bool handle_status_readable(struct status_line *status) { + char *line = read_line_buffer(status->read, + status->buffer, status->buffer_size); + switch (status->protocol) { + case PROTOCOL_I3BAR: + // TODO + break; + case PROTOCOL_TEXT: + status->text = line; + return true; + case PROTOCOL_UNDEF: + if (!line) { + return false; + } + if (line[0] == '{') { + // TODO: JSON + } else { + status->text = line; + status->protocol = PROTOCOL_TEXT; + } + return false; + } + return false; +} + +struct status_line *status_line_init(char *cmd) { + struct status_line *status = calloc(1, sizeof(struct status_line)); + status->buffer_size = 4096; + status->buffer = malloc(status->buffer_size); + + int pipe_read_fd[2]; + int pipe_write_fd[2]; + if (pipe(pipe_read_fd) != 0 || pipe(pipe_write_fd) != 0) { + wlr_log(L_ERROR, "Unable to create pipes for status_command fork"); + exit(1); + } + + status->pid = fork(); + if (status->pid == 0) { + dup2(pipe_read_fd[1], STDOUT_FILENO); + close(pipe_read_fd[0]); + close(pipe_read_fd[1]); + + dup2(pipe_write_fd[0], STDIN_FILENO); + close(pipe_write_fd[0]); + close(pipe_write_fd[1]); + + char *const _cmd[] = { "sh", "-c", cmd, NULL, }; + execvp(_cmd[0], _cmd); + exit(1); + } + + close(pipe_read_fd[1]); + status->read_fd = pipe_read_fd[0]; + fcntl(status->read_fd, F_SETFL, O_NONBLOCK); + close(pipe_write_fd[0]); + status->write_fd = pipe_write_fd[1]; + fcntl(status->write_fd, F_SETFL, O_NONBLOCK); + + status->read = fdopen(status->read_fd, "r"); + status->write = fdopen(status->write_fd, "w"); + return status; +} + +void status_line_free(struct status_line *line) { + free(line); +} -- cgit v1.2.3 From 0464a9910da2b99abea0ab202e179d66260a893b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 15:19:42 -0400 Subject: Clean up status line on exit --- swaybar/bar.c | 5 +++++ swaybar/status_line.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index 72c4be8f..44f4ee31 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -191,4 +191,9 @@ void bar_teardown(struct swaybar *bar) { if (bar->config) { free_config(bar->config); } + close(bar->ipc_event_socketfd); + close(bar->ipc_socketfd); + if (bar->status) { + status_line_free(bar->status); + } } diff --git a/swaybar/status_line.c b/swaybar/status_line.c index ff668c9c..5b131aee 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -73,6 +73,8 @@ struct status_line *status_line_init(char *cmd) { return status; } -void status_line_free(struct status_line *line) { - free(line); +void status_line_free(struct status_line *status) { + close(status->read_fd); + close(status->write_fd); + free(status); } -- cgit v1.2.3 From da6e48520bad9718a7c4ddf0591474d54736c1c2 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 15:36:52 -0400 Subject: Tear down bar when display exits --- swaybar/bar.c | 3 ++- swaybar/render.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index 44f4ee31..afbce7cc 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -148,7 +148,8 @@ static void render_all_frames(struct swaybar *bar) { static void display_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; if (wl_display_dispatch(bar->display) == -1) { - wlr_log(L_ERROR, "failed to dispatch wl: %d", errno); + bar_teardown(bar); + exit(0); } } diff --git a/swaybar/render.c b/swaybar/render.c index ec1239a1..a5834f4b 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -22,7 +22,6 @@ static uint32_t render_status_line_text(cairo_t *cairo, if (!status->text) { return 0; } - //wlr_log(L_DEBUG, "focused %d", focused); cairo_set_source_u32(cairo, focused ? config->colors.focused_statusline : config->colors.statusline); static const int margin = 3; -- cgit v1.2.3 From 6fe66d0e6c9a20a9dbe2d464671ff19ea5b0387c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:25:25 -0400 Subject: Fix layer_surface_closed --- swaybar/bar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index afbce7cc..82404d33 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -46,7 +46,7 @@ static void layer_surface_configure(void *data, static void layer_surface_closed(void *_output, struct zwlr_layer_surface_v1 *surface) { // TODO: Deal with hotplugging - struct swaybar_output *output = output; + struct swaybar_output *output = _output; zwlr_layer_surface_v1_destroy(output->layer_surface); wl_surface_destroy(output->surface); } -- cgit v1.2.3 From 095ac319214d6e51df223950292bfca5ddaf591a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 22:32:17 -0400 Subject: Use render_all_frames from bar_setup --- swaybar/bar.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index 82404d33..0fc41517 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -91,6 +91,13 @@ static const struct wl_registry_listener registry_listener = { .global_remove = handle_global_remove, }; +static void render_all_frames(struct swaybar *bar) { + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + render_frame(bar, output); + } +} + void bar_setup(struct swaybar *bar, const char *socket_path, const char *bar_id) { bar_init(bar); @@ -133,16 +140,7 @@ void bar_setup(struct swaybar *bar, } } ipc_get_workspaces(bar); - wl_list_for_each(output, &bar->outputs, link) { - render_frame(bar, output); - } -} - -static void render_all_frames(struct swaybar *bar) { - struct swaybar_output *output; - wl_list_for_each(output, &bar->outputs, link) { - render_frame(bar, output); - } + render_all_frames(bar); } static void display_in(int fd, short mask, void *_bar) { -- cgit v1.2.3 From 8d1425bde9e7f17a5a9e6bce73dffcf296dad6a1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 21:38:28 -0400 Subject: Initialize seat pointer in swaybar --- include/swaybar/bar.h | 10 +++++ meson.build | 1 + swaybar/bar.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ swaybar/meson.build | 4 +- 4 files changed, 118 insertions(+), 2 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 1bf2ea2d..0768a683 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -8,14 +8,24 @@ struct swaybar_config; struct swaybar_output; struct swaybar_workspace; +struct swaybar_pointer { + struct wl_pointer *pointer; + struct wl_cursor_theme *cursor_theme; + struct wl_cursor_image *cursor_image; + struct wl_surface *cursor_surface; + struct swaybar_output *current; +}; + struct swaybar { struct wl_display *display; struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; struct wl_shm *shm; + struct wl_seat *seat; struct swaybar_config *config; struct swaybar_output *focused_output; + struct swaybar_pointer pointer; struct status_line *status; int ipc_event_socketfd; diff --git a/meson.build b/meson.build index 49824b30..01788fd9 100644 --- a/meson.build +++ b/meson.build @@ -24,6 +24,7 @@ pcre = dependency('libpcre') wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots']) wayland_server = dependency('wayland-server') wayland_client = dependency('wayland-client') +wayland_cursor = dependency('wayland-cursor') wayland_egl = dependency('wayland-egl') wayland_protos = dependency('wayland-protocols') xkbcommon = dependency('xkbcommon') diff --git a/swaybar/bar.c b/swaybar/bar.c index 0fc41517..e7b8b2ca 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -9,7 +9,13 @@ #include #include #include +#include #include +#ifdef __FreeBSD__ +#include +#else +#include +#endif #include "swaybar/render.h" #include "swaybar/config.h" #include "swaybar/event_loop.h" @@ -56,12 +62,102 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { .closed = layer_surface_closed, }; +static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + struct swaybar *bar = data; + struct swaybar_pointer *pointer = &bar->pointer; + wl_surface_attach(pointer->cursor_surface, + wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); + wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, + pointer->cursor_image->hotspot_x, + pointer->cursor_image->hotspot_y); + wl_surface_commit(pointer->cursor_surface); +} + +static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { + // Who cares +} + +static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { + wlr_log(L_DEBUG, "motion"); + // TODO +} + +static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + wlr_log(L_DEBUG, "button"); + // TODO +} + +static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { + wlr_log(L_DEBUG, "axis"); + // TODO +} + +static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + // Who cares +} + +static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) { + // Who cares +} + +static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { + // Who cares +} + +static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) { + // Who cares +} + +struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, + .leave = wl_pointer_leave, + .motion = wl_pointer_motion, + .button = wl_pointer_button, + .axis = wl_pointer_axis, + .frame = wl_pointer_frame, + .axis_source = wl_pointer_axis_source, + .axis_stop = wl_pointer_axis_stop, + .axis_discrete = wl_pointer_axis_discrete, +}; + +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { + struct swaybar *bar = data; + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + bar->pointer.pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(bar->pointer.pointer, &pointer_listener, bar); + } +} + +static void seat_handle_name(void *data, struct wl_seat *wl_seat, + const char *name) { + // Who cares +} + +const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct swaybar *bar = data; if (strcmp(interface, wl_compositor_interface.name) == 0) { bar->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + bar->seat = wl_registry_bind(registry, name, + &wl_seat_interface, 1); + wl_seat_add_listener(bar->seat, &seat_listener, bar); } else if (strcmp(interface, wl_shm_interface.name) == 0) { bar->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); @@ -116,6 +212,15 @@ void bar_setup(struct swaybar *bar, wl_registry_add_listener(registry, ®istry_listener, bar); wl_display_roundtrip(bar->display); assert(bar->compositor && bar->layer_shell && bar->shm); + struct swaybar_pointer *pointer = &bar->pointer; + + assert(pointer->cursor_theme = wl_cursor_theme_load(NULL, 16, bar->shm)); + struct wl_cursor *cursor; + assert(cursor = wl_cursor_theme_get_cursor( + pointer->cursor_theme, "left_ptr")); + pointer->cursor_image = cursor->images[0]; + assert(pointer->cursor_surface = + wl_compositor_create_surface(bar->compositor)); // TODO: we might not necessarily be meant to do all of the outputs struct swaybar_output *output; diff --git a/swaybar/meson.build b/swaybar/meson.build index d15e8b5c..bf6f6d7a 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -1,6 +1,5 @@ executable( - 'swaybar', - [ + 'swaybar', [ 'bar.c', 'config.c', 'event_loop.c', @@ -20,6 +19,7 @@ executable( pangocairo, rt, wayland_client, + wayland_cursor, wlroots, ], link_with: [lib_sway_common, lib_sway_client], -- cgit v1.2.3 From ae14dfc7ae70f16a31a10f4ff2395d4ac432308d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 22:02:55 -0400 Subject: Implement scroll wheel workspace switching --- include/swaybar/ipc.h | 1 + swaybar/bar.c | 44 ++++++++++++++++++++++++++++++++++++++++---- swaybar/ipc.c | 8 ++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 278baef0..6ea7c4d6 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -6,5 +6,6 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id); bool handle_ipc_event(struct swaybar *bar); void ipc_get_workspaces(struct swaybar *bar); +void ipc_send_workspace_command(struct swaybar *bar, const char *ws); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index e7b8b2ca..5679a892 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -24,6 +24,7 @@ #include "swaybar/ipc.h" #include "ipc-client.h" #include "list.h" +#include "log.h" #include "pango.h" #include "pool-buffer.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -67,6 +68,13 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct swaybar *bar = data; struct swaybar_pointer *pointer = &bar->pointer; + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + if (output->surface == surface) { + pointer->current = output; + break; + } + } wl_surface_attach(pointer->cursor_surface, wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, @@ -77,12 +85,12 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { - // Who cares + struct swaybar *bar = data; + bar->pointer.current = NULL; } static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - wlr_log(L_DEBUG, "motion"); // TODO } @@ -94,8 +102,36 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { - wlr_log(L_DEBUG, "axis"); - // TODO + struct swaybar *bar = data; + struct swaybar_output *output = bar->pointer.current; + if (!output) { + return; + } + double amt = wl_fixed_to_double(value); + if (!bar->config->wrap_scroll) { + int i = 0; + struct swaybar_workspace *ws = NULL; + wl_list_for_each(ws, &output->workspaces, link) { + if (ws->focused) { + break; + } + ++i; + } + int len = wl_list_length(&output->workspaces); + if (!sway_assert(i != len, "axis with null workspace")) { + return; + } + if (i == 0 && amt > 0) { + return; // Do not wrap + } + if (i == len - 1 && amt < 0) { + return; // Do not wrap + } + } + + const char *workspace_name = + amt < 0 ? "prev_on_output" : "next_on_output"; + ipc_send_workspace_command(bar, workspace_name); } static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 326f25cc..64583df0 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -8,6 +8,14 @@ #include "swaybar/ipc.h" #include "ipc-client.h" +void ipc_send_workspace_command(struct swaybar *bar, const char *ws) { + const char *fmt = "workspace \"%s\""; + uint32_t size = snprintf(NULL, 0, fmt, ws); + char command[size]; + snprintf(command, size, fmt, ws); + ipc_single_command(bar->ipc_socketfd, IPC_COMMAND, command, &size); +} + char *parse_font(const char *font) { char *new_font = NULL; if (strncmp("pango:", font, 6) == 0) { -- cgit v1.2.3 From 2a5108a2786383cf5c3bcefd653605c916193837 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 22:42:59 -0400 Subject: Implement workspace switch on click --- include/swaybar/bar.h | 13 +++++++++++-- swaybar/bar.c | 34 ++++++++++++++++++++++++---------- swaybar/render.c | 39 ++++++++++++++++++++++++++++++++------- 3 files changed, 67 insertions(+), 19 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 0768a683..74292519 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -2,7 +2,6 @@ #define _SWAYBAR_BAR_H #include #include "pool-buffer.h" -#include "list.h" struct swaybar_config; struct swaybar_output; @@ -14,6 +13,16 @@ struct swaybar_pointer { struct wl_cursor_image *cursor_image; struct wl_surface *cursor_surface; struct swaybar_output *current; + int x, y; +}; + +struct swaybar_hotspot { + struct wl_list link; + int x, y, width, height; + void (*callback)(struct swaybar_output *output, + int x, int y, uint32_t button, void *data); + void (*destroy)(void *data); + void *data; }; struct swaybar { @@ -42,6 +51,7 @@ struct swaybar_output { struct zwlr_layer_surface_v1 *layer_surface; struct wl_list workspaces; + struct wl_list hotspots; char *name; size_t index; @@ -61,7 +71,6 @@ struct swaybar_workspace { bool urgent; }; -// TODO: Rename stuff to match wlroots conventions (init/create/etc) void bar_setup(struct swaybar *bar, const char *socket_path, const char *bar_id); diff --git a/swaybar/bar.c b/swaybar/bar.c index 5679a892..f743236c 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -34,12 +34,6 @@ static void bar_init(struct swaybar *bar) { wl_list_init(&bar->outputs); } -struct swaybar_output *new_output(const char *name) { - struct swaybar_output *output = malloc(sizeof(struct swaybar_output)); - output->name = strdup(name); - return output; -} - static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height) { @@ -91,20 +85,39 @@ static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - // TODO + struct swaybar *bar = data; + bar->pointer.x = wl_fixed_to_int(surface_x); + bar->pointer.y = wl_fixed_to_int(surface_y); } static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { - wlr_log(L_DEBUG, "button"); - // TODO + struct swaybar *bar = data; + struct swaybar_pointer *pointer = &bar->pointer; + struct swaybar_output *output = pointer->current; + if (!sway_assert(output, "button with no active output")) { + return; + } + if (state != WL_POINTER_BUTTON_STATE_PRESSED) { + return; + } + struct swaybar_hotspot *hotspot; + wl_list_for_each(hotspot, &output->hotspots, link) { + if (pointer->x >= hotspot->x + && pointer->y >= hotspot->y + && pointer->x < hotspot->x + hotspot->width + && pointer->y < hotspot->y + hotspot->height) { + hotspot->callback(output, pointer->x, pointer->y, + button, hotspot->data); + } + } } static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { struct swaybar *bar = data; struct swaybar_output *output = bar->pointer.current; - if (!output) { + if (!sway_assert(output, "axis with no active output")) { return; } double amt = wl_fixed_to_double(value); @@ -206,6 +219,7 @@ static void handle_global(void *data, struct wl_registry *registry, &wl_output_interface, 1); output->index = index++; wl_list_init(&output->workspaces); + wl_list_init(&output->hotspots); wl_list_insert(&bar->outputs, &output->link); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( diff --git a/swaybar/render.c b/swaybar/render.c index 3d9ef66b..c2358724 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -8,6 +9,7 @@ #include "pool-buffer.h" #include "swaybar/bar.h" #include "swaybar/config.h" +#include "swaybar/ipc.h" #include "swaybar/render.h" #include "swaybar/status_line.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -108,9 +110,14 @@ static const char *strip_workspace_number(const char *ws_name) { return ws_name; } +static void workspace_hotspot_callback(struct swaybar_output *output, + int x, int y, uint32_t button, void *data) { + ipc_send_workspace_command(output->bar, (const char *)data); +} + static uint32_t render_workspace_button(cairo_t *cairo, - struct swaybar_config *config, struct swaybar_workspace *ws, - double *x, uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + struct swaybar_workspace *ws, double *x, uint32_t height) { const char *name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); @@ -156,8 +163,18 @@ static uint32_t render_workspace_button(cairo_t *cairo, cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); pango_printf(cairo, config->font, 1, true, "%s", name); + struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); + hotspot->x = *x; + hotspot->y = 0; + hotspot->height = height; + hotspot->width = width; + hotspot->callback = workspace_hotspot_callback; + hotspot->destroy = free; + hotspot->data = strdup(name); + wl_list_insert(&output->hotspots, &hotspot->link); + *x += width; - return ideal_height; + return height; } static uint32_t render_to_cairo(cairo_t *cairo, @@ -184,8 +201,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, if (config->workspace_buttons) { struct swaybar_workspace *ws; wl_list_for_each_reverse(ws, &output->workspaces, link) { - uint32_t h = render_workspace_button( - cairo, config, ws, &x, output->height); + uint32_t h = render_workspace_button(cairo, + output, config, ws, &x, output->height); max_height = h > max_height ? h : max_height; } } @@ -203,8 +220,16 @@ static uint32_t render_to_cairo(cairo_t *cairo, return max_height > output->height ? max_height : output->height; } -void render_frame(struct swaybar *bar, - struct swaybar_output *output) { +void render_frame(struct swaybar *bar, struct swaybar_output *output) { + struct swaybar_hotspot *hotspot, *tmp; + wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) { + if (hotspot->destroy) { + hotspot->destroy(hotspot->data); + } + wl_list_remove(&hotspot->link); + free(hotspot); + } + cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); -- cgit v1.2.3 From 333dbcbe72b6af95573e374b66ad6ab63f274299 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 14:39:18 -0400 Subject: Render i3bar blocks --- include/swaybar/ipc.h | 2 +- include/swaybar/status_line.h | 6 +- swaybar/bar.c | 4 +- swaybar/i3bar.c | 120 ++++++++++++++++++++++-- swaybar/ipc.c | 2 +- swaybar/render.c | 209 +++++++++++++++++++++++++++++++++++++++--- swaybar/status_line.c | 5 +- 7 files changed, 314 insertions(+), 34 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 6ea7c4d6..a1696bcf 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -4,7 +4,7 @@ #include "swaybar/bar.h" void ipc_initialize(struct swaybar *bar, const char *bar_id); -bool handle_ipc_event(struct swaybar *bar); +bool handle_ipc_readable(struct swaybar *bar); void ipc_get_workspaces(struct swaybar *bar); void ipc_send_workspace_command(struct swaybar *bar, const char *ws); diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 3b93e28f..038985a3 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -38,7 +38,7 @@ struct i3bar_block { struct wl_list link; char *full_text, *short_text, *align; bool urgent; - uint32_t color; + uint32_t *color; int min_width; char *name, *instance; bool separator; @@ -68,8 +68,8 @@ struct status_line { struct status_line *status_line_init(char *cmd); void status_line_free(struct status_line *status); -bool handle_status_readable(struct status_line *status); -int i3bar_readable(struct status_line *status); +bool status_handle_readable(struct status_line *status); +bool i3bar_handle_readable(struct status_line *status); void status_error(struct status_line *status, const char *text); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index f743236c..fb417095 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -308,14 +308,14 @@ static void display_in(int fd, short mask, void *_bar) { static void ipc_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; - if (handle_ipc_event(bar)) { + if (handle_ipc_readable(bar)) { render_all_frames(bar); } } static void status_in(int fd, short mask, void *_bar) { struct swaybar *bar = (struct swaybar *)_bar; - if (handle_status_readable(bar->status)) { + if (status_handle_readable(bar->status)) { render_all_frames(bar); } } diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 5be348b2..41b71164 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -5,11 +7,109 @@ #include "swaybar/config.h" #include "swaybar/status_line.h" -static void i3bar_parse_json(struct status_line *status, const char *text) { - wlr_log(L_DEBUG, "got json: %s", text); +static void i3bar_block_free(struct i3bar_block *block) { + if (!block) { + return; + } + wl_list_remove(&block->link); + free(block->full_text); + free(block->short_text); + free(block->align); + free(block->name); + free(block->instance); + free(block->color); +} + +static bool i3bar_parse_json(struct status_line *status, const char *text) { + struct i3bar_block *block, *tmp; + wl_list_for_each_safe(block, tmp, &status->blocks, link) { + i3bar_block_free(block); + } + json_object *results = json_tokener_parse(text); + if (!results) { + status_error(status, "[failed to parse i3bar json]"); + return false; + } + if (json_object_array_length(results) < 1) { + return true; + } + for (size_t i = 0; i < json_object_array_length(results); ++i) { + json_object *full_text, *short_text, *color, *min_width, *align, *urgent; + json_object *name, *instance, *separator, *separator_block_width; + json_object *background, *border, *border_top, *border_bottom; + json_object *border_left, *border_right, *markup; + json_object *json = json_object_array_get_idx(results, i); + if (!json) { + continue; + } + json_object_object_get_ex(json, "full_text", &full_text); + json_object_object_get_ex(json, "short_text", &short_text); + json_object_object_get_ex(json, "color", &color); + json_object_object_get_ex(json, "min_width", &min_width); + json_object_object_get_ex(json, "align", &align); + json_object_object_get_ex(json, "urgent", &urgent); + json_object_object_get_ex(json, "name", &name); + json_object_object_get_ex(json, "instance", &instance); + json_object_object_get_ex(json, "markup", &markup); + json_object_object_get_ex(json, "separator", &separator); + json_object_object_get_ex(json, "separator_block_width", &separator_block_width); + json_object_object_get_ex(json, "background", &background); + json_object_object_get_ex(json, "border", &border); + json_object_object_get_ex(json, "border_top", &border_top); + json_object_object_get_ex(json, "border_bottom", &border_bottom); + json_object_object_get_ex(json, "border_left", &border_left); + json_object_object_get_ex(json, "border_right", &border_right); + + struct i3bar_block *block = calloc(1, sizeof(struct i3bar_block)); + block->full_text = full_text ? + strdup(json_object_get_string(full_text)) : NULL; + block->short_text = short_text ? + strdup(json_object_get_string(short_text)) : NULL; + if (color) { + block->color = malloc(sizeof(uint32_t)); + *block->color = parse_color(json_object_get_string(color)); + } + if (min_width) { + json_type type = json_object_get_type(min_width); + if (type == json_type_int) { + block->min_width = json_object_get_int(min_width); + } else if (type == json_type_string) { + /* the width will be calculated when rendering */ + block->min_width = 0; + } + } + block->align = strdup(align ? json_object_get_string(align) : "left"); + block->urgent = urgent ? json_object_get_int(urgent) : false; + block->name = name ? strdup(json_object_get_string(name)) : NULL; + block->instance = instance ? + strdup(json_object_get_string(instance)) : NULL; + if (markup) { + block->markup = false; + const char *markup_str = json_object_get_string(markup); + if (strcmp(markup_str, "pango") == 0) { + block->markup = true; + } + } + block->separator = separator ? json_object_get_int(separator) : true; + block->separator_block_width = separator_block_width ? + json_object_get_int(separator_block_width) : 9; + // Airblader features + block->background = background ? + parse_color(json_object_get_string(background)) : 0; + block->border = border ? + parse_color(json_object_get_string(border)) : 0; + block->border_top = border_top ? json_object_get_int(border_top) : 1; + block->border_bottom = border_bottom ? + json_object_get_int(border_bottom) : 1; + block->border_left = border_left ? json_object_get_int(border_left) : 1; + block->border_right = border_right ? + json_object_get_int(border_right) : 1; + wl_list_insert(&status->blocks, &block->link); + } + return true; } -int i3bar_readable(struct status_line *status) { +bool i3bar_handle_readable(struct status_line *status) { struct i3bar_protocol_state *state = &status->i3bar_state; char *cur = &state->buffer[state->buffer_index]; @@ -30,7 +130,7 @@ int i3bar_readable(struct status_line *status) { state->buffer = new_buffer; } - int handled = 0; + bool redraw = false; while (*cur) { if (state->nodes[state->depth] == JSON_NODE_STRING) { if (!state->escape && *cur == '"') { @@ -44,7 +144,7 @@ int i3bar_readable(struct status_line *status) { if (state->depth > sizeof(state->nodes) / sizeof(state->nodes[0])) { status_error(status, "[i3bar json too deep]"); - return -1; + return false; } state->nodes[state->depth] = JSON_NODE_ARRAY; if (state->depth == 1) { @@ -54,18 +154,18 @@ int i3bar_readable(struct status_line *status) { case ']': if (state->nodes[state->depth] != JSON_NODE_ARRAY) { status_error(status, "[failed to parse i3bar json]"); - return -1; + return false; } --state->depth; if (state->depth == 0) { // cur[1] is valid since cur[0] != '\0' char p = cur[1]; cur[1] = '\0'; - i3bar_parse_json(status, state->current_node); + redraw = i3bar_parse_json( + status, state->current_node) || redraw; cur[1] = p; memmove(state->buffer, cur, state->buffer_size - (cur - state->buffer)); - ++handled; cur = state->buffer; state->current_node = cur + 1; } @@ -75,7 +175,7 @@ int i3bar_readable(struct status_line *status) { if (state->depth > sizeof(state->nodes) / sizeof(state->nodes[0])) { status_error(status, "[i3bar json too deep]"); - return -1; + return false; } state->nodes[state->depth] = JSON_NODE_STRING; break; @@ -84,5 +184,5 @@ int i3bar_readable(struct status_line *status) { ++cur; } state->buffer_index = cur - state->buffer; - return handled; + return redraw; } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 64583df0..ed5d9a31 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -323,7 +323,7 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id) { IPC_SUBSCRIBE, subscribe, &len)); } -bool handle_ipc_event(struct swaybar *bar) { +bool handle_ipc_readable(struct swaybar *bar) { struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); if (!resp) { return false; diff --git a/swaybar/render.c b/swaybar/render.c index c2358724..3ad6d5d7 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -18,10 +18,33 @@ static const int ws_horizontal_padding = 5; static const double ws_vertical_padding = 1.5; static const double border_width = 1; +static uint32_t render_status_line_error(cairo_t *cairo, + struct swaybar_config *config, const char *error, + double *x, uint32_t width, uint32_t height) { + if (!error) { + return 0; + } + cairo_set_source_u32(cairo, 0xFF0000FF); + static const int margin = 3; + int text_width, text_height; + get_text_size(cairo, config->font, + &text_width, &text_height, 1, false, "%s", error); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + return ideal_height; + } + *x -= text_width + margin; + double text_y = height / 2.0 - text_height / 2.0; + cairo_move_to(cairo, *x, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, false, "%s", error); + *x -= margin; + return ideal_height; +} + static uint32_t render_status_line_text(cairo_t *cairo, - struct swaybar_config *config, struct status_line *status, - bool focused, uint32_t width, uint32_t height) { - if (!status->text) { + struct swaybar_config *config, const char *text, + bool focused, double *x, uint32_t width, uint32_t height) { + if (!text) { return 0; } cairo_set_source_u32(cairo, focused ? @@ -29,38 +52,193 @@ static uint32_t render_status_line_text(cairo_t *cairo, static const int margin = 3; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, config->pango_markup, "%s", status->text); + 1, config->pango_markup, "%s", text); uint32_t ideal_height = text_height + ws_vertical_padding * 2; if (height < ideal_height) { return ideal_height; } + *x -= text_width + margin; double text_y = height / 2.0 - text_height / 2.0; - cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, config->pango_markup, - "%s", status->text); + cairo_move_to(cairo, *x, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); + *x -= margin; + return ideal_height; +} + +static void render_sharp_line(cairo_t *cairo, uint32_t color, + double x, double y, double width, double height) { + cairo_set_source_u32(cairo, color); + if (width > 1 && height > 1) { + cairo_rectangle(cairo, x, y, width, height); + cairo_fill(cairo); + } else { + if (width == 1) { + x += 0.5; + height += y; + width = x; + } + if (height == 1) { + y += 0.5; + width += x; + height = y; + } + cairo_move_to(cairo, x, y); + cairo_set_line_width(cairo, 1.0); + cairo_line_to(cairo, width, height); + cairo_stroke(cairo); + } +} + +static uint32_t render_status_block(cairo_t *cairo, + struct swaybar_config *config, struct i3bar_block *block, + double *x, uint32_t height, bool focused, bool edge) { + static const int margin = 3; + if (!block->full_text || !*block->full_text) { + return 0; + } + + int text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, block->markup, "%s", block->full_text); + int width = text_width; + if (width < block->min_width) { + width = block->min_width; + } + double block_width = width; + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + return ideal_height; + } + + *x -= width; + if (block->border && block->border_left > 0) { + *x -= (block->border_left + margin); + block_width += block->border_left + margin; + } + if (block->border && block->border_right > 0) { + *x -= (block->border_right + margin); + block_width += block->border_right + margin; + } + + int sep_width; + if (!edge) { + if (config->sep_symbol) { + int _height; + get_text_size(cairo, config->font, &sep_width, &_height, + 1, false, "%s", config->sep_symbol); + uint32_t _ideal_height = _height + ws_vertical_padding * 2; + if (height < _ideal_height) { + return _height; + } + if (sep_width > block->separator_block_width) { + block->separator_block_width = sep_width + margin * 2; + } + } + *x -= block->separator_block_width; + } else { + *x -= margin; + } + + // TODO: Create hotspot here + + double pos = *x; + if (block->background) { + cairo_set_source_u32(cairo, block->background); + cairo_rectangle(cairo, pos - 0.5, 1, block_width, height); + cairo_fill(cairo); + } + + if (block->border && block->border_top > 0) { + render_sharp_line(cairo, block->border, + pos - 0.5, 1, block_width, block->border_top); + } + if (block->border && block->border_bottom > 0) { + render_sharp_line(cairo, block->border, + pos - 0.5, height - 1 - block->border_bottom, + block_width, block->border_bottom); + } + if (block->border != 0 && block->border_left > 0) { + render_sharp_line(cairo, block->border, + pos - 0.5, 1, block->border_left, height); + pos += block->border_left + margin; + } + + double offset = 0; + if (strncmp(block->align, "left", 5) == 0) { + offset = pos; + } else if (strncmp(block->align, "right", 5) == 0) { + offset = pos + width - text_width; + } else if (strncmp(block->align, "center", 6) == 0) { + offset = pos + (width - text_width) / 2; + } + cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); + uint32_t color = block->color ? *block->color : config->colors.statusline; + cairo_set_source_u32(cairo, color); + pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text); + pos += width; + + if (block->border && block->border_right > 0) { + pos += margin; + render_sharp_line(cairo, block->border, + pos - 0.5, 1, block->border_right, height); + pos += block->border_right; + } + + if (!edge && block->separator) { + if (focused) { + cairo_set_source_u32(cairo, config->colors.focused_separator); + } else { + cairo_set_source_u32(cairo, config->colors.separator); + } + if (config->sep_symbol) { + offset = pos + (block->separator_block_width - sep_width) / 2; + cairo_move_to(cairo, offset, margin); + pango_printf(cairo, config->font, 1, false, + "%s", config->sep_symbol); + } else { + cairo_set_line_width(cairo, 1); + cairo_move_to(cairo, + pos + block->separator_block_width / 2, margin); + cairo_line_to(cairo, + pos + block->separator_block_width / 2, height - margin); + cairo_stroke(cairo); + } + } return ideal_height; } static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_config *config, struct status_line *status, - bool focused, uint32_t width, uint32_t height) { - // TODO - return 0; + bool focused, double *x, uint32_t width, uint32_t height) { + struct i3bar_block *block; + uint32_t max_height = 0; + bool edge = true; + wl_list_for_each_reverse(block, &status->blocks, link) { + uint32_t h = render_status_block(cairo, config, + block, x, height, focused, edge); + max_height = h > max_height ? h : max_height; + edge = false; + } + return max_height; } static uint32_t render_status_line(cairo_t *cairo, struct swaybar_config *config, struct status_line *status, - bool focused, uint32_t width, uint32_t height) { + bool focused, double *x, uint32_t width, uint32_t height) { switch (status->protocol) { + case PROTOCOL_ERROR: + return render_status_line_error(cairo, + config, status->text, x, width, height); case PROTOCOL_TEXT: return render_status_line_text(cairo, - config, status, focused, width, height); + config, status->text, focused, x, width, height); case PROTOCOL_I3BAR: return render_status_line_i3bar(cairo, - config, status, focused, width, height); - default: + config, status, focused, x, width, height); + case PROTOCOL_UNDEF: return 0; } + return 0; } static uint32_t render_binding_mode_indicator(cairo_t *cairo, @@ -211,9 +389,10 @@ static uint32_t render_to_cairo(cairo_t *cairo, cairo, config, config->mode, x, output->height); max_height = h > max_height ? h : max_height; } + x = output->width; if (bar->status) { uint32_t h = render_status_line(cairo, config, bar->status, - output->focused, output->width, output->height); + output->focused, &x, output->width, output->height); max_height = h > max_height ? h : max_height; } diff --git a/swaybar/status_line.c b/swaybar/status_line.c index c94ac6d4..cc7e217f 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -17,13 +17,13 @@ void status_error(struct status_line *status, const char *text) { status->text = text; } -bool handle_status_readable(struct status_line *status) { +bool status_handle_readable(struct status_line *status) { char *line; switch (status->protocol) { case PROTOCOL_ERROR: return false; case PROTOCOL_I3BAR: - if (i3bar_readable(status) > 0) { + if (i3bar_handle_readable(status) > 0) { return true; } break; @@ -66,6 +66,7 @@ bool handle_status_readable(struct status_line *status) { status->protocol = PROTOCOL_I3BAR; free(status->text_state.buffer); + wl_list_init(&status->blocks); status->i3bar_state.buffer_size = 4096; status->i3bar_state.buffer = malloc(status->i3bar_state.buffer_size); -- cgit v1.2.3 From 260595076977729bcaf9aadcfbbc8c5f269c6387 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 21:06:28 -0400 Subject: Add hidpi support to swaybar --- include/swaybar/bar.h | 1 + swaybar/bar.c | 73 +++++++++++++++++++--- swaybar/render.c | 168 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 173 insertions(+), 69 deletions(-) (limited to 'swaybar/bar.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 74292519..503b961c 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -58,6 +58,7 @@ struct swaybar_output { bool focused; uint32_t width, height; + int32_t scale; struct pool_buffer buffers[2]; struct pool_buffer *current_buffer; }; diff --git a/swaybar/bar.c b/swaybar/bar.c index fb417095..cf812a60 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -69,11 +69,19 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, break; } } + int max_scale = 1; + struct swaybar_output *_output; + wl_list_for_each(_output, &bar->outputs, link) { + if (_output->scale > max_scale) { + max_scale = _output->scale; + } + } + wl_surface_set_buffer_scale(pointer->cursor_surface, max_scale); wl_surface_attach(pointer->cursor_surface, wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, - pointer->cursor_image->hotspot_x, - pointer->cursor_image->hotspot_y); + pointer->cursor_image->hotspot_x / max_scale, + pointer->cursor_image->hotspot_y / max_scale); wl_surface_commit(pointer->cursor_surface); } @@ -103,10 +111,12 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } struct swaybar_hotspot *hotspot; wl_list_for_each(hotspot, &output->hotspots, link) { - if (pointer->x >= hotspot->x - && pointer->y >= hotspot->y - && pointer->x < hotspot->x + hotspot->width - && pointer->y < hotspot->y + hotspot->height) { + double x = pointer->x * output->scale; + double y = pointer->y * output->scale; + if (x >= hotspot->x + && y >= hotspot->y + && x < hotspot->x + hotspot->width + && y < hotspot->y + hotspot->height) { hotspot->callback(output, pointer->x, pointer->y, button, hotspot->data); } @@ -197,12 +207,43 @@ const struct wl_seat_listener seat_listener = { .name = seat_handle_name, }; +static void output_geometry(void *data, struct wl_output *output, int32_t x, + int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, + const char *make, const char *model, int32_t transform) { + // Who cares +} + +static void output_mode(void *data, struct wl_output *output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) { + // Who cares +} + +static void output_done(void *data, struct wl_output *output) { + // Who cares +} + +static void output_scale(void *data, struct wl_output *wl_output, + int32_t factor) { + struct swaybar_output *output = data; + output->scale = factor; + if (output->surface) { + render_frame(output->bar, output); + } +} + +struct wl_output_listener output_listener = { + .geometry = output_geometry, + .mode = output_mode, + .done = output_done, + .scale = output_scale, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct swaybar *bar = data; if (strcmp(interface, wl_compositor_interface.name) == 0) { bar->compositor = wl_registry_bind(registry, name, - &wl_compositor_interface, 1); + &wl_compositor_interface, 3); } else if (strcmp(interface, wl_seat_interface.name) == 0) { bar->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); @@ -216,7 +257,9 @@ static void handle_global(void *data, struct wl_registry *registry, calloc(1, sizeof(struct swaybar_output)); output->bar = bar; output->output = wl_registry_bind(registry, name, - &wl_output_interface, 1); + &wl_output_interface, 3); + wl_output_add_listener(output->output, &output_listener, output); + output->scale = 1; output->index = index++; wl_list_init(&output->workspaces); wl_list_init(&output->hotspots); @@ -262,9 +305,20 @@ void bar_setup(struct swaybar *bar, wl_registry_add_listener(registry, ®istry_listener, bar); wl_display_roundtrip(bar->display); assert(bar->compositor && bar->layer_shell && bar->shm); + wl_display_roundtrip(bar->display); + struct swaybar_pointer *pointer = &bar->pointer; - assert(pointer->cursor_theme = wl_cursor_theme_load(NULL, 16, bar->shm)); + int max_scale = 1; + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + if (output->scale > max_scale) { + max_scale = output->scale; + } + } + + assert(pointer->cursor_theme = wl_cursor_theme_load( + NULL, 16 * (max_scale * 2), bar->shm)); struct wl_cursor *cursor; assert(cursor = wl_cursor_theme_get_cursor( pointer->cursor_theme, "left_ptr")); @@ -273,7 +327,6 @@ void bar_setup(struct swaybar *bar, wl_compositor_create_surface(bar->compositor)); // TODO: we might not necessarily be meant to do all of the outputs - struct swaybar_output *output; wl_list_for_each(output, &bar->outputs, link) { struct config_output *coutput; wl_list_for_each(coutput, &bar->config->outputs, link) { diff --git a/swaybar/render.c b/swaybar/render.c index 6f3b0788..bf144d5c 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -14,55 +14,73 @@ #include "swaybar/status_line.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -static const int ws_horizontal_padding = 5; -static const double ws_vertical_padding = 1.5; -static const double border_width = 1; +static const int WS_HORIZONTAL_PADDING = 5; +static const double WS_VERTICAL_PADDING = 1.5; +static const double BORDER_WIDTH = 1; static uint32_t render_status_line_error(cairo_t *cairo, - struct swaybar_config *config, const char *error, - double *x, uint32_t width, uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + const char *error, double *x, uint32_t width, uint32_t height) { if (!error) { return 0; } + + height *= output->scale; + cairo_set_source_u32(cairo, 0xFF0000FF); - static const int margin = 3; + + int margin = 3 * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int text_width, text_height; get_text_size(cairo, config->font, - &text_width, &text_height, 1, false, "%s", error); + &text_width, &text_height, output->scale, false, "%s", error); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } *x -= text_width + margin; + double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, false, "%s", error); + pango_printf(cairo, config->font, output->scale, false, "%s", error); *x -= margin; - return ideal_height; + return ideal_height / output->scale; } static uint32_t render_status_line_text(cairo_t *cairo, - struct swaybar_config *config, const char *text, - bool focused, double *x, uint32_t width, uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + const char *text, bool focused, double *x, + uint32_t width, uint32_t height) { if (!text) { return 0; } + + height *= output->scale; + cairo_set_source_u32(cairo, focused ? config->colors.focused_statusline : config->colors.statusline); - static const int margin = 3; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, config->pango_markup, "%s", text); + output->scale, config->pango_markup, "%s", text); + + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int margin = 3 * output->scale; + uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } + *x -= text_width + margin; double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); + pango_printf(cairo, config->font, output->scale, + config->pango_markup, "%s", text); *x -= margin; - return ideal_height; + return ideal_height / output->scale; } static void render_sharp_line(cairo_t *cairo, uint32_t color, @@ -100,22 +118,28 @@ static uint32_t render_status_block(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct i3bar_block *block, double *x, uint32_t height, bool focused, bool edge) { - static const int margin = 3; if (!block->full_text || !*block->full_text) { return 0; } + height *= output->scale; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, block->markup, "%s", block->full_text); + output->scale, block->markup, "%s", block->full_text); + + int margin = 3 * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING * 2; + int width = text_width; if (width < block->min_width) { width = block->min_width; } + double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } *x -= width; @@ -133,10 +157,10 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { int _height; get_text_size(cairo, config->font, &sep_width, &_height, - 1, false, "%s", config->sep_symbol); + output->scale, false, "%s", config->sep_symbol); uint32_t _ideal_height = _height + ws_vertical_padding * 2; - if (height < _ideal_height) { - return _height; + if (height < _ideal_height / output->scale) { + return _height / output->scale; } if (sep_width > block->separator_block_width) { block->separator_block_width = sep_width + margin * 2; @@ -160,22 +184,26 @@ static uint32_t render_status_block(cairo_t *cairo, double pos = *x; if (block->background) { cairo_set_source_u32(cairo, block->background); - cairo_rectangle(cairo, pos - 0.5, 1, block_width, height); + cairo_rectangle(cairo, pos - 0.5 * output->scale, + output->scale, block_width, height); cairo_fill(cairo); } if (block->border && block->border_top > 0) { render_sharp_line(cairo, block->border, - pos - 0.5, 1, block_width, block->border_top); + pos - 0.5 * output->scale, output->scale, + block_width, block->border_top); } if (block->border && block->border_bottom > 0) { render_sharp_line(cairo, block->border, - pos - 0.5, height - 1 - block->border_bottom, + pos - 0.5 * output->scale, + height - output->scale - block->border_bottom, block_width, block->border_bottom); } if (block->border != 0 && block->border_left > 0) { render_sharp_line(cairo, block->border, - pos - 0.5, 1, block->border_left, height); + pos - 0.5 * output->scale, output->scale, + block->border_left, height); pos += block->border_left + margin; } @@ -190,13 +218,15 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); uint32_t color = block->color ? *block->color : config->colors.statusline; cairo_set_source_u32(cairo, color); - pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text); + pango_printf(cairo, config->font, output->scale, + block->markup, "%s", block->full_text); pos += width; if (block->border && block->border_right > 0) { pos += margin; render_sharp_line(cairo, block->border, - pos - 0.5, 1, block->border_right, height); + pos - 0.5 * output->scale, output->scale, + block->border_right, height); pos += block->border_right; } @@ -209,7 +239,7 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { offset = pos + (block->separator_block_width - sep_width) / 2; cairo_move_to(cairo, offset, margin); - pango_printf(cairo, config->font, 1, false, + pango_printf(cairo, config->font, output->scale, false, "%s", config->sep_symbol); } else { cairo_set_line_width(cairo, 1); @@ -220,7 +250,7 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_stroke(cairo); } } - return ideal_height; + return ideal_height / output->scale; } static uint32_t render_status_line_i3bar(cairo_t *cairo, @@ -246,10 +276,10 @@ static uint32_t render_status_line(cairo_t *cairo, switch (status->protocol) { case PROTOCOL_ERROR: return render_status_line_error(cairo, - config, status->text, x, width, height); + output, config, status->text, x, width, height); case PROTOCOL_TEXT: return render_status_line_text(cairo, - config, status->text, focused, x, width, height); + output, config, status->text, focused, x, width, height); case PROTOCOL_I3BAR: return render_status_line_i3bar(cairo, config, output, status, focused, x, width, height); @@ -260,15 +290,23 @@ static uint32_t render_status_line(cairo_t *cairo, } static uint32_t render_binding_mode_indicator(cairo_t *cairo, - struct swaybar_config *config, const char *mode, double x, - uint32_t height) { + struct swaybar_output *output, struct swaybar_config *config, + const char *mode, double x, uint32_t height) { + + height *= output->scale; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, true, "%s", mode); + output->scale, true, "%s", mode); + + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; + int border_width = BORDER_WIDTH * output->scale; + uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -289,8 +327,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, true, "%s", mode); - return ideal_height; + pango_printf(cairo, config->font, output->scale, true, "%s", mode); + return ideal_height / output->scale; } static const char *strip_workspace_number(const char *ws_name) { @@ -330,14 +368,22 @@ static uint32_t render_workspace_button(cairo_t *cairo, box_colors = config->colors.inactive_workspace; } + height *= output->scale; + int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, true, "%s", name); + output->scale, true, "%s", name); + + int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; + int border_width = BORDER_WIDTH * output->scale; + uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - if (height < ideal_height) { - return ideal_height; + if (height < ideal_height / output->scale) { + return ideal_height / output->scale; } + uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; cairo_set_source_u32(cairo, box_colors.background); @@ -357,7 +403,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, box_colors.text); cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, true, "%s", name); + pango_printf(cairo, config->font, output->scale, true, "%s", name); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; @@ -370,7 +416,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, wl_list_insert(&output->hotspots, &hotspot->link); *x += width; - return height; + return height / output->scale; } static uint32_t render_to_cairo(cairo_t *cairo, @@ -394,7 +440,13 @@ static uint32_t render_to_cairo(cairo_t *cairo, * height is too tall, the render function should adapt its drawing to * utilize the available space. */ - double x = 0; + double x = output->width * output->scale; + if (bar->status) { + uint32_t h = render_status_line(cairo, config, output, bar->status, + output->focused, &x, output->width, output->height); + max_height = h > max_height ? h : max_height; + } + x = 0; if (config->workspace_buttons) { struct swaybar_workspace *ws; wl_list_for_each_reverse(ws, &output->workspaces, link) { @@ -404,14 +456,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, } } if (config->binding_mode_indicator && config->mode) { - uint32_t h = render_binding_mode_indicator( - cairo, config, config->mode, x, output->height); - max_height = h > max_height ? h : max_height; - } - x = output->width; - if (bar->status) { - uint32_t h = render_status_line(cairo, config, output, bar->status, - output->focused, &x, output->width, output->height); + uint32_t h = render_binding_mode_indicator(cairo, + output, config, config->mode, x, output->height); max_height = h > max_height ? h : max_height; } @@ -451,7 +497,9 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { } else { // Replay recording into shm and send it off output->current_buffer = get_next_buffer(bar->shm, - output->buffers, output->width, output->height); + output->buffers, + output->width * output->scale, + output->height * output->scale); cairo_t *shm = output->current_buffer->cairo; cairo_save(shm); @@ -462,9 +510,11 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { cairo_set_source_surface(shm, recorder, 0.0, 0.0); cairo_paint(shm); + wl_surface_set_buffer_scale(output->surface, output->scale); wl_surface_attach(output->surface, output->current_buffer->buffer, 0, 0); - wl_surface_damage(output->surface, 0, 0, output->width, output->height); + wl_surface_damage(output->surface, 0, 0, + output->width, output->height); wl_surface_commit(output->surface); wl_display_roundtrip(bar->display); } -- cgit v1.2.3 From d48e7036aa04f8503737de678519cc389058b259 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 21:29:43 -0400 Subject: Don't use asserts with side-effects --- swaybar/bar.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index cf812a60..b617f9ab 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -299,7 +299,8 @@ void bar_setup(struct swaybar *bar, bar->status = status_line_init(bar->config->status_command); } - assert(bar->display = wl_display_connect(NULL)); + bar->display = wl_display_connect(NULL); + assert(bar->display); struct wl_registry *registry = wl_display_get_registry(bar->display); wl_registry_add_listener(registry, ®istry_listener, bar); @@ -317,14 +318,15 @@ void bar_setup(struct swaybar *bar, } } - assert(pointer->cursor_theme = wl_cursor_theme_load( - NULL, 16 * (max_scale * 2), bar->shm)); + pointer->cursor_theme = wl_cursor_theme_load( + NULL, 16 * (max_scale * 2), bar->shm); + assert(pointer->cursor_theme); struct wl_cursor *cursor; - assert(cursor = wl_cursor_theme_get_cursor( - pointer->cursor_theme, "left_ptr")); + cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); + assert(cursor); pointer->cursor_image = cursor->images[0]; - assert(pointer->cursor_surface = - wl_compositor_create_surface(bar->compositor)); + pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); + assert(pointer->cursor_surface); // TODO: we might not necessarily be meant to do all of the outputs wl_list_for_each(output, &bar->outputs, link) { @@ -334,8 +336,8 @@ void bar_setup(struct swaybar *bar, continue; } output->name = strdup(coutput->name); - assert(output->surface = wl_compositor_create_surface( - bar->compositor)); + output->surface = wl_compositor_create_surface(bar->compositor); + assert(output->surface); output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( bar->layer_shell, output->surface, output->output, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); -- cgit v1.2.3 From 38bdd4bdebc4938f25af90bc4f79e278f61808e0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 22:52:40 -0400 Subject: Address review feedback --- swaybar/bar.c | 2 +- swaybar/render.c | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index b617f9ab..ea0141cc 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -319,7 +319,7 @@ void bar_setup(struct swaybar *bar, } pointer->cursor_theme = wl_cursor_theme_load( - NULL, 16 * (max_scale * 2), bar->shm); + NULL, 24 * max_scale, bar->shm); assert(pointer->cursor_theme); struct wl_cursor *cursor; cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); diff --git a/swaybar/render.c b/swaybar/render.c index 1f84fdba..be58301d 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -20,7 +20,7 @@ static const double BORDER_WIDTH = 1; static uint32_t render_status_line_error(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - const char *error, double *x, uint32_t width, uint32_t surface_height) { + const char *error, double *x, uint32_t surface_height) { if (!error) { return 0; } @@ -51,8 +51,7 @@ static uint32_t render_status_line_error(cairo_t *cairo, static uint32_t render_status_line_text(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - const char *text, bool focused, double *x, - uint32_t width, uint32_t surface_height) { + const char *text, bool focused, double *x, uint32_t surface_height) { if (!text) { return 0; } @@ -159,7 +158,7 @@ static uint32_t render_status_block(cairo_t *cairo, get_text_size(cairo, config->font, &sep_width, &_height, output->scale, false, "%s", config->sep_symbol); uint32_t _ideal_height = _height + ws_vertical_padding * 2; - if (height < _ideal_height / output->scale) { + if ((uint32_t)_height < _ideal_height / output->scale) { return _height / output->scale; } if (sep_width > block->separator_block_width) { @@ -256,7 +255,7 @@ static uint32_t render_status_block(cairo_t *cairo, static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, - double *x, uint32_t width, uint32_t surface_height) { + double *x, uint32_t surface_height) { uint32_t max_height = 0; bool edge = true; struct i3bar_block *block; @@ -272,17 +271,17 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, static uint32_t render_status_line(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, - double *x, uint32_t width, uint32_t surface_height) { + double *x, uint32_t surface_height) { switch (status->protocol) { case PROTOCOL_ERROR: return render_status_line_error(cairo, output, config, - status->text, x, width, surface_height); + status->text, x, surface_height); case PROTOCOL_TEXT: return render_status_line_text(cairo, output, config, - status->text, focused, x, width, surface_height); + status->text, focused, x, surface_height); case PROTOCOL_I3BAR: return render_status_line_i3bar(cairo, config, output, - status, focused, x, width, surface_height); + status, focused, x, surface_height); case PROTOCOL_UNDEF: return 0; } @@ -368,7 +367,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, box_colors = config->colors.inactive_workspace; } - uint32_t height = surface_height *output->scale; + uint32_t height = surface_height * output->scale; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, @@ -442,8 +441,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, */ double x = output->width * output->scale; if (bar->status) { - uint32_t h = render_status_line(cairo, config, output, bar->status, - output->focused, &x, output->width, output->height); + uint32_t h = render_status_line(cairo, config, output, + bar->status, output->focused, &x, output->height); max_height = h > max_height ? h : max_height; } x = 0; -- cgit v1.2.3 From f242362e7e521a8f35f47572038a20d404d25327 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 5 Apr 2018 15:39:57 -0400 Subject: Handle output removal on swaybar --- client/pool-buffer.c | 2 +- include/pool-buffer.h | 1 + include/swaybar/bar.h | 1 + sway/tree/container.c | 4 +++- swaybar/bar.c | 42 ++++++++++++++++++++++++++++++++++++++---- swaybar/ipc.c | 2 +- swaybar/render.c | 2 -- 7 files changed, 45 insertions(+), 9 deletions(-) (limited to 'swaybar/bar.c') diff --git a/client/pool-buffer.c b/client/pool-buffer.c index b5ed9c98..1f54a77c 100644 --- a/client/pool-buffer.c +++ b/client/pool-buffer.c @@ -79,7 +79,7 @@ static struct pool_buffer *create_buffer(struct wl_shm *shm, return buf; } -static void destroy_buffer(struct pool_buffer *buffer) { +void destroy_buffer(struct pool_buffer *buffer) { if (buffer->buffer) { wl_buffer_destroy(buffer->buffer); } diff --git a/include/pool-buffer.h b/include/pool-buffer.h index cdebd64d..856f7c8c 100644 --- a/include/pool-buffer.h +++ b/include/pool-buffer.h @@ -17,5 +17,6 @@ struct pool_buffer { struct pool_buffer *get_next_buffer(struct wl_shm *shm, struct pool_buffer pool[static 2], uint32_t width, uint32_t height); +void destroy_buffer(struct pool_buffer *buffer); #endif diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 503b961c..0037190b 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -49,6 +49,7 @@ struct swaybar_output { struct wl_output *output; struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; + uint32_t wl_name; struct wl_list workspaces; struct wl_list hotspots; diff --git a/sway/tree/container.c b/sway/tree/container.c index 8fc9e3e8..3e8c1c75 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -64,7 +64,9 @@ static void container_close_notify(struct sway_container *container) { return; } // TODO send ipc event type based on the container type - ipc_event_window(container, "close"); + if (container->type == C_VIEW || container->type == C_WORKSPACE) { + ipc_event_window(container, "close"); + } } struct sway_container *container_create(enum sway_container_type type) { diff --git a/swaybar/bar.c b/swaybar/bar.c index ea0141cc..f1a701b9 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -34,6 +34,34 @@ static void bar_init(struct swaybar *bar) { wl_list_init(&bar->outputs); } +static void swaybar_output_free(struct swaybar_output *output) { + if (!output) { + return; + } + wlr_log(L_DEBUG, "Removing output %s", output->name); + zwlr_layer_surface_v1_destroy(output->layer_surface); + wl_surface_destroy(output->surface); + wl_output_destroy(output->output); + destroy_buffer(&output->buffers[0]); + destroy_buffer(&output->buffers[1]); + struct swaybar_workspace *ws, *ws_tmp; + wl_list_for_each_safe(ws, ws_tmp, &output->workspaces, link) { + wl_list_remove(&ws->link); + free(ws->name); + free(ws); + } + 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); +} + static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height) { @@ -46,10 +74,8 @@ static void layer_surface_configure(void *data, static void layer_surface_closed(void *_output, struct zwlr_layer_surface_v1 *surface) { - // TODO: Deal with hotplugging struct swaybar_output *output = _output; - zwlr_layer_surface_v1_destroy(output->layer_surface); - wl_surface_destroy(output->surface); + swaybar_output_free(output); } struct zwlr_layer_surface_v1_listener layer_surface_listener = { @@ -261,6 +287,7 @@ static void handle_global(void *data, struct wl_registry *registry, wl_output_add_listener(output->output, &output_listener, output); output->scale = 1; output->index = index++; + output->wl_name = name; wl_list_init(&output->workspaces); wl_list_init(&output->hotspots); wl_list_insert(&bar->outputs, &output->link); @@ -272,7 +299,14 @@ static void handle_global(void *data, struct wl_registry *registry, static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { - // who cares + struct swaybar *bar = data; + struct swaybar_output *output, *tmp; + wl_list_for_each_safe(output, tmp, &bar->outputs, link) { + if (output->wl_name == name) { + swaybar_output_free(output); + break; + } + } } static const struct wl_registry_listener registry_listener = { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index ed5d9a31..92dbb8ea 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -367,5 +367,5 @@ bool handle_ipc_readable(struct swaybar *bar) { return false; } free_ipc_response(resp); - return true; + return false; } diff --git a/swaybar/render.c b/swaybar/render.c index be58301d..53e578f0 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -421,8 +421,6 @@ static uint32_t render_workspace_button(cairo_t *cairo, static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; - wlr_log(L_DEBUG, "output %p", output); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (output->focused) { cairo_set_source_u32(cairo, config->colors.focused_background); -- cgit v1.2.3 From c38de1672255e9906623c133598ac7fded10640a Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 10 Apr 2018 13:38:15 +1000 Subject: Fix swaybar output config. --- swaybar/bar.c | 70 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 28 deletions(-) (limited to 'swaybar/bar.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index f1a701b9..d51c4ec7 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -264,6 +264,19 @@ struct wl_output_listener output_listener = { .scale = output_scale, }; +static bool bar_uses_output(struct swaybar *bar, size_t output_index) { + if (bar->config->all_outputs) { + return true; + } + struct config_output *coutput; + wl_list_for_each(coutput, &bar->config->outputs, link) { + if (coutput->index == output_index) { + return true; + } + } + return false; +} + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct swaybar *bar = data; @@ -278,19 +291,22 @@ static void handle_global(void *data, struct wl_registry *registry, bar->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { - static size_t index = 0; - struct swaybar_output *output = - calloc(1, sizeof(struct swaybar_output)); - output->bar = bar; - output->output = wl_registry_bind(registry, name, - &wl_output_interface, 3); - wl_output_add_listener(output->output, &output_listener, output); - output->scale = 1; - output->index = index++; - output->wl_name = name; - wl_list_init(&output->workspaces); - wl_list_init(&output->hotspots); - wl_list_insert(&bar->outputs, &output->link); + static size_t output_index = 0; + if (bar_uses_output(bar, output_index)) { + struct swaybar_output *output = + calloc(1, sizeof(struct swaybar_output)); + output->bar = bar; + output->output = wl_registry_bind(registry, name, + &wl_output_interface, 3); + wl_output_add_listener(output->output, &output_listener, output); + output->scale = 1; + output->index = output_index; + output->wl_name = name; + wl_list_init(&output->workspaces); + wl_list_init(&output->hotspots); + wl_list_insert(&bar->outputs, &output->link); + } + ++output_index; } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); @@ -362,26 +378,24 @@ void bar_setup(struct swaybar *bar, pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); assert(pointer->cursor_surface); - // TODO: we might not necessarily be meant to do all of the outputs wl_list_for_each(output, &bar->outputs, link) { struct config_output *coutput; wl_list_for_each(coutput, &bar->config->outputs, link) { - if (coutput->index != output->index) { - continue; + if (coutput->index == output->index) { + output->name = strdup(coutput->name); + break; } - output->name = strdup(coutput->name); - output->surface = wl_compositor_create_surface(bar->compositor); - assert(output->surface); - output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - bar->layer_shell, output->surface, output->output, - 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); - break; } + output->surface = wl_compositor_create_surface(bar->compositor); + assert(output->surface); + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + bar->layer_shell, output->surface, output->output, + 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); } ipc_get_workspaces(bar); render_all_frames(bar); -- cgit v1.2.3