2012-10-07 16:32:50 +02:00
|
|
|
|
#undef I3__FILE__
|
|
|
|
|
#define I3__FILE__ "config_directives.c"
|
|
|
|
|
/*
|
|
|
|
|
* vim:ts=4:sw=4:expandtab
|
|
|
|
|
*
|
|
|
|
|
* i3 - an improved dynamic tiling window manager
|
2015-04-04 02:17:56 +02:00
|
|
|
|
* © 2009 Michael Stapelberg and contributors (see also: LICENSE)
|
2012-10-07 16:32:50 +02:00
|
|
|
|
*
|
2012-10-08 13:23:48 +02:00
|
|
|
|
* config_directives.c: all config storing functions (see config_parser.c)
|
2012-10-07 16:32:50 +02:00
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
#include <float.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
#include "all.h"
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Criteria functions.
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
static int criteria_next_state;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initializes the specified 'Match' data structure and the initial state of
|
|
|
|
|
* commands.c for matching target windows of a command.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
CFGFUN(criteria_init, int _state) {
|
|
|
|
|
criteria_next_state = _state;
|
|
|
|
|
|
|
|
|
|
DLOG("Initializing criteria, current_match = %p, state = %d\n", current_match, _state);
|
|
|
|
|
match_init(current_match);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(criteria_pop_state) {
|
|
|
|
|
result->next_state = criteria_next_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Interprets a ctype=cvalue pair and adds it to the current match
|
|
|
|
|
* specification.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
CFGFUN(criteria_add, const char *ctype, const char *cvalue) {
|
2015-09-27 09:42:26 +02:00
|
|
|
|
match_parse_property(current_match, ctype, cvalue);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Utility functions
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
static bool eval_boolstr(const char *str) {
|
|
|
|
|
return (strcasecmp(str, "1") == 0 ||
|
|
|
|
|
strcasecmp(str, "yes") == 0 ||
|
|
|
|
|
strcasecmp(str, "true") == 0 ||
|
|
|
|
|
strcasecmp(str, "on") == 0 ||
|
|
|
|
|
strcasecmp(str, "enable") == 0 ||
|
|
|
|
|
strcasecmp(str, "active") == 0);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-28 04:45:01 +01:00
|
|
|
|
/*
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
* A utility function to convert a string containing the group and modifiers to
|
|
|
|
|
* the corresponding bit mask.
|
2014-01-28 04:45:01 +01:00
|
|
|
|
*/
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
i3_event_state_mask_t event_state_from_str(const char *str) {
|
2012-10-08 13:23:48 +02:00
|
|
|
|
/* It might be better to use strtok() here, but the simpler strstr() should
|
|
|
|
|
* do for now. */
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
i3_event_state_mask_t result = 0;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
if (str == NULL)
|
|
|
|
|
return result;
|
|
|
|
|
if (strstr(str, "Mod1") != NULL)
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
result |= XCB_KEY_BUT_MASK_MOD_1;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
if (strstr(str, "Mod2") != NULL)
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
result |= XCB_KEY_BUT_MASK_MOD_2;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
if (strstr(str, "Mod3") != NULL)
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
result |= XCB_KEY_BUT_MASK_MOD_3;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
if (strstr(str, "Mod4") != NULL)
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
result |= XCB_KEY_BUT_MASK_MOD_4;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
if (strstr(str, "Mod5") != NULL)
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
result |= XCB_KEY_BUT_MASK_MOD_5;
|
2012-10-09 14:05:49 +02:00
|
|
|
|
if (strstr(str, "Control") != NULL ||
|
|
|
|
|
strstr(str, "Ctrl") != NULL)
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
result |= XCB_KEY_BUT_MASK_CONTROL;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
if (strstr(str, "Shift") != NULL)
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
result |= XCB_KEY_BUT_MASK_SHIFT;
|
|
|
|
|
|
|
|
|
|
if (strstr(str, "Group1") != NULL)
|
|
|
|
|
result |= (I3_XKB_GROUP_MASK_1 << 16);
|
|
|
|
|
if (strstr(str, "Group2") != NULL ||
|
|
|
|
|
strstr(str, "Mode_switch") != NULL)
|
|
|
|
|
result |= (I3_XKB_GROUP_MASK_2 << 16);
|
|
|
|
|
if (strstr(str, "Group3") != NULL)
|
|
|
|
|
result |= (I3_XKB_GROUP_MASK_3 << 16);
|
|
|
|
|
if (strstr(str, "Group4") != NULL)
|
|
|
|
|
result |= (I3_XKB_GROUP_MASK_4 << 16);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-07 16:32:50 +02:00
|
|
|
|
static char *font_pattern;
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(font, const char *font) {
|
2014-06-15 19:07:02 +02:00
|
|
|
|
config.font = load_font(font, true);
|
|
|
|
|
set_font(&config.font);
|
2012-10-07 16:32:50 +02:00
|
|
|
|
|
2014-06-15 19:07:02 +02:00
|
|
|
|
/* Save the font pattern for using it as bar font later on */
|
|
|
|
|
FREE(font_pattern);
|
|
|
|
|
font_pattern = sstrdup(font);
|
2012-10-07 16:32:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-02 03:43:46 +02:00
|
|
|
|
CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command) {
|
2015-10-12 23:43:47 +02:00
|
|
|
|
configure_binding(bindtype, modifiers, key, release, border, whole_window, command, DEFAULT_BINDING_MODE, false);
|
2012-10-07 16:32:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Mode handling
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
2014-01-28 04:45:01 +01:00
|
|
|
|
static char *current_mode;
|
2015-10-12 23:43:47 +02:00
|
|
|
|
static bool current_mode_pango_markup;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
|
2015-04-02 03:43:46 +02:00
|
|
|
|
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) {
|
2015-10-12 23:43:47 +02:00
|
|
|
|
configure_binding(bindtype, modifiers, key, release, border, whole_window, command, current_mode, current_mode_pango_markup);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-12 23:43:47 +02:00
|
|
|
|
CFGFUN(enter_mode, const char *pango_markup, const char *modename) {
|
2014-01-28 04:45:01 +01:00
|
|
|
|
if (strcasecmp(modename, DEFAULT_BINDING_MODE) == 0) {
|
|
|
|
|
ELOG("You cannot use the name %s for your mode\n", DEFAULT_BINDING_MODE);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
DLOG("\t now in mode %s\n", modename);
|
2014-01-28 04:45:01 +01:00
|
|
|
|
FREE(current_mode);
|
|
|
|
|
current_mode = sstrdup(modename);
|
2015-10-12 23:43:47 +02:00
|
|
|
|
current_mode_pango_markup = (pango_markup != NULL);
|
2012-10-07 16:32:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(exec, const char *exectype, const char *no_startup_id, const char *command) {
|
2014-06-15 19:07:02 +02:00
|
|
|
|
struct Autostart *new = smalloc(sizeof(struct Autostart));
|
|
|
|
|
new->command = sstrdup(command);
|
|
|
|
|
new->no_startup_id = (no_startup_id != NULL);
|
|
|
|
|
if (strcmp(exectype, "exec") == 0) {
|
|
|
|
|
TAILQ_INSERT_TAIL(&autostarts, new, autostarts);
|
|
|
|
|
} else {
|
|
|
|
|
TAILQ_INSERT_TAIL(&autostarts_always, new, autostarts_always);
|
|
|
|
|
}
|
2012-10-07 16:32:50 +02:00
|
|
|
|
}
|
2012-10-08 13:23:48 +02:00
|
|
|
|
|
|
|
|
|
CFGFUN(for_window, const char *command) {
|
|
|
|
|
if (match_is_empty(current_match)) {
|
|
|
|
|
ELOG("Match is empty, ignoring this for_window statement\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
DLOG("\t should execute command %s for the criteria mentioned above\n", command);
|
2015-08-03 11:50:13 +02:00
|
|
|
|
Assignment *assignment = scalloc(1, sizeof(Assignment));
|
2012-10-08 13:23:48 +02:00
|
|
|
|
assignment->type = A_COMMAND;
|
|
|
|
|
match_copy(&(assignment->match), current_match);
|
|
|
|
|
assignment->dest.command = sstrdup(command);
|
|
|
|
|
TAILQ_INSERT_TAIL(&assignments, assignment, assignments);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(floating_minimum_size, const long width, const long height) {
|
|
|
|
|
config.floating_minimum_width = width;
|
|
|
|
|
config.floating_minimum_height = height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(floating_maximum_size, const long width, const long height) {
|
|
|
|
|
config.floating_maximum_width = width;
|
|
|
|
|
config.floating_maximum_height = height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(floating_modifier, const char *modifiers) {
|
Use libxkbcommon for translating keysyms, support all XKB groups.
fixes #1835
This commit improves the translation of keysyms to keycodes by loading
keymaps using libxkbcommon-x11 and using libxkbcommon for figuring out
the keymap, depending on each keybinding’s modifiers. This way, the
upper layers of complex layouts are now usable with i3’s bindsym
directive, such as de_neo’s layer 3 and higher.
Furthermore, the commit generalizes the handling of different XKB
groups. We formerly had support only for two separate groups, the
default group 1, and group 2. While Mode_switch is only one way to
switch to group 2, we called the binding option Mode_switch. With this
commit, the new names Group1, Group2 (an alias for Mode_switch), Group3
and Group4 are introduced for configuring bindings. This is only useful
for advanced keyboard layouts, such as people loading two keyboard
layouts and switching between them (us, ru seems to be a popular
combination).
When grabbing keys, one can only specify the modifier mask, but not an
XKB state mask (or value), so we still dynamically unbind and re-bind
keys whenever the XKB group changes.
The commit was manually tested using the following i3 config:
bindsym Group4+n nop heya from group 4
bindsym Group3+n nop heya from group 3
bindsym Group2+n nop heya from group 2
bindsym n nop heya
bindsym shift+N nop explicit shift binding
bindsym shift+r nop implicit shift binding
bindcode Group2+38 nop fallback overwritten in group 2 only
bindcode 38 nop fallback
…with the following layout:
setxkbmap -layout "us,ua,ru,de" -variant ",winkeys,,neo" \
-option "grp:shift_caps_toggle,grp_led:scroll" \
-model pc104 -rules evdev
By default (xkb group 1, us layout), pressing “n” will result in the
“heya” message appearing. Pressing “a” will result in the “fallback”
message appearing. “j” is not triggered.
By pressing Shift+CapsLock you switch to the next group (xkb group 2, ua
layout). Pressing “a” will result in the “fallback overwritten in group
2 only” message, pressing “n” will still result in “heya”. “j” is not
triggered.
In the next group (xkb group 3, ru layout), pressing “a” will result in
the “fallback” message again, pressing “n” will result in “heya”,
“j” is not triggered.
In the last group (xkb group 4, de_neo layout), pressing “a” will still
result in “fallback”, pressing “n” will result in “heya”, pressing “j”
will result in “heya from group 4”.
Pressing shift+n results in “explicit shift binding”, pressing shift+r
results in “implicit shift binding”. This ensures that keysym
translation falls back to looking at non-shift keys (“r” can be used
instead of ”R”) and that the order of keybindings doesn’t play a role
(“bindsym n” does not override “bindsym shift+n”, even though it’s
specified earlier in the config).
The fallback behavior ensures use-cases such as ticket #1775 are still
covered.
Only binding keys when the X server is in the corresponding XKB group
ensures use-cases such as ticket #585 are still covered.
2015-08-23 22:49:32 +02:00
|
|
|
|
config.floating_modifier = event_state_from_str(modifiers);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(default_orientation, const char *orientation) {
|
|
|
|
|
if (strcmp(orientation, "horizontal") == 0)
|
|
|
|
|
config.default_orientation = HORIZ;
|
|
|
|
|
else if (strcmp(orientation, "vertical") == 0)
|
|
|
|
|
config.default_orientation = VERT;
|
2014-06-15 19:07:02 +02:00
|
|
|
|
else
|
|
|
|
|
config.default_orientation = NO_ORIENTATION;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(workspace_layout, const char *layout) {
|
|
|
|
|
if (strcmp(layout, "default") == 0)
|
|
|
|
|
config.default_layout = L_DEFAULT;
|
|
|
|
|
else if (strcmp(layout, "stacking") == 0 ||
|
|
|
|
|
strcmp(layout, "stacked") == 0)
|
|
|
|
|
config.default_layout = L_STACKED;
|
2014-06-15 19:07:02 +02:00
|
|
|
|
else
|
|
|
|
|
config.default_layout = L_TABBED;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(new_window, const char *windowtype, const char *border, const long width) {
|
|
|
|
|
int border_style;
|
|
|
|
|
int border_width;
|
|
|
|
|
|
|
|
|
|
if (strcmp(border, "1pixel") == 0) {
|
|
|
|
|
border_style = BS_PIXEL;
|
|
|
|
|
border_width = 1;
|
|
|
|
|
} else if (strcmp(border, "none") == 0) {
|
|
|
|
|
border_style = BS_NONE;
|
|
|
|
|
border_width = 0;
|
|
|
|
|
} else if (strcmp(border, "pixel") == 0) {
|
|
|
|
|
border_style = BS_PIXEL;
|
|
|
|
|
border_width = width;
|
|
|
|
|
} else {
|
|
|
|
|
border_style = BS_NORMAL;
|
|
|
|
|
border_width = width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strcmp(windowtype, "new_window") == 0) {
|
2014-08-11 09:45:35 +02:00
|
|
|
|
DLOG("default tiled border style = %d and border width = %d (%d physical px)\n",
|
|
|
|
|
border_style, border_width, logical_px(border_width));
|
2012-10-08 13:23:48 +02:00
|
|
|
|
config.default_border = border_style;
|
2014-08-11 09:45:35 +02:00
|
|
|
|
config.default_border_width = logical_px(border_width);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
} else {
|
2014-08-11 09:45:35 +02:00
|
|
|
|
DLOG("default floating border style = %d and border width = %d (%d physical px)\n",
|
|
|
|
|
border_style, border_width, logical_px(border_width));
|
2012-10-08 13:23:48 +02:00
|
|
|
|
config.default_floating_border = border_style;
|
2014-08-11 09:45:35 +02:00
|
|
|
|
config.default_floating_border_width = logical_px(border_width);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(hide_edge_borders, const char *borders) {
|
|
|
|
|
if (strcmp(borders, "vertical") == 0)
|
|
|
|
|
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
|
|
|
|
else if (strcmp(borders, "horizontal") == 0)
|
|
|
|
|
config.hide_edge_borders = ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE;
|
|
|
|
|
else if (strcmp(borders, "both") == 0)
|
|
|
|
|
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE | ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE;
|
|
|
|
|
else if (strcmp(borders, "none") == 0)
|
|
|
|
|
config.hide_edge_borders = ADJ_NONE;
|
|
|
|
|
else if (eval_boolstr(borders))
|
|
|
|
|
config.hide_edge_borders = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE;
|
2014-06-15 19:07:02 +02:00
|
|
|
|
else
|
|
|
|
|
config.hide_edge_borders = ADJ_NONE;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(focus_follows_mouse, const char *value) {
|
|
|
|
|
config.disable_focus_follows_mouse = !eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-24 18:03:05 +01:00
|
|
|
|
CFGFUN(mouse_warping, const char *value) {
|
|
|
|
|
if (strcmp(value, "none") == 0)
|
|
|
|
|
config.mouse_warping = POINTER_WARPING_NONE;
|
|
|
|
|
else if (strcmp(value, "output") == 0)
|
|
|
|
|
config.mouse_warping = POINTER_WARPING_OUTPUT;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(force_xinerama, const char *value) {
|
|
|
|
|
config.force_xinerama = eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(force_focus_wrapping, const char *value) {
|
|
|
|
|
config.force_focus_wrapping = eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(workspace_back_and_forth, const char *value) {
|
|
|
|
|
config.workspace_auto_back_and_forth = eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(fake_outputs, const char *outputs) {
|
|
|
|
|
config.fake_outputs = sstrdup(outputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(force_display_urgency_hint, const long duration_ms) {
|
|
|
|
|
config.workspace_urgency_timer = duration_ms / 1000.0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-30 22:07:48 +02:00
|
|
|
|
CFGFUN(focus_on_window_activation, const char *mode) {
|
|
|
|
|
if (strcmp(mode, "smart") == 0)
|
|
|
|
|
config.focus_on_window_activation = FOWA_SMART;
|
|
|
|
|
else if (strcmp(mode, "urgent") == 0)
|
|
|
|
|
config.focus_on_window_activation = FOWA_URGENT;
|
|
|
|
|
else if (strcmp(mode, "focus") == 0)
|
|
|
|
|
config.focus_on_window_activation = FOWA_FOCUS;
|
|
|
|
|
else if (strcmp(mode, "none") == 0)
|
|
|
|
|
config.focus_on_window_activation = FOWA_NONE;
|
|
|
|
|
else {
|
|
|
|
|
ELOG("Unknown focus_on_window_activation mode \"%s\", ignoring it.\n", mode);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-30 20:48:35 +02:00
|
|
|
|
DLOG("Set new focus_on_window_activation mode = %i.\n", config.focus_on_window_activation);
|
2015-03-30 22:07:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-29 00:26:49 +01:00
|
|
|
|
CFGFUN(show_marks, const char *value) {
|
|
|
|
|
config.show_marks = eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(workspace, const char *workspace, const char *output) {
|
|
|
|
|
DLOG("Assigning workspace \"%s\" to output \"%s\"\n", workspace, output);
|
|
|
|
|
/* Check for earlier assignments of the same workspace so that we
|
|
|
|
|
* don’t have assignments of a single workspace to different
|
|
|
|
|
* outputs */
|
|
|
|
|
struct Workspace_Assignment *assignment;
|
|
|
|
|
bool duplicate = false;
|
2014-06-19 11:20:32 +02:00
|
|
|
|
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
2012-10-08 13:23:48 +02:00
|
|
|
|
if (strcasecmp(assignment->name, workspace) == 0) {
|
|
|
|
|
ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n",
|
|
|
|
|
workspace);
|
|
|
|
|
assignment->output = sstrdup(output);
|
|
|
|
|
duplicate = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!duplicate) {
|
2015-08-03 11:50:13 +02:00
|
|
|
|
assignment = scalloc(1, sizeof(struct Workspace_Assignment));
|
2012-10-08 13:23:48 +02:00
|
|
|
|
assignment->name = sstrdup(workspace);
|
|
|
|
|
assignment->output = sstrdup(output);
|
|
|
|
|
TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(ipc_socket, const char *path) {
|
|
|
|
|
config.ipc_socket_path = sstrdup(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(restart_state, const char *path) {
|
|
|
|
|
config.restart_state_path = sstrdup(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(popup_during_fullscreen, const char *value) {
|
2013-02-24 17:23:37 +01:00
|
|
|
|
if (strcmp(value, "ignore") == 0) {
|
|
|
|
|
config.popup_during_fullscreen = PDF_IGNORE;
|
|
|
|
|
} else if (strcmp(value, "leave_fullscreen") == 0) {
|
|
|
|
|
config.popup_during_fullscreen = PDF_LEAVE_FULLSCREEN;
|
|
|
|
|
} else {
|
|
|
|
|
config.popup_during_fullscreen = PDF_SMART;
|
|
|
|
|
}
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(color_single, const char *colorclass, const char *color) {
|
|
|
|
|
/* used for client.background only currently */
|
|
|
|
|
config.client.background = get_colorpixel(color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(color, const char *colorclass, const char *border, const char *background, const char *text, const char *indicator) {
|
2014-06-15 19:07:02 +02:00
|
|
|
|
#define APPLY_COLORS(classname) \
|
|
|
|
|
do { \
|
|
|
|
|
if (strcmp(colorclass, "client." #classname) == 0) { \
|
|
|
|
|
config.client.classname.border = get_colorpixel(border); \
|
|
|
|
|
config.client.classname.background = get_colorpixel(background); \
|
|
|
|
|
config.client.classname.text = get_colorpixel(text); \
|
|
|
|
|
if (indicator != NULL) { \
|
|
|
|
|
config.client.classname.indicator = get_colorpixel(indicator); \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
2012-10-08 13:23:48 +02:00
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
APPLY_COLORS(focused_inactive);
|
|
|
|
|
APPLY_COLORS(focused);
|
|
|
|
|
APPLY_COLORS(unfocused);
|
|
|
|
|
APPLY_COLORS(urgent);
|
2015-01-31 22:55:45 +01:00
|
|
|
|
APPLY_COLORS(placeholder);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
|
|
|
|
|
#undef APPLY_COLORS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(assign, const char *workspace) {
|
|
|
|
|
if (match_is_empty(current_match)) {
|
|
|
|
|
ELOG("Match is empty, ignoring this assignment\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-06-30 20:48:35 +02:00
|
|
|
|
DLOG("New assignment, using above criteria, to workspace \"%s\".\n", workspace);
|
2015-08-03 11:50:13 +02:00
|
|
|
|
Assignment *assignment = scalloc(1, sizeof(Assignment));
|
2012-10-08 13:23:48 +02:00
|
|
|
|
match_copy(&(assignment->match), current_match);
|
|
|
|
|
assignment->type = A_TO_WORKSPACE;
|
|
|
|
|
assignment->dest.workspace = sstrdup(workspace);
|
|
|
|
|
TAILQ_INSERT_TAIL(&assignments, assignment, assignments);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-29 17:30:14 +02:00
|
|
|
|
CFGFUN(no_focus) {
|
|
|
|
|
if (match_is_empty(current_match)) {
|
|
|
|
|
ELOG("Match is empty, ignoring this assignment\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-30 20:48:35 +02:00
|
|
|
|
DLOG("New assignment, using above criteria, to ignore focus on manage.\n");
|
2015-08-03 11:50:13 +02:00
|
|
|
|
Assignment *assignment = scalloc(1, sizeof(Assignment));
|
2015-03-29 17:30:14 +02:00
|
|
|
|
match_copy(&(assignment->match), current_match);
|
|
|
|
|
assignment->type = A_NO_FOCUS;
|
|
|
|
|
TAILQ_INSERT_TAIL(&assignments, assignment, assignments);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Bar configuration (i3bar)
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
static Barconfig current_bar;
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_font, const char *font) {
|
|
|
|
|
FREE(current_bar.font);
|
|
|
|
|
current_bar.font = sstrdup(font);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-24 23:07:25 +01:00
|
|
|
|
CFGFUN(bar_separator_symbol, const char *separator) {
|
|
|
|
|
FREE(current_bar.separator_symbol);
|
|
|
|
|
current_bar.separator_symbol = sstrdup(separator);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(bar_mode, const char *mode) {
|
introduced i3 command for changing the hidden state and the mode of i3bar
The hidden_state and mode of each i3bar instance can now be controlled from within i3.
Therefore, two new i3 command were introduced:
_
bar hidden_state show|hide|toggle [<bar_id>]
show: always show the bar
hide: normal hide mode
toggle: toggle between show and hide (individually for each bar)
_
bar mode dock|hide|invisible|toggle [<bar_id>]
hide,dock: like before
invisible: always keep the bar hidden
toggle: toggle between dock and hide (individually for each bar)
This patch introduces a hidden_state ("hidden_state hide|show") in the
barconfig, which indicates the current hidden_state of each i3bar
instance. It only affects the bar when in hide mode. Additionally, a new
invisible mode was introduced. In order to change the hidden_state or
mode of the bar from i3, a barconfig-update event was introduced, for
which a bar can subscribe and the bar then gets notified about the
currently set hidden_state and mode in its barconfig.
For convenience, an id field ("id <bar_id>") was added to the barconfig, where one can
set the desired id for the corresponding bar. If the id is not specified, i3 will
deterministically choose an id; otherwise, with the previous random approach for finding
a new id, which is actually not shared with i3bar, as it would determine its id on
startup, the event-subscription would be destroyed on reload. Still, this issue remains
when manually changing the bar_id in the config and then reloading.
fixes #833, #651
2013-05-25 14:30:00 +02:00
|
|
|
|
current_bar.mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_hidden_state, const char *hidden_state) {
|
|
|
|
|
current_bar.hidden_state = (strcmp(hidden_state, "hide") == 0 ? S_HIDE : S_SHOW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_id, const char *bar_id) {
|
|
|
|
|
current_bar.id = sstrdup(bar_id);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_output, const char *output) {
|
|
|
|
|
int new_outputs = current_bar.num_outputs + 1;
|
2014-06-15 19:07:02 +02:00
|
|
|
|
current_bar.outputs = srealloc(current_bar.outputs, sizeof(char *) * new_outputs);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
current_bar.outputs[current_bar.num_outputs] = sstrdup(output);
|
|
|
|
|
current_bar.num_outputs = new_outputs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_verbose, const char *verbose) {
|
|
|
|
|
current_bar.verbose = eval_boolstr(verbose);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_modifier, const char *modifier) {
|
|
|
|
|
if (strcmp(modifier, "Mod1") == 0)
|
|
|
|
|
current_bar.modifier = M_MOD1;
|
|
|
|
|
else if (strcmp(modifier, "Mod2") == 0)
|
|
|
|
|
current_bar.modifier = M_MOD2;
|
|
|
|
|
else if (strcmp(modifier, "Mod3") == 0)
|
|
|
|
|
current_bar.modifier = M_MOD3;
|
|
|
|
|
else if (strcmp(modifier, "Mod4") == 0)
|
|
|
|
|
current_bar.modifier = M_MOD4;
|
|
|
|
|
else if (strcmp(modifier, "Mod5") == 0)
|
|
|
|
|
current_bar.modifier = M_MOD5;
|
2012-10-09 14:05:49 +02:00
|
|
|
|
else if (strcmp(modifier, "Control") == 0 ||
|
|
|
|
|
strcmp(modifier, "Ctrl") == 0)
|
2012-10-08 13:23:48 +02:00
|
|
|
|
current_bar.modifier = M_CONTROL;
|
|
|
|
|
else if (strcmp(modifier, "Shift") == 0)
|
|
|
|
|
current_bar.modifier = M_SHIFT;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-23 22:48:29 +02:00
|
|
|
|
static void bar_configure_binding(const char *button, const char *command) {
|
|
|
|
|
if (strncasecmp(button, "button", strlen("button")) != 0) {
|
|
|
|
|
ELOG("Bindings for a bar can only be mouse bindings, not \"%s\", ignoring.\n", button);
|
2015-05-02 21:54:56 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-23 22:48:29 +02:00
|
|
|
|
int input_code = atoi(button + strlen("button"));
|
|
|
|
|
if (input_code < 1) {
|
|
|
|
|
ELOG("Button \"%s\" does not seem to be in format 'buttonX'.\n", button);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Barbinding *current;
|
|
|
|
|
TAILQ_FOREACH(current, &(current_bar.bar_bindings), bindings) {
|
|
|
|
|
if (current->input_code == input_code) {
|
2015-05-02 21:54:56 +02:00
|
|
|
|
ELOG("command for button %s was already specified, ignoring.\n", button);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-03 11:50:13 +02:00
|
|
|
|
struct Barbinding *new_binding = scalloc(1, sizeof(struct Barbinding));
|
2015-05-23 22:48:29 +02:00
|
|
|
|
new_binding->input_code = input_code;
|
|
|
|
|
new_binding->command = sstrdup(command);
|
|
|
|
|
TAILQ_INSERT_TAIL(&(current_bar.bar_bindings), new_binding, bindings);
|
2015-05-02 21:53:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-07-04 11:53:22 +02:00
|
|
|
|
CFGFUN(bar_wheel_up_cmd, const char *command) {
|
2015-05-02 21:53:23 +02:00
|
|
|
|
ELOG("'wheel_up_cmd' is deprecated. Please us 'bindsym button4 %s' instead.\n", command);
|
2015-05-23 22:48:29 +02:00
|
|
|
|
bar_configure_binding("button4", command);
|
2014-07-04 11:53:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_wheel_down_cmd, const char *command) {
|
2015-05-02 21:53:23 +02:00
|
|
|
|
ELOG("'wheel_down_cmd' is deprecated. Please us 'bindsym button5 %s' instead.\n", command);
|
2015-05-23 22:48:29 +02:00
|
|
|
|
bar_configure_binding("button5", command);
|
2015-05-02 21:53:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_bindsym, const char *button, const char *command) {
|
2015-05-23 22:48:29 +02:00
|
|
|
|
bar_configure_binding(button, command);
|
2014-07-04 11:53:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(bar_position, const char *position) {
|
|
|
|
|
current_bar.position = (strcmp(position, "top") == 0 ? P_TOP : P_BOTTOM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_i3bar_command, const char *i3bar_command) {
|
|
|
|
|
FREE(current_bar.i3bar_command);
|
|
|
|
|
current_bar.i3bar_command = sstrdup(i3bar_command);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text) {
|
2014-06-15 19:07:02 +02:00
|
|
|
|
#define APPLY_COLORS(classname) \
|
|
|
|
|
do { \
|
|
|
|
|
if (strcmp(colorclass, #classname) == 0) { \
|
|
|
|
|
if (text != NULL) { \
|
|
|
|
|
/* New syntax: border, background, text */ \
|
|
|
|
|
current_bar.colors.classname##_border = sstrdup(border); \
|
|
|
|
|
current_bar.colors.classname##_bg = sstrdup(background); \
|
|
|
|
|
current_bar.colors.classname##_text = sstrdup(text); \
|
|
|
|
|
} else { \
|
|
|
|
|
/* Old syntax: text, background */ \
|
|
|
|
|
current_bar.colors.classname##_bg = sstrdup(background); \
|
|
|
|
|
current_bar.colors.classname##_text = sstrdup(border); \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
2012-10-08 13:23:48 +02:00
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
APPLY_COLORS(focused_workspace);
|
|
|
|
|
APPLY_COLORS(active_workspace);
|
|
|
|
|
APPLY_COLORS(inactive_workspace);
|
|
|
|
|
APPLY_COLORS(urgent_workspace);
|
2015-05-31 16:07:23 +02:00
|
|
|
|
APPLY_COLORS(binding_mode);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
|
|
|
|
|
#undef APPLY_COLORS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_socket_path, const char *socket_path) {
|
|
|
|
|
FREE(current_bar.socket_path);
|
|
|
|
|
current_bar.socket_path = sstrdup(socket_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_tray_output, const char *output) {
|
|
|
|
|
FREE(current_bar.tray_output);
|
|
|
|
|
current_bar.tray_output = sstrdup(output);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-09 10:06:45 +02:00
|
|
|
|
CFGFUN(bar_tray_padding, const long padding_px) {
|
|
|
|
|
current_bar.tray_padding = padding_px;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(bar_color_single, const char *colorclass, const char *color) {
|
|
|
|
|
if (strcmp(colorclass, "background") == 0)
|
|
|
|
|
current_bar.colors.background = sstrdup(color);
|
2013-01-27 21:27:21 +01:00
|
|
|
|
else if (strcmp(colorclass, "separator") == 0)
|
|
|
|
|
current_bar.colors.separator = sstrdup(color);
|
|
|
|
|
else
|
|
|
|
|
current_bar.colors.statusline = sstrdup(color);
|
2012-10-08 13:23:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFGFUN(bar_status_command, const char *command) {
|
|
|
|
|
FREE(current_bar.status_command);
|
|
|
|
|
current_bar.status_command = sstrdup(command);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-09 05:30:14 +02:00
|
|
|
|
CFGFUN(bar_binding_mode_indicator, const char *value) {
|
|
|
|
|
current_bar.hide_binding_mode_indicator = !eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(bar_workspace_buttons, const char *value) {
|
|
|
|
|
current_bar.hide_workspace_buttons = !eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-05 19:56:47 +02:00
|
|
|
|
CFGFUN(bar_strip_workspace_numbers, const char *value) {
|
|
|
|
|
current_bar.strip_workspace_numbers = eval_boolstr(value);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-02 21:53:23 +02:00
|
|
|
|
CFGFUN(bar_start) {
|
2015-05-23 22:48:29 +02:00
|
|
|
|
TAILQ_INIT(&(current_bar.bar_bindings));
|
2015-06-09 10:06:45 +02:00
|
|
|
|
current_bar.tray_padding = 2;
|
2015-05-02 21:53:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
|
CFGFUN(bar_finish) {
|
|
|
|
|
DLOG("\t new bar configuration finished, saving.\n");
|
introduced i3 command for changing the hidden state and the mode of i3bar
The hidden_state and mode of each i3bar instance can now be controlled from within i3.
Therefore, two new i3 command were introduced:
_
bar hidden_state show|hide|toggle [<bar_id>]
show: always show the bar
hide: normal hide mode
toggle: toggle between show and hide (individually for each bar)
_
bar mode dock|hide|invisible|toggle [<bar_id>]
hide,dock: like before
invisible: always keep the bar hidden
toggle: toggle between dock and hide (individually for each bar)
This patch introduces a hidden_state ("hidden_state hide|show") in the
barconfig, which indicates the current hidden_state of each i3bar
instance. It only affects the bar when in hide mode. Additionally, a new
invisible mode was introduced. In order to change the hidden_state or
mode of the bar from i3, a barconfig-update event was introduced, for
which a bar can subscribe and the bar then gets notified about the
currently set hidden_state and mode in its barconfig.
For convenience, an id field ("id <bar_id>") was added to the barconfig, where one can
set the desired id for the corresponding bar. If the id is not specified, i3 will
deterministically choose an id; otherwise, with the previous random approach for finding
a new id, which is actually not shared with i3bar, as it would determine its id on
startup, the event-subscription would be destroyed on reload. Still, this issue remains
when manually changing the bar_id in the config and then reloading.
fixes #833, #651
2013-05-25 14:30:00 +02:00
|
|
|
|
/* Generate a unique ID for this bar if not already configured */
|
|
|
|
|
if (!current_bar.id)
|
|
|
|
|
sasprintf(¤t_bar.id, "bar-%d", config.number_barconfigs);
|
|
|
|
|
|
|
|
|
|
config.number_barconfigs++;
|
2012-10-08 13:23:48 +02:00
|
|
|
|
|
|
|
|
|
/* If no font was explicitly set, we use the i3 font as default */
|
|
|
|
|
if (!current_bar.font && font_pattern)
|
|
|
|
|
current_bar.font = sstrdup(font_pattern);
|
|
|
|
|
|
|
|
|
|
/* Copy the current (static) structure into a dynamically allocated
|
|
|
|
|
* one, then cleanup our static one. */
|
2015-08-03 11:50:13 +02:00
|
|
|
|
Barconfig *bar_config = scalloc(1, sizeof(Barconfig));
|
2012-10-08 13:23:48 +02:00
|
|
|
|
memcpy(bar_config, ¤t_bar, sizeof(Barconfig));
|
|
|
|
|
TAILQ_INSERT_TAIL(&barconfigs, bar_config, configs);
|
|
|
|
|
|
|
|
|
|
memset(¤t_bar, '\0', sizeof(Barconfig));
|
|
|
|
|
}
|