X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fconfig.c;h=4ce45ad6f496acbdf2f0ffc21ae9ee291ff0e4a5;hb=f1560e5eb6d8d64b62e10e8f896f688b44392648;hp=c5846279658dcd7426d86c88b814de0041be3e3f;hpb=8d2799c251cc1c44f1429c36817c346fa56b9701;p=i3%2Fi3 diff --git a/src/config.c b/src/config.c index c5846279..4ce45ad6 100644 --- a/src/config.c +++ b/src/config.c @@ -6,8 +6,8 @@ * i3 - an improved dynamic tiling window manager * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE) * - * config.c: Configuration file (calling the parser (src/cfgparse.y) with the - * correct path, switching key bindings mode). + * config.c: Configuration file (calling the parser (src/config_parser.c) with + * the correct path, switching key bindings mode). * */ #include "all.h" @@ -26,27 +26,28 @@ struct barconfig_head barconfigs = TAILQ_HEAD_INITIALIZER(barconfigs); * */ void ungrab_all_keys(xcb_connection_t *conn) { - DLOG("Ungrabbing all keys\n"); - xcb_ungrab_key(conn, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY); + DLOG("Ungrabbing all keys\n"); + xcb_ungrab_key(conn, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY); } static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint32_t keycode) { - DLOG("Grabbing %d\n", keycode); - /* Grab the key in all combinations */ - #define GRAB_KEY(modifier) \ - do { \ - xcb_grab_key(conn, 0, root, modifier, keycode, \ - XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \ - } while (0) - int mods = bind->mods; - if ((bind->mods & BIND_MODE_SWITCH) != 0) { - mods &= ~BIND_MODE_SWITCH; - if (mods == 0) - mods = XCB_MOD_MASK_ANY; - } - GRAB_KEY(mods); - GRAB_KEY(mods | xcb_numlock_mask); - GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK); + DLOG("Grabbing %d with modifiers %d (with mod_mask_lock %d)\n", keycode, bind->mods, bind->mods | XCB_MOD_MASK_LOCK); + /* Grab the key in all combinations */ + #define GRAB_KEY(modifier) \ + do { \ + xcb_grab_key(conn, 0, root, modifier, keycode, \ + XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \ + } while (0) + int mods = bind->mods; + if ((bind->mods & BIND_MODE_SWITCH) != 0) { + mods &= ~BIND_MODE_SWITCH; + if (mods == 0) + mods = XCB_MOD_MASK_ANY; + } + GRAB_KEY(mods); + GRAB_KEY(mods | xcb_numlock_mask); + GRAB_KEY(mods | XCB_MOD_MASK_LOCK); + GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK); } /* @@ -54,29 +55,57 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint * or NULL if no such binding exists. * */ -Binding *get_binding(uint16_t modifiers, xcb_keycode_t keycode) { - Binding *bind; +Binding *get_binding(uint16_t modifiers, bool key_release, xcb_keycode_t keycode) { + Binding *bind; + if (!key_release) { + /* On a KeyPress event, we first reset all + * B_UPON_KEYRELEASE_IGNORE_MODS bindings back to B_UPON_KEYRELEASE */ TAILQ_FOREACH(bind, bindings, bindings) { - /* First compare the modifiers */ - if (bind->mods != modifiers) - continue; - - /* If a symbol was specified by the user, we need to look in - * the array of translated keycodes for the event’s keycode */ - if (bind->symbol != NULL) { - if (memmem(bind->translated_to, - bind->number_keycodes * sizeof(xcb_keycode_t), - &keycode, sizeof(xcb_keycode_t)) != NULL) - break; - } else { - /* This case is easier: The user specified a keycode */ - if (bind->keycode == keycode) - break; - } + if (bind->release == B_UPON_KEYRELEASE_IGNORE_MODS) + bind->release = B_UPON_KEYRELEASE; + } + } + + TAILQ_FOREACH(bind, bindings, bindings) { + /* First compare the modifiers (unless this is a + * B_UPON_KEYRELEASE_IGNORE_MODS binding and this is a KeyRelease + * event) */ + if (bind->mods != modifiers && + (bind->release != B_UPON_KEYRELEASE_IGNORE_MODS || + !key_release)) + continue; + + /* If a symbol was specified by the user, we need to look in + * the array of translated keycodes for the event’s keycode */ + if (bind->symbol != NULL) { + if (memmem(bind->translated_to, + bind->number_keycodes * sizeof(xcb_keycode_t), + &keycode, sizeof(xcb_keycode_t)) == NULL) + continue; + } else { + /* This case is easier: The user specified a keycode */ + if (bind->keycode != keycode) + continue; } - return (bind == TAILQ_END(bindings) ? NULL : bind); + /* If this keybinding is a KeyRelease binding, it matches the key which + * the user pressed. We therefore mark it as + * B_UPON_KEYRELEASE_IGNORE_MODS for later, so that the user can + * release the modifiers before the actual key and the KeyRelease will + * still be matched. */ + if (bind->release == B_UPON_KEYRELEASE && !key_release) + bind->release = B_UPON_KEYRELEASE_IGNORE_MODS; + + /* Check if the binding is for a KeyPress or a KeyRelease event */ + if ((bind->release == B_UPON_KEYPRESS && key_release) || + (bind->release >= B_UPON_KEYRELEASE && !key_release)) + continue; + + break; + } + + return (bind == TAILQ_END(bindings) ? NULL : bind); } /* @@ -133,22 +162,22 @@ void translate_keysyms(void) { * */ void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch) { - Binding *bind; - TAILQ_FOREACH(bind, bindings, bindings) { - if ((bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) == 0) || - (!bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) != 0)) - continue; - - /* The easy case: the user specified a keycode directly. */ - if (bind->keycode > 0) { - grab_keycode_for_binding(conn, bind, bind->keycode); - continue; - } - - xcb_keycode_t *walk = bind->translated_to; - for (int i = 0; i < bind->number_keycodes; i++) - grab_keycode_for_binding(conn, bind, *walk++); + Binding *bind; + TAILQ_FOREACH(bind, bindings, bindings) { + if ((bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) == 0) || + (!bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) != 0)) + continue; + + /* The easy case: the user specified a keycode directly. */ + if (bind->keycode > 0) { + grab_keycode_for_binding(conn, bind, bind->keycode); + continue; } + + xcb_keycode_t *walk = bind->translated_to; + for (uint32_t i = 0; i < bind->number_keycodes; i++) + grab_keycode_for_binding(conn, bind, *walk++); + } } /* @@ -156,22 +185,72 @@ void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch) { * */ void switch_mode(const char *new_mode) { - struct Mode *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; - LOG("Switching to mode %s\n", new_mode); + ungrab_all_keys(conn); + bindings = mode->bindings; + translate_keysyms(); + grab_all_keys(conn, false); - SLIST_FOREACH(mode, &modes, modes) { - if (strcasecmp(mode->name, new_mode) != 0) - continue; + char *event_msg; + sasprintf(&event_msg, "{\"change\":\"%s\"}", mode->name); + + ipc_send_event("mode", I3_IPC_EVENT_MODE, event_msg); + FREE(event_msg); + + return; + } - ungrab_all_keys(conn); - bindings = mode->bindings; - translate_keysyms(); - grab_all_keys(conn, false); - 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; } - ELOG("ERROR: Mode not found\n"); + 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); + } } /* @@ -377,6 +456,9 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, INIT_COLOR(config.client.unfocused, "#333333", "#222222", "#888888", "#292d2e"); INIT_COLOR(config.client.urgent, "#2f343a", "#900000", "#ffffff", "#900000"); + /* border and indicator color are ignored for placeholder contents */ + INIT_COLOR(config.client.placeholder, "#000000", "#0c0c0c", "#ffffff", "#000000"); + /* the last argument (indicator color) is ignored for bar colors */ INIT_COLOR(config.bar.focused, "#4c7899", "#285577", "#ffffff", "#000000"); INIT_COLOR(config.bar.unfocused, "#333333", "#222222", "#888888", "#000000"); @@ -384,9 +466,14 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, config.default_border = BS_NORMAL; config.default_floating_border = BS_NORMAL; + config.default_border_width = 2; /* Set default_orientation to NO_ORIENTATION for auto orientation. */ config.default_orientation = NO_ORIENTATION; + /* Set default urgency reset delay to 500ms */ + if (config.workspace_urgency_timer == 0) + config.workspace_urgency_timer = 0.5; + parse_configuration(override_configpath); if (reload) {