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/render.c | 388 ++++++------------------------------------------------- 1 file changed, 42 insertions(+), 346 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 6fc09078..2eaa0195 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,367 +1,63 @@ #include #include #include - -#include "client/cairo.h" -#include "client/pango.h" -#include "client/window.h" +#include +#include "cairo.h" +#include "pango.h" +#include "pool-buffer.h" +#include "swaybar/bar.h" #include "swaybar/config.h" -#include "swaybar/status_line.h" #include "swaybar/render.h" -#ifdef ENABLE_TRAY -#include "swaybar/tray/tray.h" -#include "swaybar/tray/sni.h" -#endif -#include "log.h" - - -/* internal spacing */ -static int margin = 3; -static int ws_horizontal_padding = 5; -static double ws_vertical_padding = 1.5; -static int ws_spacing = 1; - -/** - * Renders a sharp line of any width and height. - * - * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0 - * if the line has a width/height of one pixel, respectively. - */ -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 void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge, bool is_focused) { - int width, height, sep_width; - get_text_size(window->cairo, window->font, &width, &height, - window->scale, block->markup, "%s", block->full_text); - - int textwidth = width; - double block_width = width; - - if (width < block->min_width) { - width = block->min_width; - } - - *x -= width; - - if (block->border != 0 && block->border_left > 0) { - *x -= (block->border_left + margin); - block_width += block->border_left + margin; - } - - if (block->border != 0 && block->border_right > 0) { - *x -= (block->border_right + margin); - block_width += block->border_right + margin; - } - - // Add separator - if (!edge) { - if (config->sep_symbol) { - get_text_size(window->cairo, window->font, &sep_width, &height, - window->scale, false, "%s", config->sep_symbol); - if (sep_width > block->separator_block_width) { - block->separator_block_width = sep_width + margin * 2; - } - } - - *x -= block->separator_block_width; - } else { - *x -= margin; - } - - double pos = *x; - - block->x = (int)pos; - block->width = (int)block_width; - - // render background - if (block->background != 0x0) { - cairo_set_source_u32(window->cairo, block->background); - cairo_rectangle(window->cairo, pos - 0.5, 1, block_width, (window->height * window->scale) - 2); - cairo_fill(window->cairo); - } - - // render top border - if (block->border != 0 && block->border_top > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block_width, - block->border_top); - } - - // render bottom border - if (block->border != 0 && block->border_bottom > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - (window->height * window->scale) - 1 - block->border_bottom, - block_width, - block->border_bottom); - } - - // render left border - if (block->border != 0 && block->border_left > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block->border_left, - (window->height * window->scale) - 2); - - pos += block->border_left + margin; - } - - // render text - double offset = 0; - - if (strncmp(block->align, "left", 5) == 0) { - offset = pos; - } else if (strncmp(block->align, "right", 5) == 0) { - offset = pos + width - textwidth; - } else if (strncmp(block->align, "center", 6) == 0) { - offset = pos + (width - textwidth) / 2; - } - - cairo_move_to(window->cairo, offset, margin); - cairo_set_source_u32(window->cairo, block->color); - pango_printf(window->cairo, window->font, window->scale, - block->markup, "%s", block->full_text); - - pos += width; +#include "wlr-layer-shell-unstable-v1-client-protocol.h" - // render right border - if (block->border != 0 && block->border_right > 0) { - pos += margin; - - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block->border_right, - (window->height * window->scale) - 2); - - pos += block->border_right; - } - - // render separator - if (!edge && block->separator) { - if (is_focused) { - cairo_set_source_u32(window->cairo, config->colors.focused_separator); - } else { - cairo_set_source_u32(window->cairo, config->colors.separator); - } - if (config->sep_symbol) { - offset = pos + (block->separator_block_width - sep_width) / 2; - cairo_move_to(window->cairo, offset, margin); - pango_printf(window->cairo, window->font, window->scale, - false, "%s", config->sep_symbol); - } else { - cairo_set_line_width(window->cairo, 1); - cairo_move_to(window->cairo, pos + block->separator_block_width/2, - margin); - cairo_line_to(window->cairo, pos + block->separator_block_width/2, - (window->height * window->scale) - margin); - cairo_stroke(window->cairo); - } - } +static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, + struct swaybar_output *output) { + struct swaybar_config *config = bar->config; -} - -static const char *strip_workspace_name(bool strip_num, const char *ws_name) { - bool strip = false; - int i; - - if (strip_num) { - int len = strlen(ws_name); - for (i = 0; i < len; ++i) { - if (!('0' <= ws_name[i] && ws_name[i] <= '9')) { - if (':' == ws_name[i] && i < len-1 && i > 0) { - strip = true; - ++i; - } - break; - } - } - } - - if (strip) { - return ws_name + i; - } - - return ws_name; -} - -void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height) { - const char *stripped_name = strip_workspace_name(swaybar.config->strip_workspace_numbers, workspace_name); - - get_text_size(window->cairo, window->font, width, height, - window->scale, true, "%s", stripped_name); - *width += 2 * ws_horizontal_padding; - *height += 2 * ws_vertical_padding; -} - -static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) { - const char *stripped_name = strip_workspace_name(config->strip_workspace_numbers, ws->name); - - struct box_colors box_colors; - if (ws->urgent) { - box_colors = config->colors.urgent_workspace; - } else if (ws->focused) { - box_colors = config->colors.focused_workspace; - } else if (ws->visible) { - box_colors = config->colors.active_workspace; - } else { - box_colors = config->colors.inactive_workspace; - } - - int width, height; - workspace_button_size(window, stripped_name, &width, &height); - - // background - cairo_set_source_u32(window->cairo, box_colors.background); - cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); - cairo_fill(window->cairo); - - // border - cairo_set_source_u32(window->cairo, box_colors.border); - cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); - cairo_stroke(window->cairo); - - // text - cairo_set_source_u32(window->cairo, box_colors.text); - cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin); - pango_printf(window->cairo, window->font, window->scale, - true, "%s", stripped_name); - - *x += width + ws_spacing; -} - -static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) { - int width, height; - get_text_size(window->cairo, window->font, &width, &height, - window->scale, false, "%s", config->mode); - - // background - cairo_set_source_u32(window->cairo, config->colors.binding_mode.background); - cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_fill(window->cairo); - - // border - cairo_set_source_u32(window->cairo, config->colors.binding_mode.border); - cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_stroke(window->cairo); - - // text - cairo_set_source_u32(window->cairo, config->colors.binding_mode.text); - cairo_move_to(window->cairo, (int)pos + ws_horizontal_padding, margin); - pango_printf(window->cairo, window->font, window->scale, - false, "%s", config->mode); -} - -void render(struct output *output, struct config *config, struct status_line *line) { - int i; - - struct window *window = output->window; - cairo_t *cairo = window->cairo; - bool is_focused = output->focused; - - // Clear cairo_save(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); cairo_restore(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - - // Background - if (is_focused) { + if (output->focused) { cairo_set_source_u32(cairo, config->colors.focused_background); } else { cairo_set_source_u32(cairo, config->colors.background); } cairo_paint(cairo); -#ifdef ENABLE_TRAY - uint32_t tray_width = tray_render(output, config); -#else - const uint32_t tray_width = window->width * window->scale; -#endif - - // Command output - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_statusline); + // TODO: use actual height + return 20; +} + +void render_frame(struct swaybar *bar, + struct swaybar_output *output) { + cairo_surface_t *recorder = cairo_recording_surface_create( + CAIRO_CONTENT_COLOR_ALPHA, NULL); + cairo_t *cairo = cairo_create(recorder); + uint32_t height = render_to_cairo(cairo, bar, output); + if (height != output->height) { + // Reconfigure surface + zwlr_layer_surface_v1_set_size( + output->layer_surface, 0, height); + // TODO: this could infinite loop if the compositor assigns us a + // different height than what we asked for + wl_surface_commit(output->surface); + wl_display_roundtrip(bar->display); } else { - cairo_set_source_u32(cairo, config->colors.statusline); - } - - int width, height; - - if (line->protocol == TEXT) { - get_text_size(window->cairo, window->font, &width, &height, - window->scale, config->pango_markup, "%s", line->text_line); - cairo_move_to(cairo, tray_width - margin - width, margin); - pango_printf(window->cairo, window->font, window->scale, - config->pango_markup, "%s", line->text_line); - } else if (line->protocol == I3BAR && line->block_line) { - double pos = tray_width - 0.5; - bool edge = true; - for (i = line->block_line->length - 1; i >= 0; --i) { - struct status_block *block = line->block_line->items[i]; - if (block->full_text && block->full_text[0]) { - render_block(window, config, block, &pos, edge, is_focused); - edge = false; - } - } - } - - cairo_set_line_width(cairo, 1.0); - double x = 0.5; - - // Workspaces - if (config->workspace_buttons) { - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - render_workspace_button(window, config, ws, &x); - } - } - - // binding mode indicator - if (config->mode && config->binding_mode_indicator) { - render_binding_mode_indicator(window, config, x); - } -} - -void set_window_height(struct window *window, int height) { - int text_width, text_height; - get_text_size(window->cairo, window->font, - &text_width, &text_height, window->scale, false, - "Test string for measuring purposes"); - if (height > 0) { - margin = (height - text_height) / 2; - ws_vertical_padding = margin - 1.5; - } - window->height = (text_height + margin * 2) / window->scale; + // Replay recording into shm and send it off + output->current_buffer = get_next_buffer(bar->shm, + output->buffers, output->width, output->height); + cairo_t *shm = output->current_buffer->cairo; + cairo_set_source_surface(shm, recorder, 0.0, 0.0); + cairo_paint(shm); + wl_surface_attach(output->surface, + output->current_buffer->buffer, 0, 0); + wl_surface_damage(output->surface, 0, 0, output->width, output->height); + wl_surface_commit(output->surface); + wl_display_roundtrip(bar->display); + } + cairo_surface_destroy(recorder); + cairo_destroy(cairo); } -- cgit v1.2.3-70-g09d2 From 3a458cd7b55bdfad1b04a01064f4fe8fa86ed0de Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 00:49:59 -0400 Subject: Implement workspace button rendering --- swaybar/render.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 4 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 2eaa0195..226e4ce3 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -10,8 +10,79 @@ #include "swaybar/render.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, - struct swaybar_output *output) { +static const char *strip_workspace_number(const char *ws_name) { + size_t len = strlen(ws_name); + for (size_t i = 0; i < len; ++i) { + if (ws_name[i] < '0' || ws_name[i] > '9') { + if (':' == ws_name[i] && i < len - 1 && i > 0) { + return ws_name + i + 1; + } + return ws_name; + } + } + return ws_name; +} + +static uint32_t render_workspace_button(cairo_t *cairo, + struct swaybar_config *config, struct swaybar_workspace *ws, + double *x, uint32_t height) { + static const int ws_horizontal_padding = 5; + static const double ws_vertical_padding = 1.5; + static const int ws_spacing = 1; + + const char *name = ws->name; + if (config->strip_workspace_numbers) { + name = strip_workspace_number(ws->name); + } + + struct box_colors box_colors; + if (ws->urgent) { + box_colors = config->colors.urgent_workspace; + } else if (ws->focused) { + box_colors = config->colors.focused_workspace; + } else if (ws->visible) { + box_colors = config->colors.active_workspace; + } else { + box_colors = config->colors.inactive_workspace; + } + + int text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, true, "%s", name); + uint32_t ideal_height = ws_vertical_padding * 2 + text_height; + if (height < ideal_height) { + height = ideal_height; + } + uint32_t width = ws_horizontal_padding * 2 + text_width; + + cairo_set_source_u32(cairo, box_colors.background); + cairo_rectangle(cairo, *x, 0, width - 1, height); + cairo_fill(cairo); + + cairo_set_source_u32(cairo, box_colors.border); + cairo_rectangle(cairo, *x, 0, width - 1, height); + cairo_stroke(cairo); + + double text_y = height / 2.0 - text_height / 2.0; + cairo_set_source_u32(cairo, box_colors.text); + cairo_move_to(cairo, (int)*x + ws_horizontal_padding, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, true, "%s", name); + + *x += width + ws_spacing; + return ideal_height; +} + +static void update_heights(uint32_t height, uint32_t *min, uint32_t *max) { + if (*min < height) { + *min = height; + } + if (height > *max) { + *max = height; + } +} + +static uint32_t render_to_cairo(cairo_t *cairo, + struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; cairo_save(cairo); @@ -27,8 +98,20 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, } cairo_paint(cairo); - // TODO: use actual height - return 20; + uint32_t min_height = output->height, max_height = output->height; + + double x = 0; + if (config->workspace_buttons) { + struct swaybar_workspace *ws; + wl_list_for_each(ws, &output->workspaces, link) { + uint32_t h = render_workspace_button( + cairo, config, ws, &x, output->height); + update_heights(h, &min_height, &max_height); + } + } + + // TODO: Shrink via min_height if sane + return max_height; } void render_frame(struct swaybar *bar, @@ -41,6 +124,7 @@ void render_frame(struct swaybar *bar, // Reconfigure surface zwlr_layer_surface_v1_set_size( output->layer_surface, 0, height); + zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); // TODO: this could infinite loop if the compositor assigns us a // different height than what we asked for wl_surface_commit(output->surface); -- cgit v1.2.3-70-g09d2 From 37b61eff2df3c8b47b1304650d1fb204a62658db Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 10:59:33 -0400 Subject: Add binding mode indicator --- swaybar/ipc.c | 1 + swaybar/render.c | 77 +++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 55 insertions(+), 23 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 75f17953..3c2d6fbc 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -306,6 +306,7 @@ bool handle_ipc_event(struct swaybar *bar) { ipc_get_workspaces(bar); break; case IPC_EVENT_MODE: { + // TODO: interpret "pango_markup" field json_object *result = json_tokener_parse(resp->payload); if (!result) { free_ipc_response(resp); diff --git a/swaybar/render.c b/swaybar/render.c index 226e4ce3..beb4de40 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -10,6 +11,38 @@ #include "swaybar/render.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 int ws_spacing = 1; + +static uint32_t render_binding_mode_indicator(cairo_t *cairo, + struct swaybar_config *config, const char *mode, double x, + uint32_t height) { + int text_width, text_height; + get_text_size(cairo, config->font, &text_width, &text_height, + 1, true, "⚡ %s", mode); + uint32_t ideal_height = text_height + ws_vertical_padding * 2; + if (height < ideal_height) { + height = ideal_height; + } + + cairo_set_source_u32(cairo, config->colors.binding_mode.background); + cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, + height + ws_vertical_padding * 2); + cairo_fill(cairo); + + cairo_set_source_u32(cairo, config->colors.binding_mode.border); + cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, + height + ws_vertical_padding * 2); + cairo_stroke(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, (int)x + ws_horizontal_padding, (int)floor(text_y)); + pango_printf(cairo, config->font, 1, true, "⚡ %s", mode); + return ideal_height; +} + static const char *strip_workspace_number(const char *ws_name) { size_t len = strlen(ws_name); for (size_t i = 0; i < len; ++i) { @@ -26,10 +59,6 @@ static const char *strip_workspace_number(const char *ws_name) { static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_config *config, struct swaybar_workspace *ws, double *x, uint32_t height) { - static const int ws_horizontal_padding = 5; - static const double ws_vertical_padding = 1.5; - static const int ws_spacing = 1; - const char *name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); @@ -72,24 +101,10 @@ static uint32_t render_workspace_button(cairo_t *cairo, return ideal_height; } -static void update_heights(uint32_t height, uint32_t *min, uint32_t *max) { - if (*min < height) { - *min = height; - } - if (height > *max) { - *max = height; - } -} - static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; - cairo_save(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); - cairo_paint(cairo); - cairo_restore(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (output->focused) { cairo_set_source_u32(cairo, config->colors.focused_background); @@ -98,20 +113,30 @@ static uint32_t render_to_cairo(cairo_t *cairo, } cairo_paint(cairo); - uint32_t min_height = output->height, max_height = output->height; - + uint32_t max_height = 0; + /* + * Each render_* function takes the actual height of the bar, and returns + * the ideal height. If the actual height is too short, the render function + * can do whatever it wants - the buffer won't be committed. If the actual + * height is too tall, the render function should adapt its drawing to + * utilize the available space. + */ double x = 0; if (config->workspace_buttons) { struct swaybar_workspace *ws; wl_list_for_each(ws, &output->workspaces, link) { uint32_t h = render_workspace_button( cairo, config, ws, &x, output->height); - update_heights(h, &min_height, &max_height); + max_height = h > max_height ? h : max_height; } } + 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; + } - // TODO: Shrink via min_height if sane - return max_height; + return max_height > output->height ? max_height : output->height; } void render_frame(struct swaybar *bar, @@ -134,6 +159,12 @@ void render_frame(struct swaybar *bar, output->current_buffer = get_next_buffer(bar->shm, output->buffers, output->width, output->height); cairo_t *shm = output->current_buffer->cairo; + + cairo_save(shm); + cairo_set_operator(shm, CAIRO_OPERATOR_CLEAR); + cairo_paint(shm); + cairo_restore(shm); + cairo_set_source_surface(shm, recorder, 0.0, 0.0); cairo_paint(shm); wl_surface_attach(output->surface, -- cgit v1.2.3-70-g09d2 From 1e8faeec0263a7da311a13c56a0de34e47e66fa6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 11:58:54 -0400 Subject: Pixel-perfect rendering --- include/swaybar/config.h | 1 + swaybar/config.c | 1 + swaybar/ipc.c | 62 ++++++++++++++++++++++++++++++++---------------- swaybar/render.c | 48 ++++++++++++++++++++++++------------- 4 files changed, 75 insertions(+), 37 deletions(-) (limited to 'swaybar/render.c') diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 6bcefe64..7634cb16 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -24,6 +24,7 @@ struct swaybar_config { char *font; char *sep_symbol; char *mode; + bool mode_pango_markup; bool strip_workspace_numbers; bool binding_mode_indicator; bool wrap_scroll; diff --git a/swaybar/config.c b/swaybar/config.c index 83cf2309..802d0779 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -41,6 +41,7 @@ struct swaybar_config *init_config() { /* colors */ config->colors.background = 0x000000FF; + config->colors.focused_background = 0x000000FF; config->colors.statusline = 0xFFFFFFFF; config->colors.separator = 0x666666FF; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 3c2d6fbc..a260b798 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -48,58 +48,76 @@ static void ipc_parse_colors( 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)); + config->colors.background = parse_color( + json_object_get_string(background)); } if (statusline) { - config->colors.statusline = parse_color(json_object_get_string(statusline)); + config->colors.statusline = parse_color( + json_object_get_string(statusline)); } if (separator) { - config->colors.separator = parse_color(json_object_get_string(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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + 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)); + config->colors.binding_mode.text = parse_color( + json_object_get_string(binding_mode_text)); } } @@ -306,14 +324,13 @@ bool handle_ipc_event(struct swaybar *bar) { ipc_get_workspaces(bar); break; case IPC_EVENT_MODE: { - // TODO: interpret "pango_markup" field 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; + json_object *json_change, *json_pango_markup; if (json_object_object_get_ex(result, "change", &json_change)) { const char *change = json_object_get_string(json_change); free(bar->config->mode); @@ -328,6 +345,11 @@ bool handle_ipc_event(struct swaybar *bar) { free_ipc_response(resp); return false; } + if (json_object_object_get_ex(result, + "pango_markup", &json_pango_markup)) { + bar->config->mode_pango_markup = json_object_get_boolean( + json_pango_markup); + } json_object_put(result); break; } diff --git a/swaybar/render.c b/swaybar/render.c index beb4de40..ba22e9d4 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -13,33 +13,39 @@ static const int ws_horizontal_padding = 5; static const double ws_vertical_padding = 1.5; -static const int ws_spacing = 1; +static const double border_width = 1; static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_config *config, const char *mode, double x, uint32_t height) { int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, - 1, true, "⚡ %s", mode); - uint32_t ideal_height = text_height + ws_vertical_padding * 2; + 1, true, "%s", mode); + uint32_t ideal_height = text_height + ws_vertical_padding * 2 + + border_width * 2; if (height < ideal_height) { height = ideal_height; } + uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; cairo_set_source_u32(cairo, config->colors.binding_mode.background); - cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); + cairo_rectangle(cairo, x, 0, width, height); cairo_fill(cairo); cairo_set_source_u32(cairo, config->colors.binding_mode.border); - cairo_rectangle(cairo, x, 0, text_width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_stroke(cairo); + cairo_rectangle(cairo, x, 0, width, border_width); + cairo_fill(cairo); + cairo_rectangle(cairo, x, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, x + width - border_width, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, x, height - border_width, width, border_width); + cairo_fill(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, (int)x + ws_horizontal_padding, (int)floor(text_y)); - pango_printf(cairo, config->font, 1, true, "⚡ %s", mode); + 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; } @@ -78,26 +84,33 @@ static uint32_t render_workspace_button(cairo_t *cairo, int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, 1, true, "%s", name); - uint32_t ideal_height = ws_vertical_padding * 2 + text_height; + uint32_t ideal_height = ws_vertical_padding * 2 + text_height + + border_width * 2; if (height < ideal_height) { height = ideal_height; } - uint32_t width = ws_horizontal_padding * 2 + text_width; + uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; cairo_set_source_u32(cairo, box_colors.background); - cairo_rectangle(cairo, *x, 0, width - 1, height); + cairo_rectangle(cairo, *x, 0, width, height); cairo_fill(cairo); cairo_set_source_u32(cairo, box_colors.border); - cairo_rectangle(cairo, *x, 0, width - 1, height); - cairo_stroke(cairo); + cairo_rectangle(cairo, *x, 0, width, border_width); + cairo_fill(cairo); + cairo_rectangle(cairo, *x, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, *x + width - border_width, 0, border_width, height); + cairo_fill(cairo); + cairo_rectangle(cairo, *x, height - border_width, width, border_width); + cairo_fill(cairo); double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, box_colors.text); - cairo_move_to(cairo, (int)*x + ws_horizontal_padding, (int)floor(text_y)); + cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); pango_printf(cairo, config->font, 1, true, "%s", name); - *x += width + ws_spacing; + *x += width; return ideal_height; } @@ -167,6 +180,7 @@ void render_frame(struct swaybar *bar, cairo_set_source_surface(shm, recorder, 0.0, 0.0); cairo_paint(shm); + wl_surface_attach(output->surface, output->current_buffer->buffer, 0, 0); wl_surface_damage(output->surface, 0, 0, output->width, output->height); -- cgit v1.2.3-70-g09d2 From 531c175d3e60bf9dbfd538af1fd5eebb906c6f91 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 12:03:08 -0400 Subject: Respect user bar height preference This is an i3-gaps feature we support --- swaybar/render.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index ba22e9d4..317b0f65 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -158,6 +158,9 @@ void render_frame(struct swaybar *bar, CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); uint32_t height = render_to_cairo(cairo, bar, output); + if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) { + height = bar->config->height; + } if (height != output->height) { // Reconfigure surface zwlr_layer_surface_v1_set_size( -- cgit v1.2.3-70-g09d2 From 718502c815d0af81b4ab71fb6b86976b5403adf9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 13:49:46 -0400 Subject: Iterate over workspaces backwards --- swaybar/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 317b0f65..f797873c 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -137,7 +137,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, double x = 0; if (config->workspace_buttons) { struct swaybar_workspace *ws; - wl_list_for_each(ws, &output->workspaces, link) { + wl_list_for_each_reverse(ws, &output->workspaces, link) { uint32_t h = render_workspace_button( cairo, config, ws, &x, output->height); max_height = h > max_height ? h : max_height; -- cgit v1.2.3-70-g09d2 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/render.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-70-g09d2 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/render.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-70-g09d2 From d8104db8f1820bd3d4db8bf4f1ee51ae334ee6e7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 23:35:49 -0400 Subject: Early return from render functions if necessary --- swaybar/render.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index a5834f4b..3d9ef66b 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -30,7 +30,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, 1, config->pango_markup, "%s", status->text); uint32_t ideal_height = text_height + ws_vertical_padding * 2; if (height < ideal_height) { - height = ideal_height; + return ideal_height; } double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); @@ -70,7 +70,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; if (height < ideal_height) { - height = ideal_height; + return ideal_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -133,7 +133,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; if (height < ideal_height) { - height = ideal_height; + return ideal_height; } uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; -- cgit v1.2.3-70-g09d2 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/render.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-70-g09d2 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/render.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-70-g09d2 From 0cbd2a4f492b758f495af9f3ec4899dffe8d57d4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 14:58:30 -0400 Subject: Send click events for i3bar blocks --- include/swaybar/status_line.h | 6 ++++-- swaybar/i3bar.c | 22 ++++++++++++++++++++++ swaybar/render.c | 42 ++++++++++++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 14 deletions(-) (limited to 'swaybar/render.c') diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 038985a3..3538f49c 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -67,9 +67,11 @@ struct status_line { }; struct status_line *status_line_init(char *cmd); -void status_line_free(struct status_line *status); +void status_error(struct status_line *status, const char *text); bool status_handle_readable(struct status_line *status); +void status_line_free(struct status_line *status); bool i3bar_handle_readable(struct status_line *status); -void status_error(struct status_line *status, const char *text); +void i3bar_block_send_click(struct status_line *status, + struct i3bar_block *block, int x, int y, uint32_t button); #endif diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 41b71164..5e98c4aa 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -186,3 +186,25 @@ bool i3bar_handle_readable(struct status_line *status) { state->buffer_index = cur - state->buffer; return redraw; } + +void i3bar_block_send_click(struct status_line *status, + struct i3bar_block *block, int x, int y, uint32_t button) { + wlr_log(L_DEBUG, "block %s clicked", block->name ? block->name : "(nil)"); + if (!block->name || !status->i3bar_state.click_events) { + return; + } + + struct json_object *event_json = json_object_new_object(); + json_object_object_add(event_json, "name", + json_object_new_string(block->name)); + if (block->instance) { + json_object_object_add(event_json, "instance", + json_object_new_string(block->instance)); + } + + json_object_object_add(event_json, "button", json_object_new_int(button)); + json_object_object_add(event_json, "x", json_object_new_int(x)); + json_object_object_add(event_json, "y", json_object_new_int(y)); + dprintf(status->write_fd, "%s\n", json_object_to_json_string(event_json)); + json_object_put(event_json); +} diff --git a/swaybar/render.c b/swaybar/render.c index 3ad6d5d7..a5039a2e 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -89,9 +89,17 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, } } +static void block_hotspot_callback(struct swaybar_output *output, + int x, int y, uint32_t button, void *data) { + struct i3bar_block *block = data; + struct status_line *status = output->bar->status; + i3bar_block_send_click(status, block, x, y, button); +} + 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) { + 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; @@ -139,7 +147,15 @@ static uint32_t render_status_block(cairo_t *cairo, *x -= margin; } - // TODO: Create hotspot here + struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); + hotspot->x = *x; + hotspot->y = 0; + hotspot->width = width; + hotspot->height = height; + hotspot->callback = block_hotspot_callback; + hotspot->destroy = free; + hotspot->data = block; + wl_list_insert(&output->hotspots, &hotspot->link); double pos = *x; if (block->background) { @@ -208,13 +224,14 @@ static uint32_t render_status_block(cairo_t *cairo, } static uint32_t render_status_line_i3bar(cairo_t *cairo, - struct swaybar_config *config, struct status_line *status, - bool focused, double *x, uint32_t width, uint32_t height) { + struct swaybar_config *config, struct swaybar_output *output, + struct status_line *status, 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, + uint32_t h = render_status_block(cairo, config, output, block, x, height, focused, edge); max_height = h > max_height ? h : max_height; edge = false; @@ -223,8 +240,9 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, } static uint32_t render_status_line(cairo_t *cairo, - struct swaybar_config *config, struct status_line *status, - bool focused, double *x, uint32_t width, uint32_t height) { + struct swaybar_config *config, struct swaybar_output *output, + struct status_line *status, bool focused, + double *x, uint32_t width, uint32_t height) { switch (status->protocol) { case PROTOCOL_ERROR: return render_status_line_error(cairo, @@ -233,8 +251,8 @@ static uint32_t render_status_line(cairo_t *cairo, return render_status_line_text(cairo, config, status->text, focused, x, width, height); case PROTOCOL_I3BAR: - return render_status_line_i3bar(cairo, - config, status, focused, x, width, height); + return render_status_line_i3bar(cairo, config, output, status, + focused, x, width, height); case PROTOCOL_UNDEF: return 0; } @@ -344,8 +362,8 @@ static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; hotspot->y = 0; - hotspot->height = height; hotspot->width = width; + hotspot->height = height; hotspot->callback = workspace_hotspot_callback; hotspot->destroy = free; hotspot->data = strdup(name); @@ -391,7 +409,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, } x = output->width; if (bar->status) { - uint32_t h = render_status_line(cairo, config, 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; } -- cgit v1.2.3-70-g09d2 From c507727ad240b978c6e09e3aa9238080ca9a1c81 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 11:53:56 -0400 Subject: Fix use-after-free with block hotspots --- common/pango.c | 9 ++++++++- sway/tree/layout.c | 4 ++-- swaybar/i3bar.c | 4 +--- swaybar/render.c | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) (limited to 'swaybar/render.c') diff --git a/common/pango.c b/common/pango.c index 2ae7883c..658d2876 100644 --- a/common/pango.c +++ b/common/pango.c @@ -6,6 +6,7 @@ #include #include #include +#include "log.h" PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text, int32_t scale, bool markup) { @@ -13,7 +14,13 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, PangoAttrList *attrs; if (markup) { char *buf; - pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL); + GError *error = NULL; + if (!sway_assert(pango_parse_markup( + text, -1, 0, &attrs, &buf, NULL, &error), + "pango_parse_markup '%s' -> error %s", text, + error ? error->message : NULL)) { + return NULL; + } pango_layout_set_markup(layout, buf, -1); free(buf); } else { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc..e8363660 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -248,8 +248,8 @@ void arrange_windows(struct sway_container *container, struct wlr_box *area = &output->sway_output->usable_area; wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", area->width, area->height, area->x, area->y); - container->width = area->width; - container->height = area->height; + container->width = width = area->width; + container->height = height = area->height; container->x = x = area->x; container->y = y = area->y; wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 5e98c4aa..46459e24 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -30,9 +30,7 @@ static bool i3bar_parse_json(struct status_line *status, const char *text) { status_error(status, "[failed to parse i3bar json]"); return false; } - if (json_object_array_length(results) < 1) { - return true; - } + wlr_log(L_DEBUG, "Got i3bar json: '%s'", text); 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; diff --git a/swaybar/render.c b/swaybar/render.c index a5039a2e..a62e1d01 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -153,7 +153,7 @@ static uint32_t render_status_block(cairo_t *cairo, hotspot->width = width; hotspot->height = height; hotspot->callback = block_hotspot_callback; - hotspot->destroy = free; + hotspot->destroy = NULL; hotspot->data = block; wl_list_insert(&output->hotspots, &hotspot->link); @@ -227,9 +227,9 @@ 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 height) { - struct i3bar_block *block; uint32_t max_height = 0; bool edge = true; + struct i3bar_block *block; wl_list_for_each_reverse(block, &status->blocks, link) { uint32_t h = render_status_block(cairo, config, output, block, x, height, focused, edge); @@ -376,6 +376,7 @@ 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) { -- cgit v1.2.3-70-g09d2 From ef50d84be1180a7ddd73e1273ebb77503b3f36c4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 13:53:40 -0400 Subject: Render blocks the correct order --- swaybar/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index a62e1d01..6f3b0788 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -230,7 +230,7 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, uint32_t max_height = 0; bool edge = true; struct i3bar_block *block; - wl_list_for_each_reverse(block, &status->blocks, link) { + wl_list_for_each(block, &status->blocks, link) { uint32_t h = render_status_block(cairo, config, output, block, x, height, focused, edge); max_height = h > max_height ? h : max_height; -- cgit v1.2.3-70-g09d2 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/render.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-70-g09d2 From c4e92c81f5ce0adbc3320c578dc926a8004d3b75 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 21:57:47 -0400 Subject: Adjust height calculation, naming --- swaybar/render.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index bf144d5c..1f84fdba 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -20,12 +20,12 @@ 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 height) { + const char *error, double *x, uint32_t width, uint32_t surface_height) { if (!error) { return 0; } - height *= output->scale; + uint32_t height = surface_height * output->scale; cairo_set_source_u32(cairo, 0xFF0000FF); @@ -37,7 +37,7 @@ static uint32_t render_status_line_error(cairo_t *cairo, &text_width, &text_height, output->scale, false, "%s", error); uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } *x -= text_width + margin; @@ -52,12 +52,12 @@ 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 height) { + uint32_t width, uint32_t surface_height) { if (!text) { return 0; } - height *= output->scale; + uint32_t height = surface_height * output->scale; cairo_set_source_u32(cairo, focused ? config->colors.focused_statusline : config->colors.statusline); @@ -70,7 +70,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, int margin = 3 * output->scale; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } @@ -117,12 +117,12 @@ static void block_hotspot_callback(struct swaybar_output *output, 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) { + uint32_t surface_height, bool focused, bool edge) { if (!block->full_text || !*block->full_text) { return 0; } - 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, @@ -138,7 +138,7 @@ static uint32_t render_status_block(cairo_t *cairo, double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } @@ -256,13 +256,13 @@ 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 height) { + double *x, uint32_t width, uint32_t surface_height) { uint32_t max_height = 0; bool edge = true; struct i3bar_block *block; wl_list_for_each(block, &status->blocks, link) { uint32_t h = render_status_block(cairo, config, output, - block, x, height, focused, edge); + block, x, surface_height, focused, edge); max_height = h > max_height ? h : max_height; edge = false; } @@ -272,17 +272,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 height) { + double *x, uint32_t width, uint32_t surface_height) { switch (status->protocol) { case PROTOCOL_ERROR: - return render_status_line_error(cairo, - output, config, status->text, x, width, height); + return render_status_line_error(cairo, output, config, + status->text, x, width, surface_height); case PROTOCOL_TEXT: - return render_status_line_text(cairo, - output, config, status->text, focused, x, width, height); + return render_status_line_text(cairo, output, config, + status->text, focused, x, width, surface_height); case PROTOCOL_I3BAR: - return render_status_line_i3bar(cairo, config, output, status, - focused, x, width, height); + return render_status_line_i3bar(cairo, config, output, + status, focused, x, width, surface_height); case PROTOCOL_UNDEF: return 0; } @@ -291,9 +291,9 @@ static uint32_t render_status_line(cairo_t *cairo, static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - const char *mode, double x, uint32_t height) { + const char *mode, double x, uint32_t surface_height) { - 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, @@ -305,7 +305,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -351,7 +351,7 @@ static void workspace_hotspot_callback(struct swaybar_output *output, static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, - struct swaybar_workspace *ws, double *x, uint32_t height) { + struct swaybar_workspace *ws, double *x, uint32_t surface_height) { const char *name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); @@ -368,7 +368,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, box_colors = config->colors.inactive_workspace; } - 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, @@ -380,7 +380,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - if (height < ideal_height / output->scale) { + if (height < ideal_height) { return ideal_height / output->scale; } -- cgit v1.2.3-70-g09d2 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/render.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-70-g09d2 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/render.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-70-g09d2 From 257a831c726e7dadb23eca224ef405f374961695 Mon Sep 17 00:00:00 2001 From: db Date: Sun, 8 Apr 2018 15:48:59 +0200 Subject: Use full ws->name in swaybar hotspot callback If strip_workspace_numbers option is enabled, we must preserve the right workspace name for hotspot. --- swaybar/render.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 53e578f0..1c24e01f 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -352,6 +352,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, struct swaybar_workspace *ws, double *x, uint32_t surface_height) { const char *name = ws->name; + const char *whole_name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); } @@ -411,7 +412,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, hotspot->height = height; hotspot->callback = workspace_hotspot_callback; hotspot->destroy = free; - hotspot->data = strdup(name); + hotspot->data = strdup(whole_name); wl_list_insert(&output->hotspots, &hotspot->link); *x += width; -- cgit v1.2.3-70-g09d2 From 4ba6545c650712b1ec18854fa7f94995d0176637 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 8 Apr 2018 10:04:23 -0400 Subject: Fixup for #1773 --- swaybar/render.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 1c24e01f..d2175f0a 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -352,7 +352,6 @@ static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, struct swaybar_workspace *ws, double *x, uint32_t surface_height) { const char *name = ws->name; - const char *whole_name = ws->name; if (config->strip_workspace_numbers) { name = strip_workspace_number(ws->name); } @@ -412,7 +411,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, hotspot->height = height; hotspot->callback = workspace_hotspot_callback; hotspot->destroy = free; - hotspot->data = strdup(whole_name); + hotspot->data = strdup(ws->name); wl_list_insert(&output->hotspots, &hotspot->link); *x += width; -- cgit v1.2.3-70-g09d2 From 16e363e3e23e11674d06324efb4374320de40e63 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 8 Apr 2018 13:49:11 -0400 Subject: Fix swaybar HiDPI rounding issue --- swaybar/render.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index d2175f0a..28296f31 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -37,8 +37,9 @@ static uint32_t render_status_line_error(cairo_t *cairo, &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 / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } *x -= text_width + margin; @@ -46,7 +47,7 @@ static uint32_t render_status_line_error(cairo_t *cairo, cairo_move_to(cairo, *x, (int)floor(text_y)); pango_printf(cairo, config->font, output->scale, false, "%s", error); *x -= margin; - return ideal_height / output->scale; + return surface_height; } static uint32_t render_status_line_text(cairo_t *cairo, @@ -69,8 +70,9 @@ static uint32_t render_status_line_text(cairo_t *cairo, int margin = 3 * output->scale; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } *x -= text_width + margin; @@ -79,7 +81,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, pango_printf(cairo, config->font, output->scale, config->pango_markup, "%s", text); *x -= margin; - return ideal_height / output->scale; + return surface_height; } static void render_sharp_line(cairo_t *cairo, uint32_t color, @@ -137,8 +139,9 @@ static uint32_t render_status_block(cairo_t *cairo, double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } *x -= width; @@ -249,7 +252,7 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_stroke(cairo); } } - return ideal_height / output->scale; + return surface_height; } static uint32_t render_status_line_i3bar(cairo_t *cairo, @@ -291,7 +294,6 @@ static uint32_t render_status_line(cairo_t *cairo, static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_output *output, struct swaybar_config *config, const char *mode, double x, uint32_t surface_height) { - uint32_t height = surface_height * output->scale; int text_width, text_height; @@ -304,8 +306,9 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; @@ -327,7 +330,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, 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, output->scale, true, "%s", mode); - return ideal_height / output->scale; + return surface_height; } static const char *strip_workspace_number(const char *ws_name) { @@ -379,8 +382,9 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - if (height < ideal_height) { - return ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height / output->scale; + if (surface_height < ideal_surface_height) { + return ideal_surface_height; } uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; @@ -415,7 +419,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, wl_list_insert(&output->hotspots, &hotspot->link); *x += width; - return height / output->scale; + return surface_height; } static uint32_t render_to_cairo(cairo_t *cairo, @@ -484,8 +488,7 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { } if (height != output->height) { // Reconfigure surface - zwlr_layer_surface_v1_set_size( - output->layer_surface, 0, height); + zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); // TODO: this could infinite loop if the compositor assigns us a // different height than what we asked for -- cgit v1.2.3-70-g09d2 From 1a0d367f227fddd026ddf2a1bd21c5edbb111b00 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 10 Apr 2018 16:08:08 +1000 Subject: Fix swaybar not showing all status blocks. --- swaybar/render.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 28296f31..8681532a 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -154,15 +154,14 @@ static uint32_t render_status_block(cairo_t *cairo, block_width += block->border_right + margin; } - int sep_width; + int sep_width, sep_height; if (!edge) { if (config->sep_symbol) { - int _height; - get_text_size(cairo, config->font, &sep_width, &_height, + get_text_size(cairo, config->font, &sep_width, &sep_height, output->scale, false, "%s", config->sep_symbol); - uint32_t _ideal_height = _height + ws_vertical_padding * 2; - if ((uint32_t)_height < _ideal_height / output->scale) { - return _height / output->scale; + uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; + if (_ideal_height * output->scale > height) { + return _ideal_height; } if (sep_width > block->separator_block_width) { block->separator_block_width = sep_width + margin * 2; @@ -240,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); + cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0); pango_printf(cairo, config->font, output->scale, false, "%s", config->sep_symbol); } else { -- cgit v1.2.3-70-g09d2 From 7dfc0409ebd14f256294118ded769cf4df56e758 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 11 Apr 2018 08:34:21 +1000 Subject: Check height in surface local coordinates and rename some variables. --- swaybar/render.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 8681532a..3fd8da0b 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -159,9 +159,10 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, output->scale, false, "%s", config->sep_symbol); - uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; - if (_ideal_height * output->scale > height) { - return _ideal_height; + uint32_t _ideal_surface_height = ws_vertical_padding * 2 + + sep_height; + if (_ideal_surface_height > surface_height) { + return _ideal_surface_height; } if (sep_width > block->separator_block_width) { block->separator_block_width = sep_width + margin * 2; -- cgit v1.2.3-70-g09d2 From 5785170421dc38437acde8bb61068cd16fda716c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 10 Apr 2018 22:18:54 -0400 Subject: Fix separator height calculation Fixes #1796 Also rearranged this code to more closely mirror the similar code above so future discrepancies are easier to spot. --- swaybar/render.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 3fd8da0b..26248d35 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -159,9 +159,9 @@ static uint32_t render_status_block(cairo_t *cairo, if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, output->scale, false, "%s", config->sep_symbol); - uint32_t _ideal_surface_height = ws_vertical_padding * 2 - + sep_height; - if (_ideal_surface_height > surface_height) { + uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; + uint32_t _ideal_surface_height = _ideal_height / output->scale; + if (surface_height < _ideal_surface_height) { return _ideal_surface_height; } if (sep_width > block->separator_block_width) { -- cgit v1.2.3-70-g09d2