The format string set with "title_format" can contain the placeholder "%title" which will be replaced with the actual window title.
By not overwriting window->name itself, we make sure that assignment matching still works as expected.
fixes #1723
/** The name of the window. */
i3String *name;
+ /** The format with which the window's name should be displayed. */
+ char *title_format;
/** The WM_WINDOW_ROLE of this window (for example, the pidgin buddy window
* sets "buddy list"). Useful to match specific windows in assignments or
*/
void i3string_set_markup(i3String *str, bool is_markup);
+/**
+ * Escape pango markup characters in the given string.
+ */
+i3String *i3string_escape_markup(i3String *str);
+
/**
* Returns the number of glyphs in an i3String.
*
*/
void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background);
+/**
+ * Returns true if and only if the current font is a pango font.
+ *
+ */
+bool font_is_pango(void);
+
/**
* Draws text onto the specified X drawable (normally a pixmap) at the
* specified coordinates (from the top left corner of the leftmost, uppermost
}
}
+/*
+ * Returns true if and only if the current font is a pango font.
+ *
+ */
+bool font_is_pango(void) {
+#if PANGO_SUPPORT
+ return savedFont->type == FONT_TYPE_PANGO;
+#else
+ return false;
+#endif
+}
+
static int predict_text_width_xcb(const xcb_char2b_t *text, size_t text_len);
static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawable_t drawable,
#include <stdlib.h>
#include <string.h>
+#if PANGO_SUPPORT
+#include <glib.h>
+#endif
+
#include "libi3.h"
struct _i3String {
str->is_markup = is_markup;
}
+/*
+ * Escape pango markup characters in the given string.
+ */
+i3String *i3string_escape_markup(i3String *str) {
+#if PANGO_SUPPORT
+ const char *text = i3string_as_utf8(str);
+ return i3string_from_utf8(g_markup_escape_text(text, -1));
+#else
+ return str;
+#endif
+}
+
/*
* Returns the number of glyphs in an i3String.
*
*
*/
void cmd_title_format(I3_CMD, char *format) {
- DLOG("setting title_format to %s\n", format);
+ DLOG("setting title_format to \"%s\"\n", format);
+ HANDLE_EMPTY_MATCH;
+
+ owindow *current;
+ TAILQ_FOREACH(current, &owindows, owindows) {
+ if (current->con->window == NULL)
+ continue;
+
+ DLOG("setting title_format for %p / %s\n", current->con, current->con->name);
+ FREE(current->con->window->title_format);
+
+ /* If we only display the title without anything else, we can skip the parsing step,
+ * so we remove the title format altogether. */
+ if (strcasecmp(format, "%title") != 0)
+ current->con->window->title_format = sstrdup(format);
+
+ /* Make sure the window title is redrawn immediately. */
+ current->con->window->name_x_changed = true;
+ }
cmd_output->needs_tree_render = true;
ysuccess(true);
free(event);
}
+static i3String *parse_title_format(char *format, i3String *_title) {
+ /* We need to ensure that we only escape the window title if pango
+ * is used by the current font. */
+ const bool is_markup = font_is_pango();
+
+ i3String *title = is_markup ? i3string_escape_markup(_title) : _title;
+ const char *escaped_title = i3string_as_utf8(title);
+
+ /* We have to first iterate over the string to see how much buffer space
+ * we need to allocate. */
+ int buffer_len = strlen(format) + 1;
+ for (char *walk = format; *walk != '\0'; walk++) {
+ if (STARTS_WITH(walk, "%title")) {
+ buffer_len = buffer_len - strlen("%title") + strlen(escaped_title);
+ walk += strlen("%title") - 1;
+ }
+ }
+
+ /* Now we can parse the format string. */
+ char buffer[buffer_len];
+ char *outwalk = buffer;
+ for (char *walk = format; *walk != '\0'; walk++) {
+ if (*walk != '%') {
+ *(outwalk++) = *walk;
+ continue;
+ }
+
+ if (STARTS_WITH(walk + 1, "title")) {
+ outwalk += sprintf(outwalk, "%s", escaped_title);
+ walk += strlen("title");
+ }
+ }
+ *outwalk = '\0';
+
+ i3String *formatted = i3string_from_utf8(buffer);
+ i3string_set_markup(formatted, is_markup);
+ return formatted;
+}
+
/*
* Draws the decoration of the given container onto its parent.
*
I3STRING_FREE(mark);
}
- draw_text(win->name,
+ i3String *title = win->title_format == NULL ? win->name : parse_title_format(win->title_format, win->name);
+ draw_text(title,
parent->pixmap, parent->pm_gc,
con->deco_rect.x + logical_px(2) + indent_px, con->deco_rect.y + text_offset_y,
con->deco_rect.width - logical_px(2) - indent_px - mark_width - logical_px(2));
+ if (win->title_format != NULL)
+ I3STRING_FREE(title);
after_title:
/* Since we don’t clip the text at all, it might in some cases be painted