diff --git a/docs/i3bar-protocol b/docs/i3bar-protocol index 0ca2fd82..8fd51ae9 100644 --- a/docs/i3bar-protocol +++ b/docs/i3bar-protocol @@ -119,7 +119,8 @@ click_events:: full_text:: The most simple block you can think of is one which just includes the only required key, the +full_text+ key. i3bar will display the string - value and that’s it. + value parsed as + https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup]. short_text:: Where appropriate, the +short_text+ (string) entry should also be provided. It will be used in case the status line needs to be shortened diff --git a/docs/userguide b/docs/userguide index 4b4dacc8..45b05a06 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1625,6 +1625,10 @@ container to the next/previous workspace and +move container to workspace curren See <> for how to move a container/workspace to a different RandR output. +Workspace names are parsed as +https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup] +by i3bar. + [[back_and_forth]] To switch back to the previously focused workspace, use +workspace back_and_forth+; likewise, you can move containers to the previously focused @@ -1646,6 +1650,7 @@ move [window|container] [to] workspace ------------------------- bindsym $mod+1 workspace 1 bindsym $mod+2 workspace 2 +bindsym $mod+3 workspace 3:vim ... bindsym $mod+Shift+1 move container to workspace 1 diff --git a/i3bar/src/child.c b/i3bar/src/child.c index d0f0c5fb..2f7dd76e 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -182,7 +182,7 @@ static int stdin_boolean(void *context, int val) { static int stdin_string(void *context, const unsigned char *val, size_t len) { parser_ctx *ctx = context; if (strcasecmp(ctx->last_map_key, "full_text") == 0) { - ctx->block.full_text = i3string_from_utf8_with_length((const char *)val, len); + ctx->block.full_text = i3string_from_markup_with_length((const char *)val, len); } if (strcasecmp(ctx->last_map_key, "color") == 0) { sasprintf(&(ctx->block.color), "%.*s", len, val); @@ -196,7 +196,7 @@ static int stdin_string(void *context, const unsigned char *val, size_t len) { ctx->block.align = ALIGN_LEFT; } } else if (strcasecmp(ctx->last_map_key, "min_width") == 0) { - i3String *text = i3string_from_utf8_with_length((const char *)val, len); + i3String *text = i3string_from_markup_with_length((const char *)val, len); ctx->block.min_width = (uint32_t)predict_text_width(text); i3string_free(text); } @@ -304,7 +304,7 @@ static void read_flat_input(char *buffer, int length) { buffer[length - 1] = '\0'; else buffer[length] = '\0'; - first->full_text = i3string_from_utf8(buffer); + first->full_text = i3string_from_markup(buffer); } static bool read_json_input(unsigned char *input, int length) { diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index e8184d40..45b511ff 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -123,12 +123,12 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t /* Offset may be equal to length, in which case display the number */ params->workspaces_walk->name = (offset < len - ? i3string_from_utf8_with_length(ws_name + offset, len - offset) - : i3string_from_utf8(ws_num)); + ? i3string_from_markup_with_length(ws_name + offset, len - offset) + : i3string_from_markup(ws_num)); } else { /* Default case: just save the name */ - params->workspaces_walk->name = i3string_from_utf8_with_length(ws_name, len); + params->workspaces_walk->name = i3string_from_markup_with_length(ws_name, len); } /* Save its rendered width */ diff --git a/include/libi3.h b/include/libi3.h index 7a2bdf58..c1a11dfc 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -141,6 +141,12 @@ int sasprintf(char **strp, const char *fmt, ...); */ i3String *i3string_from_utf8(const char *from_utf8); +/** + * Build an i3String from an UTF-8 encoded string in Pango markup. + * + */ +i3String *i3string_from_markup(const char *from_markup); + /** * Build an i3String from an UTF-8 encoded string with fixed length. * To be used when no proper NUL-terminaison is available. @@ -149,6 +155,13 @@ i3String *i3string_from_utf8(const char *from_utf8); */ i3String *i3string_from_utf8_with_length(const char *from_utf8, size_t num_bytes); +/** + * Build an i3String from an UTF-8 encoded string in Pango markup with fixed + * length. + * + */ +i3String *i3string_from_markup_with_length(const char *from_markup, size_t num_bytes); + /** * Build an i3String from an UCS-2 encoded string. * Returns the newly-allocated i3String. @@ -193,6 +206,11 @@ const xcb_char2b_t *i3string_as_ucs2(i3String *str); */ size_t i3string_get_num_bytes(i3String *str); +/** + * Whether the given i3String is in Pango markup. + */ +bool i3string_is_markup(i3String *str); + /** * Returns the number of glyphs in an i3String. * diff --git a/libi3/font.c b/libi3/font.c index a338f975..f2a7e1fb 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -102,7 +102,8 @@ static bool load_pango_font(i3Font *font, const char *desc) { * */ static void draw_text_pango(const char *text, size_t text_len, - xcb_drawable_t drawable, int x, int y, int max_width) { + xcb_drawable_t drawable, int x, int y, + int max_width, bool is_markup) { /* Create the Pango layout */ /* root_visual_type is cached in load_pango_font */ cairo_surface_t *surface = cairo_xcb_surface_create(conn, drawable, @@ -116,7 +117,10 @@ static void draw_text_pango(const char *text, size_t text_len, pango_layout_set_wrap(layout, PANGO_WRAP_CHAR); pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); - pango_layout_set_text(layout, text, text_len); + if (is_markup) + pango_layout_set_markup(layout, text, text_len); + else + pango_layout_set_text(layout, text, text_len); /* Do the drawing */ cairo_set_source_rgb(cr, pango_font_red, pango_font_green, pango_font_blue); @@ -135,7 +139,7 @@ static void draw_text_pango(const char *text, size_t text_len, * Calculate the text width using Pango rendering. * */ -static int predict_text_width_pango(const char *text, size_t text_len) { +static int predict_text_width_pango(const char *text, size_t text_len, bool is_markup) { /* Create a dummy Pango layout */ /* root_visual_type is cached in load_pango_font */ cairo_surface_t *surface = cairo_xcb_surface_create(conn, root_screen->root, root_visual_type, 1, 1); @@ -145,7 +149,12 @@ static int predict_text_width_pango(const char *text, size_t text_len) { /* Get the font width */ gint width; pango_layout_set_font_description(layout, savedFont->specific.pango_desc); - pango_layout_set_text(layout, text, text_len); + + if (is_markup) + pango_layout_set_markup(layout, text, text_len); + else + pango_layout_set_text(layout, text, text_len); + pango_cairo_update_layout(cr, layout); pango_layout_get_pixel_size(layout, &width, NULL); @@ -383,7 +392,7 @@ void draw_text(i3String *text, xcb_drawable_t drawable, case FONT_TYPE_PANGO: /* Render the text using Pango */ draw_text_pango(i3string_as_utf8(text), i3string_get_num_bytes(text), - drawable, x, y, max_width); + drawable, x, y, max_width, i3string_is_markup(text)); return; #endif default: @@ -422,7 +431,7 @@ void draw_text_ascii(const char *text, xcb_drawable_t drawable, case FONT_TYPE_PANGO: /* Render the text using Pango */ draw_text_pango(text, strlen(text), - drawable, x, y, max_width); + drawable, x, y, max_width, false); return; #endif default: @@ -518,7 +527,8 @@ int predict_text_width(i3String *text) { #if PANGO_SUPPORT case FONT_TYPE_PANGO: /* Calculate extents using Pango */ - return predict_text_width_pango(i3string_as_utf8(text), i3string_get_num_bytes(text)); + return predict_text_width_pango(i3string_as_utf8(text), i3string_get_num_bytes(text), + i3string_is_markup(text)); #endif default: assert(false); diff --git a/libi3/string.c b/libi3/string.c index 009312d6..afeca974 100644 --- a/libi3/string.c +++ b/libi3/string.c @@ -20,6 +20,7 @@ struct _i3String { xcb_char2b_t *ucs2; size_t num_glyphs; size_t num_bytes; + bool is_markup; }; /* @@ -39,6 +40,19 @@ i3String *i3string_from_utf8(const char *from_utf8) { return str; } +/* + * Build an i3String from an UTF-8 encoded string in Pango markup. + * + */ +i3String *i3string_from_markup(const char *from_markup) { + i3String *str = i3string_from_utf8(from_markup); + + /* Set the markup flag */ + str->is_markup = true; + + return str; +} + /* * Build an i3String from an UTF-8 encoded string with fixed length. * To be used when no proper NUL-terminaison is available. @@ -59,6 +73,20 @@ i3String *i3string_from_utf8_with_length(const char *from_utf8, size_t num_bytes return str; } +/* + * Build an i3String from an UTF-8 encoded string in Pango markup with fixed + * length. + * + */ +i3String *i3string_from_markup_with_length(const char *from_markup, size_t num_bytes) { + i3String *str = i3string_from_utf8_with_length(from_markup, num_bytes); + + /* set the markup flag */ + str->is_markup = true; + + return str; +} + /* * Build an i3String from an UCS-2 encoded string. * Returns the newly-allocated i3String. @@ -133,6 +161,13 @@ size_t i3string_get_num_bytes(i3String *str) { return str->num_bytes; } +/* + * Whether the given i3String is in Pango markup. + */ +bool i3string_is_markup(i3String *str) { + return str->is_markup; +} + /* * Returns the number of glyphs in an i3String. *