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. --- include/swaybar/bar.h | 89 ++++++++++++++++++--------------------------------- 1 file changed, 31 insertions(+), 58 deletions(-) (limited to 'include/swaybar/bar.h') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 50d36e76..3ae8c0b3 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -1,72 +1,45 @@ #ifndef _SWAYBAR_BAR_H #define _SWAYBAR_BAR_H - -#include "client/registry.h" -#include "client/window.h" +#include +#include "pool-buffer.h" #include "list.h" -struct bar { - struct config *config; - struct status_line *status; - list_t *outputs; - struct output *focused_output; +struct swaybar_config; +struct swaybar_output; +struct swaybar_workspace; + +struct swaybar { + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; - int ipc_event_socketfd; - int ipc_socketfd; - int status_read_fd; - int status_write_fd; - pid_t status_command_pid; + struct swaybar_config *config; + struct swaybar_output *focused_output; + + struct wl_list outputs; }; -struct output { - struct window *window; - struct registry *registry; - list_t *workspaces; -#ifdef ENABLE_TRAY - list_t *items; -#endif +struct swaybar_output { + struct wl_list link; + struct swaybar *bar; + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + char *name; int idx; bool focused; -}; -struct workspace { - int num; - char *name; - bool focused; - bool visible; - bool urgent; + uint32_t width, height; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; }; -/** Global bar state */ -extern struct bar swaybar; +void bar_setup(struct swaybar *bar, + const char *socket_path, + const char *bar_id); +void bar_run(struct swaybar *bar); +void bar_teardown(struct swaybar *bar); -/** True if sway needs to render */ -extern bool dirty; - -/** - * Setup bar. - */ -void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id); - -/** - * Create new output struct from name. - */ -struct output *new_output(const char *name); - -/** - * Bar mainloop. - */ -void bar_run(struct bar *bar); - -/** - * free workspace list. - */ -void free_workspaces(list_t *workspaces); - -/** - * Teardown bar. - */ -void bar_teardown(struct bar *bar); - -#endif /* _SWAYBAR_BAR_H */ +#endif -- 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 'include/swaybar/bar.h') 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 'include/swaybar/bar.h') 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 'include/swaybar/bar.h') 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 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 'include/swaybar/bar.h') 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 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 'include/swaybar/bar.h') 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 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 'include/swaybar/bar.h') 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 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 'include/swaybar/bar.h') 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 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 'include/swaybar/bar.h') 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