]> git.sur5r.net Git - i3/i3/blobdiff - src/config.c
Optionally change i3bar color on focused output, implements #2020
[i3/i3] / src / config.c
index a8e66314fbba2eff3e4c912dedb3a254a07df70e..c1c31e30a358168ecca5b053c0c8a41f6648633d 100644 (file)
@@ -4,16 +4,14 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * config.c: Configuration file (calling the parser (src/config_parser.c) with
  *           the correct path, switching key bindings mode).
  *
  */
 #include "all.h"
-
-/* We need Xlib for XStringToKeysym */
-#include <X11/Xlib.h>
+#include <xkbcommon/xkbcommon.h>
 
 char *current_configpath = NULL;
 Config config;
@@ -30,159 +28,41 @@ void ungrab_all_keys(xcb_connection_t *conn) {
     xcb_ungrab_key(conn, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY);
 }
 
-/*
- * Switches the key bindings to the given mode, if the mode exists
- *
- */
-void switch_mode(const char *new_mode) {
-    struct Mode *mode;
-
-    LOG("Switching to mode %s\n", new_mode);
-
-    SLIST_FOREACH(mode, &modes, modes) {
-        if (strcasecmp(mode->name, new_mode) != 0)
-            continue;
-
-        ungrab_all_keys(conn);
-        bindings = mode->bindings;
-        translate_keysyms();
-        grab_all_keys(conn, false);
-
-        char *event_msg;
-        sasprintf(&event_msg, "{\"change\":\"%s\"}", mode->name);
-
-        ipc_send_event("mode", I3_IPC_EVENT_MODE, event_msg);
-        FREE(event_msg);
-
-        return;
-    }
-
-    ELOG("ERROR: Mode not found\n");
-}
-
 /*
  * Sends the current bar configuration as an event to all barconfig_update listeners.
- * This update mechnism currently only includes the hidden_state and the mode in the config.
  *
  */
 void update_barconfig() {
     Barconfig *current;
     TAILQ_FOREACH(current, &barconfigs, configs) {
-        /* Build json message */
-        char *hidden_state;
-        switch (current->hidden_state) {
-            case S_SHOW:
-                hidden_state ="show";
-                break;
-            case S_HIDE:
-            default:
-                hidden_state = "hide";
-                break;
-        }
-
-        char *mode;
-        switch (current->mode) {
-            case M_HIDE:
-                mode ="hide";
-                break;
-            case M_INVISIBLE:
-                mode ="invisible";
-                break;
-            case M_DOCK:
-            default:
-                mode = "dock";
-                break;
-        }
-
-        /* Send an event to all barconfig listeners*/
-        char *event_msg;
-        sasprintf(&event_msg, "{ \"id\":\"%s\", \"hidden_state\":\"%s\", \"mode\":\"%s\" }", current->id, hidden_state, mode);
-
-        ipc_send_event("barconfig_update", I3_IPC_EVENT_BARCONFIG_UPDATE, event_msg);
-        FREE(event_msg);
+        ipc_send_barconfig_update_event(current);
     }
 }
 
-/*
- * Get the path of the first configuration file found. If override_configpath
- * is specified, that path is returned and saved for further calls. Otherwise,
- * checks the home directory first, then the system directory first, always
- * taking into account the XDG Base Directory Specification ($XDG_CONFIG_HOME,
- * $XDG_CONFIG_DIRS)
- *
- */
-static char *get_config_path(const char *override_configpath) {
-    char *xdg_config_home, *xdg_config_dirs, *config_path;
-
-    static const char *saved_configpath = NULL;
-
-    if (override_configpath != NULL) {
-        saved_configpath = override_configpath;
-        return sstrdup(saved_configpath);
-    }
-
-    if (saved_configpath != NULL)
-        return sstrdup(saved_configpath);
-
-    /* 1: check the traditional path under the home directory */
-    config_path = resolve_tilde("~/.i3/config");
-    if (path_exists(config_path))
-        return config_path;
-    free(config_path);
-
-    /* 2: check for $XDG_CONFIG_HOME/i3/config */
-    if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL)
-        xdg_config_home = "~/.config";
-
-    xdg_config_home = resolve_tilde(xdg_config_home);
-    sasprintf(&config_path, "%s/i3/config", xdg_config_home);
-    free(xdg_config_home);
-
-    if (path_exists(config_path))
-        return config_path;
-    free(config_path);
-
-    /* 3: check the traditional path under /etc */
-    config_path = SYSCONFDIR "/i3/config";
-    if (path_exists(config_path))
-        return sstrdup(config_path);
-
-    /* 4: check for $XDG_CONFIG_DIRS/i3/config */
-    if ((xdg_config_dirs = getenv("XDG_CONFIG_DIRS")) == NULL)
-        xdg_config_dirs = "/etc/xdg";
-
-    char *buf = sstrdup(xdg_config_dirs);
-    char *tok = strtok(buf, ":");
-    while (tok != NULL) {
-        tok = resolve_tilde(tok);
-        sasprintf(&config_path, "%s/i3/config", tok);
-        free(tok);
-        if (path_exists(config_path)) {
-            free(buf);
-            return config_path;
-        }
-        free(config_path);
-        tok = strtok(NULL, ":");
-    }
-    free(buf);
-
-    die("Unable to find the configuration file (looked at "
-            "~/.i3/config, $XDG_CONFIG_HOME/i3/config, "
-            SYSCONFDIR "/i3/config and $XDG_CONFIG_DIRS/i3/config)");
-}
-
 /*
  * Finds the configuration file to use (either the one specified by
  * override_configpath), the user’s one or the system default) and calls
  * parse_file().
  *
  */
-static void parse_configuration(const char *override_configpath) {
-    char *path = get_config_path(override_configpath);
+bool parse_configuration(const char *override_configpath, bool use_nagbar) {
+    char *path = get_config_path(override_configpath, true);
+    if (path == NULL) {
+        die("Unable to find the configuration file (looked at "
+            "~/.i3/config, $XDG_CONFIG_HOME/i3/config, " SYSCONFDIR "/i3/config and $XDG_CONFIG_DIRS/i3/config)");
+    }
+
     LOG("Parsing configfile %s\n", path);
     FREE(current_configpath);
     current_configpath = path;
-    parse_file(path);
+
+    /* initialize default bindings if we're just validating the config file */
+    if (!use_nagbar && bindings == NULL) {
+        bindings = scalloc(1, sizeof(struct bindings_head));
+        TAILQ_INIT(bindings);
+    }
+
+    return parse_file(path, use_nagbar);
 }
 
 /*
@@ -205,9 +85,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
             while (!TAILQ_EMPTY(bindings)) {
                 bind = TAILQ_FIRST(bindings);
                 TAILQ_REMOVE(bindings, bind, bindings);
-                FREE(bind->translated_to);
-                FREE(bind->command);
-                FREE(bind);
+                binding_free(bind);
             }
             FREE(bindings);
             SLIST_REMOVE(&modes, mode, Mode, modes);
@@ -218,8 +96,6 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
             assign = TAILQ_FIRST(&assignments);
             if (assign->type == A_TO_WORKSPACE)
                 FREE(assign->dest.workspace);
-            else if (assign->type == A_TO_OUTPUT)
-                FREE(assign->dest.output);
             else if (assign->type == A_COMMAND)
                 FREE(assign->dest.command);
             match_free(&(assign->match));
@@ -242,6 +118,10 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
             FREE(barconfig->font);
             FREE(barconfig->colors.background);
             FREE(barconfig->colors.statusline);
+            FREE(barconfig->colors.separator);
+            FREE(barconfig->colors.focused_background);
+            FREE(barconfig->colors.focused_statusline);
+            FREE(barconfig->colors.focused_separator);
             FREE(barconfig->colors.focused_workspace_border);
             FREE(barconfig->colors.focused_workspace_bg);
             FREE(barconfig->colors.focused_workspace_text);
@@ -254,11 +134,14 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
             FREE(barconfig->colors.urgent_workspace_border);
             FREE(barconfig->colors.urgent_workspace_bg);
             FREE(barconfig->colors.urgent_workspace_text);
+            FREE(barconfig->colors.binding_mode_border);
+            FREE(barconfig->colors.binding_mode_bg);
+            FREE(barconfig->colors.binding_mode_text);
             TAILQ_REMOVE(&barconfigs, barconfig, configs);
             FREE(barconfig);
         }
 
-        /* Clear workspace names */
+/* Clear workspace names */
 #if 0
         Workspace *ws;
         TAILQ_FOREACH(ws, workspaces, workspaces)
@@ -268,7 +151,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
         /* Invalidate pixmap caches in case font or colors changed */
         Con *con;
         TAILQ_FOREACH(con, &all_cons, all_cons)
-            FREE(con->deco_render_params);
+        FREE(con->deco_render_params);
 
         /* Get rid of the current font */
         free_font();
@@ -276,28 +159,28 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
 
     SLIST_INIT(&modes);
 
-    struct Mode *default_mode = scalloc(sizeof(struct Mode));
+    struct Mode *default_mode = scalloc(1, sizeof(struct Mode));
     default_mode->name = sstrdup("default");
-    default_mode->bindings = scalloc(sizeof(struct bindings_head));
+    default_mode->bindings = scalloc(1, sizeof(struct bindings_head));
     TAILQ_INIT(default_mode->bindings);
     SLIST_INSERT_HEAD(&modes, default_mode, modes);
 
     bindings = default_mode->bindings;
 
 #define REQUIRED_OPTION(name) \
-    if (config.name == NULL) \
+    if (config.name == NULL)  \
         die("You did not specify required configuration option " #name "\n");
 
     /* Clear the old config or initialize the data structure */
     memset(&config, 0, sizeof(config));
 
-    /* Initialize default colors */
+/* Initialize default colors */
 #define INIT_COLOR(x, cborder, cbackground, ctext, cindicator) \
-    do { \
-        x.border = get_colorpixel(cborder); \
-        x.background = get_colorpixel(cbackground); \
-        x.text = get_colorpixel(ctext); \
-        x.indicator = get_colorpixel(cindicator); \
+    do {                                                       \
+        x.border = get_colorpixel(cborder);                    \
+        x.background = get_colorpixel(cbackground);            \
+        x.text = get_colorpixel(ctext);                        \
+        x.indicator = get_colorpixel(cindicator);              \
     } while (0)
 
     config.client.background = get_colorpixel("#000000");
@@ -314,9 +197,12 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
     INIT_COLOR(config.bar.unfocused, "#333333", "#222222", "#888888", "#000000");
     INIT_COLOR(config.bar.urgent, "#2f343a", "#900000", "#ffffff", "#000000");
 
+    config.show_marks = true;
+
     config.default_border = BS_NORMAL;
     config.default_floating_border = BS_NORMAL;
-    config.default_border_width = 2;
+    config.default_border_width = logical_px(2);
+    config.default_floating_border_width = logical_px(2);
     /* Set default_orientation to NO_ORIENTATION for auto orientation. */
     config.default_orientation = NO_ORIENTATION;
 
@@ -324,11 +210,11 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
     if (config.workspace_urgency_timer == 0)
         config.workspace_urgency_timer = 0.5;
 
-    parse_configuration(override_configpath);
+    parse_configuration(override_configpath, true);
 
     if (reload) {
         translate_keysyms();
-        grab_all_keys(conn, false);
+        grab_all_keys(conn);
     }
 
     if (config.font.type == FONT_TYPE_NONE) {