]> git.sur5r.net Git - i3/i3/commitdiff
Make pango markup in mode names optional with a flag.
authorIngo Bürk <ingo.buerk@tngtech.com>
Mon, 12 Oct 2015 21:43:47 +0000 (23:43 +0200)
committerIngo Bürk <ingo.buerk@tngtech.com>
Tue, 13 Oct 2015 07:23:30 +0000 (09:23 +0200)
This introduces the flag "--pango" on the mode config directive to
explicitly enable pango markup for mode names. Not setting this will
cause the mode name to be rendered as is.
This fixes a regression in 4.11 where mode names containing characters
such as '<' would break user's configs as they didn't escape these
characters.

fixes #1992

docs/ipc
i3bar/src/mode.c
include/bindings.h
include/config.h
include/config_directives.h
parser-specs/config.spec
src/bindings.c
src/config_directives.c
testcases/t/201-config-parser.t

index 5113d79bf60abc178c798ab1f33ca30873fa7b9b..1813e53a863e2a2561599cb62be0ee1324f4e138 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -717,11 +717,15 @@ This event consists of a single serialized map containing a property
 This event consists of a single serialized map containing a property
 +change (string)+ which holds the name of current mode in use. The name
 is the same as specified in config when creating a mode. The default
-mode is simply named default.
+mode is simply named default. It contains a second property, +pango_markup+, which
+defines whether pango markup shall be used for displaying this mode.
 
 *Example:*
 ---------------------------
-{ "change": "default" }
+{
+  "change": "default",
+  "pango_markup": true
+}
 ---------------------------
 
 === window event
index 7f7537af7d086e6db8168df6943932fa6e5530f9..4b27b110ae826b04b6dc22b4578cdafcfabe1200 100644 (file)
@@ -20,6 +20,8 @@
 struct mode_json_params {
     char *json;
     char *cur_key;
+    char *name;
+    bool pango_markup;
     mode *mode;
 };
 
@@ -31,17 +33,35 @@ static int mode_string_cb(void *params_, const unsigned char *val, size_t len) {
     struct mode_json_params *params = (struct mode_json_params *)params_;
 
     if (!strcmp(params->cur_key, "change")) {
-        /* Save the name */
-        params->mode->name = i3string_from_markup_with_length((const char *)val, len);
-        /* Save its rendered width */
-        params->mode->width = predict_text_width(params->mode->name);
+        char *copy = smalloc(sizeof(const unsigned char) * (len + 1));
+        strncpy(copy, (const char *)val, len);
+        copy[len] = '\0';
 
-        DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
+        params->name = copy;
         FREE(params->cur_key);
+        return 1;
+    }
+
+    FREE(params->cur_key);
+    return 0;
+}
+
+/*
+ * Parse a boolean.
+ *
+ */
+static int mode_boolean_cb(void *params_, int val) {
+    struct mode_json_params *params = (struct mode_json_params *)params_;
 
+    if (strcmp(params->cur_key, "pango_markup") == 0) {
+        DLOG("Setting pango_markup to %d.\n", val);
+        params->pango_markup = val;
+
+        FREE(params->cur_key);
         return 1;
     }
 
+    FREE(params->cur_key);
     return 0;
 }
 
@@ -62,10 +82,27 @@ static int mode_map_key_cb(void *params_, const unsigned char *keyVal, size_t ke
     return 1;
 }
 
+static int mode_end_map_cb(void *params_) {
+    struct mode_json_params *params = (struct mode_json_params *)params_;
+
+    /* Save the name */
+    params->mode->name = i3string_from_utf8(params->name);
+    i3string_set_markup(params->mode->name, params->pango_markup);
+    /* Save its rendered width */
+    params->mode->width = predict_text_width(params->mode->name);
+
+    DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
+    FREE(params->cur_key);
+
+    return 1;
+}
+
 /* A datastructure to pass all these callbacks to yajl */
 static yajl_callbacks mode_callbacks = {
     .yajl_string = mode_string_cb,
+    .yajl_boolean = mode_boolean_cb,
     .yajl_map_key = mode_map_key_cb,
+    .yajl_end_map = mode_end_map_cb,
 };
 
 /*
index 88b4a6cc96ff347fb6b70a907779a1d081c1481d..e9e5dac922f40e5d80602d6cab756d83efc547ad 100644 (file)
@@ -25,7 +25,7 @@ const char *DEFAULT_BINDING_MODE;
  */
 Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
                            const char *release, const char *border, const char *whole_window,
-                           const char *command, const char *mode);
+                           const char *command, const char *mode, bool pango_markup);
 
 /**
  * Grab the bound keys (tell X to send us keypress events for those keycodes)
index fd6fe6c092d9511722054bbacc484080b6f1787f..6312d3d2dc13cf2873181427f6430de52ad2127d 100644 (file)
@@ -77,6 +77,7 @@ struct Variable {
  */
 struct Mode {
     char *name;
+    bool pango_markup;
     struct bindings_head *bindings;
 
     SLIST_ENTRY(Mode) modes;
index c0c70bb487fa4ed057163d54e8b1e76482e85a23..97b8b424840f3c80abfec8f9f5933db9b54ed9c9 100644 (file)
@@ -66,7 +66,7 @@ CFGFUN(new_window, const char *windowtype, const char *border, const long width)
 CFGFUN(workspace, const char *workspace, const char *output);
 CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command);
 
-CFGFUN(enter_mode, const char *mode);
+CFGFUN(enter_mode, const char *pango_markup, const char *mode);
 CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command);
 
 CFGFUN(bar_font, const char *font);
index b9542c8c3c9e14cee6c8fa690b43bc8905ca6e3e..2170ace32d6da3f6dc14c7acadd2e668d0f01c34 100644 (file)
@@ -326,8 +326,10 @@ state BINDCOMMAND:
 ################################################################################
 
 state MODENAME:
+  pango_markup = '--pango_markup'
+      ->
   modename = word
-      -> call cfg_enter_mode($modename); MODEBRACE
+      -> call cfg_enter_mode($pango_markup, $modename); MODEBRACE
 
 state MODEBRACE:
   end
index c0e010301c3cb373b40478b2ebe827f8c701f101..b5f3190146a78382131bf40ea15ebdb94a5b12c5 100644 (file)
@@ -27,7 +27,7 @@ const char *DEFAULT_BINDING_MODE = "default";
  * the list of modes.
  *
  */
-static struct Mode *mode_from_name(const char *name) {
+static struct Mode *mode_from_name(const char *name, bool pango_markup) {
     struct Mode *mode;
 
     /* Try to find the mode in the list of modes and return it */
@@ -39,6 +39,7 @@ static struct Mode *mode_from_name(const char *name) {
     /* If the mode was not found, create a new one */
     mode = scalloc(1, sizeof(struct Mode));
     mode->name = sstrdup(name);
+    mode->pango_markup = pango_markup;
     mode->bindings = scalloc(1, sizeof(struct bindings_head));
     TAILQ_INIT(mode->bindings);
     SLIST_INSERT_HEAD(&modes, mode, modes);
@@ -54,7 +55,7 @@ static struct Mode *mode_from_name(const char *name) {
  */
 Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
                            const char *release, const char *border, const char *whole_window,
-                           const char *command, const char *modename) {
+                           const char *command, const char *modename, bool pango_markup) {
     Binding *new_binding = scalloc(1, sizeof(Binding));
     DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release);
     new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
@@ -91,7 +92,7 @@ Binding *configure_binding(const char *bindtype, const char *modifiers, const ch
     if (group_bits_set > 1)
         ELOG("Keybinding has more than one Group specified, but your X server is always in precisely one group. The keybinding can never trigger.\n");
 
-    struct Mode *mode = mode_from_name(modename);
+    struct Mode *mode = mode_from_name(modename, pango_markup);
     TAILQ_INSERT_TAIL(mode->bindings, new_binding, bindings);
 
     return new_binding;
@@ -437,7 +438,8 @@ void switch_mode(const char *new_mode) {
         grab_all_keys(conn);
 
         char *event_msg;
-        sasprintf(&event_msg, "{\"change\":\"%s\"}", mode->name);
+        sasprintf(&event_msg, "{\"change\":\"%s\", \"pango_markup\":%s}",
+                  mode->name, (mode->pango_markup ? "true" : "false"));
 
         ipc_send_event("mode", I3_IPC_EVENT_MODE, event_msg);
         FREE(event_msg);
index cd0432fe06c31b6e2b068f416c1cebc77a30fba2..99b70db8998ceacad69b4d1ccc10818656870687 100644 (file)
@@ -108,7 +108,7 @@ CFGFUN(font, const char *font) {
 }
 
 CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command) {
-    configure_binding(bindtype, modifiers, key, release, border, whole_window, command, DEFAULT_BINDING_MODE);
+    configure_binding(bindtype, modifiers, key, release, border, whole_window, command, DEFAULT_BINDING_MODE, false);
 }
 
 /*******************************************************************************
@@ -116,12 +116,13 @@ CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, co
  ******************************************************************************/
 
 static char *current_mode;
+static bool current_mode_pango_markup;
 
 CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command) {
-    configure_binding(bindtype, modifiers, key, release, border, whole_window, command, current_mode);
+    configure_binding(bindtype, modifiers, key, release, border, whole_window, command, current_mode, current_mode_pango_markup);
 }
 
-CFGFUN(enter_mode, const char *modename) {
+CFGFUN(enter_mode, const char *pango_markup, const char *modename) {
     if (strcasecmp(modename, DEFAULT_BINDING_MODE) == 0) {
         ELOG("You cannot use the name %s for your mode\n", DEFAULT_BINDING_MODE);
         exit(1);
@@ -129,6 +130,7 @@ CFGFUN(enter_mode, const char *modename) {
     DLOG("\t now in mode %s\n", modename);
     FREE(current_mode);
     current_mode = sstrdup(modename);
+    current_mode_pango_markup = (pango_markup != NULL);
 }
 
 CFGFUN(exec, const char *exectype, const char *no_startup_id, const char *command) {
index a2b0a3a937dab2ff2701dd73f5724146c4c4fd53..7b3a181e2ed0439fe5ee2b1519662dd610ba53b5 100644 (file)
@@ -53,7 +53,7 @@ mode "meh" {
 EOT
 
 my $expected = <<'EOT';
-cfg_enter_mode(meh)
+cfg_enter_mode((null), meh)
 cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), (null), resize grow)
 cfg_mode_binding(bindcode, Mod1, 44, (null), (null), (null), resize shrink)
 cfg_mode_binding(bindsym, Mod1, x, --release, (null), (null), exec foo)
@@ -627,7 +627,7 @@ mode "yo" {
 EOT
 
 $expected = <<'EOT';
-cfg_enter_mode(yo)
+cfg_enter_mode((null), yo)
 cfg_mode_binding(bindsym, (null), x, (null), (null), (null), resize shrink left)
 ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', '}'
 ERROR: CONFIG: (in file <stdin>)