]> git.sur5r.net Git - i3/i3/commitdiff
Parse the title_format and display the customized window title if a format was set.
authorIngo Bürk <ingo.buerk@tngtech.com>
Wed, 10 Jun 2015 17:01:05 +0000 (19:01 +0200)
committerIngo Bürk <ingo.buerk@tngtech.com>
Mon, 29 Jun 2015 07:13:31 +0000 (09:13 +0200)
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

include/data.h
include/libi3.h
libi3/font.c
libi3/string.c
src/commands.c
src/x.c

index 6cb6babc56d5ec0668a55799bde0a3885f2f98ea..e08cdd4c484938c1c9dec5d32e12c7fc8dae2557 100644 (file)
@@ -363,6 +363,8 @@ struct Window {
 
     /** 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
index 3e6f8427d4f8e0f984e5d6c2964cd6413b1ff086..69c4452862a026b979e04d0796cb1aa18a0fb295 100644 (file)
@@ -243,6 +243,11 @@ bool i3string_is_markup(i3String *str);
  */
 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.
  *
@@ -381,6 +386,12 @@ xcb_char2b_t *convert_utf8_to_ucs2(char *input, size_t *real_strlen);
  */
 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
index 0f30e74eb517a4cf2d2253671984fa57d952d9e6..b502b52c6390c57dc5e9774ba269f33bce738716 100644 (file)
@@ -340,6 +340,18 @@ 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) {
+#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,
index 28575e1fb6bcaa2b4eb1625e0dff2456be8cf269..70244743283f33e9f8034682e1f2a01b26ce42a8 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#if PANGO_SUPPORT
+#include <glib.h>
+#endif
+
 #include "libi3.h"
 
 struct _i3String {
@@ -185,6 +189,18 @@ void i3string_set_markup(i3String *str, bool is_markup) {
     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.
  *
index 3790f50f0d5d3969013679feb06358fc6fdb1f25..71b48182e61ca1c47d4c100774f8b17d0c443c77 100644 (file)
@@ -1904,7 +1904,25 @@ void cmd_scratchpad_show(I3_CMD) {
  *
  */
 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);
diff --git a/src/x.c b/src/x.c
index 2dcffe6b15929ae8d25d6a656ae1017d8d122a20..ef6c734162c0431bc6dad0ee7bb56d17e9c78788 100644 (file)
--- a/src/x.c
+++ b/src/x.c
@@ -302,6 +302,45 @@ void x_window_kill(xcb_window_t window, kill_window_t kill_window) {
     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.
  *
@@ -549,10 +588,13 @@ void x_draw_decoration(Con *con) {
         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