typedef struct Config Config;
extern Config config;
extern bool config_use_lexer;
+extern SLIST_HEAD(modes_head, Mode) modes;
/**
* Part of the struct Config. It makes sense to group colors for background,
SLIST_ENTRY(Variable) variables;
};
+/**
+ * The configuration file can contain multiple sets of bindings. Apart from the
+ * default set (name == "default"), you can specify other sets and change the
+ * currently active set of bindings by using the "mode <name>" command.
+ *
+ */
+struct Mode {
+ char *name;
+ struct bindings_head *bindings;
+
+ SLIST_ENTRY(Mode) modes;
+};
+
/**
* Holds part of the configuration (the part which is not already in dedicated
* structures in include/data.h).
*/
void grab_all_keys(xcb_connection_t *conn);
+/**
+ * Switches the key bindings to the given mode, if the mode exists
+ *
+ */
+void switch_mode(xcb_connection_t *conn, const char *new_mode);
+
#endif
extern xcb_key_symbols_t *keysyms;
extern char **start_argv;
extern Display *xkbdpy;
-extern TAILQ_HEAD(bindings_head, Binding) bindings;
+extern TAILQ_HEAD(bindings_head, Binding) *bindings;
extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
extern TAILQ_HEAD(assignments_head, Assignment) assignments;
extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
bindline:
binding
{
- TAILQ_INSERT_TAIL(&bindings, $<binding>1, bindings);
+ TAILQ_INSERT_TAIL(bindings, $<binding>1, bindings);
}
;
mode:
TOKMODE WHITESPACE QUOTEDSTRING WHITESPACE '{' modelines '}'
{
+ if (strcasecmp($<string>3, "default") == 0) {
+ printf("You cannot use the name \"default\" for your mode\n");
+ exit(1);
+ }
printf("\t now in mode %s\n", $<string>3);
printf("\t current bindings = %p\n", current_bindings);
+ Binding *binding;
+ TAILQ_FOREACH(binding, current_bindings, bindings) {
+ printf("got binding on mods %d, keycode %d, symbol %s, command %s\n",
+ binding->mods, binding->keycode, binding->symbol, binding->command);
+ }
+
+ struct Mode *mode = scalloc(sizeof(struct Mode));
+ mode->name = strdup($<string>3);
+ mode->bindings = current_bindings;
+ current_bindings = NULL;
+ SLIST_INSERT_HEAD(&modes, mode, modes);
}
;
return;
}
+ if (STARTS_WITH(command, "mode ")) {
+ const char *rest = command + strlen("mode ");
+ switch_mode(conn, rest);
+ return;
+ }
+
/* Is it an <exit>? */
if (STARTS_WITH(command, "exit")) {
LOG("User issued exit-command, exiting without error.\n");
void parse_file(const char *f);
Config config;
+struct modes_head modes;
bool config_use_lexer = false;
*/
void grab_all_keys(xcb_connection_t *conn) {
Binding *bind;
- TAILQ_FOREACH(bind, &bindings, bindings) {
+ TAILQ_FOREACH(bind, bindings, bindings) {
/* The easy case: the user specified a keycode directly. */
if (bind->keycode > 0) {
grab_keycode_for_binding(conn, bind, bind->keycode);
}
}
+/*
+ * Switches the key bindings to the given mode, if the mode exists
+ *
+ */
+void switch_mode(xcb_connection_t *conn, 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;
+ grab_all_keys(conn);
+ return;
+ }
+
+ LOG("ERROR: Mode not found\n");
+}
+
/*
* Reads the configuration from ~/.i3/config or /etc/i3/config if not found.
*
/* First ungrab the keys */
ungrab_all_keys(conn);
- /* Clear the old binding and assignment lists */
+ struct Mode *mode;
Binding *bind;
- while (!TAILQ_EMPTY(&bindings)) {
- bind = TAILQ_FIRST(&bindings);
- TAILQ_REMOVE(&bindings, bind, bindings);
- FREE(bind->command);
- FREE(bind);
+ while (!SLIST_EMPTY(&modes)) {
+ mode = SLIST_FIRST(&modes);
+ FREE(mode->name);
+
+ /* Clear the old binding list */
+ bindings = mode->bindings;
+ while (!TAILQ_EMPTY(bindings)) {
+ bind = TAILQ_FIRST(bindings);
+ TAILQ_REMOVE(bindings, bind, bindings);
+ FREE(bind->command);
+ FREE(bind);
+ }
+ FREE(bindings);
+ SLIST_REMOVE(&modes, mode, Mode, modes);
}
struct Assignment *assign;
}
}
+ SLIST_INIT(&modes);
+
+ struct Mode *default_mode = scalloc(sizeof(struct Mode));
+ default_mode->name = sstrdup("default");
+ default_mode->bindings = scalloc(sizeof(struct bindings_head));
+ TAILQ_INIT(default_mode->bindings);
+ SLIST_INSERT_HEAD(&modes, default_mode, modes);
+
+ bindings = default_mode->bindings;
+
SLIST_HEAD(variables_head, Variable) variables;
#define OPTION_STRING(name) \
LOG("keycode = %d, symbol = %s, modifiers = %d, command = *%s*\n", new->keycode, new->symbol, modifiers, rest);
new->mods = modifiers;
new->command = sstrdup(rest);
- TAILQ_INSERT_TAIL(&bindings, new, bindings);
+ TAILQ_INSERT_TAIL(bindings, new, bindings);
continue;
}
/* Find the binding */
Binding *bind;
- TAILQ_FOREACH(bind, &bindings, bindings) {
+ TAILQ_FOREACH(bind, bindings, bindings) {
/* First compare the modifiers */
if (bind->mods != state_filtered)
continue;
/* No match? Then it was an actively grabbed key, that is with Mode_switch, and
the user did not press Mode_switch, so just pass it… */
- if (bind == TAILQ_END(&bindings)) {
+ if (bind == TAILQ_END(bindings)) {
xcb_allow_events(conn, ReplayKeyboard, event->time);
xcb_flush(conn);
return 1;
xcb_key_symbols_t *keysyms;
/* The list of key bindings */
-struct bindings_head bindings = TAILQ_HEAD_INITIALIZER(bindings);
+struct bindings_head *bindings;
/* The list of exec-lines */
struct autostarts_head autostarts = TAILQ_HEAD_INITIALIZER(autostarts);