2012-10-07 16:32:50 +02:00
|
|
|
# vim:ts=2:sw=2: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
|
|
|
#
|
|
|
|
# parser-specs/config.spec: Specification file for generate-command-parser.pl
|
|
|
|
# which will generate the appropriate header files for our C parser.
|
|
|
|
#
|
|
|
|
# Use :source highlighting.vim in vim to get syntax highlighting
|
|
|
|
# for this file.
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
# TODO: should we implement an include statement for the criteria part so we DRY?
|
2012-10-07 16:32:50 +02:00
|
|
|
|
|
|
|
state INITIAL:
|
|
|
|
# We have an end token here for all the commands which just call some
|
|
|
|
# function without using an explicit 'end' token.
|
|
|
|
end ->
|
2012-11-20 17:09:03 +01:00
|
|
|
error ->
|
2012-10-08 13:40:44 +02:00
|
|
|
'#' -> IGNORE_LINE
|
|
|
|
'set' -> IGNORE_LINE
|
|
|
|
bindtype = 'bindsym', 'bindcode', 'bind' -> BINDING
|
|
|
|
'bar' -> BARBRACE
|
|
|
|
'font' -> FONT
|
|
|
|
'mode' -> MODENAME
|
|
|
|
'floating_minimum_size' -> FLOATING_MINIMUM_SIZE_WIDTH
|
|
|
|
'floating_maximum_size' -> FLOATING_MAXIMUM_SIZE_WIDTH
|
|
|
|
'floating_modifier' -> FLOATING_MODIFIER
|
|
|
|
'default_orientation' -> DEFAULT_ORIENTATION
|
|
|
|
'workspace_layout' -> WORKSPACE_LAYOUT
|
|
|
|
windowtype = 'new_window', 'new_float' -> NEW_WINDOW
|
|
|
|
'hide_edge_borders' -> HIDE_EDGE_BORDERS
|
|
|
|
'for_window' -> FOR_WINDOW
|
|
|
|
'assign' -> ASSIGN
|
2015-03-29 17:30:14 +02:00
|
|
|
'no_focus' -> NO_FOCUS
|
2012-10-08 13:40:44 +02:00
|
|
|
'focus_follows_mouse' -> FOCUS_FOLLOWS_MOUSE
|
2014-03-24 18:03:05 +01:00
|
|
|
'mouse_warping' -> MOUSE_WARPING
|
2012-10-08 13:40:44 +02:00
|
|
|
'force_focus_wrapping' -> FORCE_FOCUS_WRAPPING
|
|
|
|
'force_xinerama', 'force-xinerama' -> FORCE_XINERAMA
|
|
|
|
'workspace_auto_back_and_forth' -> WORKSPACE_BACK_AND_FORTH
|
|
|
|
'fake_outputs', 'fake-outputs' -> FAKE_OUTPUTS
|
|
|
|
'force_display_urgency_hint' -> FORCE_DISPLAY_URGENCY_HINT
|
2015-03-30 22:07:48 +02:00
|
|
|
'focus_on_window_activation' -> FOCUS_ON_WINDOW_ACTIVATION
|
2015-03-29 00:26:49 +01:00
|
|
|
'show_marks' -> SHOW_MARKS
|
2012-10-08 13:40:44 +02:00
|
|
|
'workspace' -> WORKSPACE
|
|
|
|
'ipc_socket', 'ipc-socket' -> IPC_SOCKET
|
|
|
|
'restart_state' -> RESTART_STATE
|
|
|
|
'popup_during_fullscreen' -> POPUP_DURING_FULLSCREEN
|
|
|
|
exectype = 'exec_always', 'exec' -> EXEC
|
2012-10-08 13:23:48 +02:00
|
|
|
colorclass = 'client.background'
|
|
|
|
-> COLOR_SINGLE
|
2015-01-31 22:55:45 +01:00
|
|
|
colorclass = 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
|
2012-10-08 13:23:48 +02:00
|
|
|
-> COLOR_BORDER
|
|
|
|
|
|
|
|
# We ignore comments and 'set' lines (variables).
|
|
|
|
state IGNORE_LINE:
|
2013-04-01 14:42:41 +02:00
|
|
|
line
|
2012-10-08 13:23:48 +02:00
|
|
|
-> INITIAL
|
|
|
|
|
|
|
|
# floating_minimum_size <width> x <height>
|
|
|
|
state FLOATING_MINIMUM_SIZE_WIDTH:
|
|
|
|
width = number
|
|
|
|
-> FLOATING_MINIMUM_SIZE_X
|
|
|
|
|
|
|
|
state FLOATING_MINIMUM_SIZE_X:
|
|
|
|
'x'
|
|
|
|
-> FLOATING_MINIMUM_SIZE_HEIGHT
|
|
|
|
|
|
|
|
state FLOATING_MINIMUM_SIZE_HEIGHT:
|
|
|
|
height = number
|
|
|
|
-> call cfg_floating_minimum_size(&width, &height)
|
|
|
|
|
|
|
|
# floating_maximum_size <width> x <height>
|
|
|
|
state FLOATING_MAXIMUM_SIZE_WIDTH:
|
|
|
|
width = number
|
|
|
|
-> FLOATING_MAXIMUM_SIZE_X
|
|
|
|
|
|
|
|
state FLOATING_MAXIMUM_SIZE_X:
|
|
|
|
'x'
|
|
|
|
-> FLOATING_MAXIMUM_SIZE_HEIGHT
|
|
|
|
|
|
|
|
state FLOATING_MAXIMUM_SIZE_HEIGHT:
|
|
|
|
height = number
|
|
|
|
-> call cfg_floating_maximum_size(&width, &height)
|
|
|
|
|
|
|
|
# floating_modifier <modifier>
|
|
|
|
state FLOATING_MODIFIER:
|
2012-10-09 14:05:49 +02:00
|
|
|
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl'
|
2012-10-08 13:23:48 +02:00
|
|
|
->
|
|
|
|
'+'
|
|
|
|
->
|
|
|
|
end
|
|
|
|
-> call cfg_floating_modifier($modifiers)
|
|
|
|
|
|
|
|
# default_orientation <horizontal|vertical|auto>
|
|
|
|
state DEFAULT_ORIENTATION:
|
|
|
|
orientation = 'horizontal', 'vertical', 'auto'
|
|
|
|
-> call cfg_default_orientation($orientation)
|
|
|
|
|
|
|
|
# workspace_layout <default|stacking|tabbed>
|
|
|
|
state WORKSPACE_LAYOUT:
|
|
|
|
layout = 'default', 'stacking', 'stacked', 'tabbed'
|
|
|
|
-> call cfg_workspace_layout($layout)
|
|
|
|
|
|
|
|
# new_window <normal|1pixel|none>
|
|
|
|
# new_float <normal|1pixel|none>
|
|
|
|
state NEW_WINDOW:
|
|
|
|
border = 'normal', 'pixel'
|
|
|
|
-> NEW_WINDOW_PIXELS
|
|
|
|
border = '1pixel', 'none'
|
|
|
|
-> call cfg_new_window($windowtype, $border, -1)
|
|
|
|
|
|
|
|
state NEW_WINDOW_PIXELS:
|
|
|
|
end
|
|
|
|
-> call cfg_new_window($windowtype, $border, 2)
|
|
|
|
width = number
|
|
|
|
-> NEW_WINDOW_PIXELS_PX
|
|
|
|
|
|
|
|
state NEW_WINDOW_PIXELS_PX:
|
|
|
|
'px'
|
|
|
|
->
|
|
|
|
end
|
|
|
|
-> call cfg_new_window($windowtype, $border, &width)
|
|
|
|
|
|
|
|
# hide_edge_borders <none|vertical|horizontal|both>
|
|
|
|
# also hide_edge_borders <bool> for compatibility
|
|
|
|
state HIDE_EDGE_BORDERS:
|
|
|
|
hide_borders = 'none', 'vertical', 'horizontal', 'both'
|
|
|
|
-> call cfg_hide_edge_borders($hide_borders)
|
|
|
|
hide_borders = '1', 'yes', 'true', 'on', 'enable', 'active'
|
|
|
|
-> call cfg_hide_edge_borders($hide_borders)
|
|
|
|
|
|
|
|
# for_window <criteria> command
|
|
|
|
state FOR_WINDOW:
|
|
|
|
'['
|
|
|
|
-> call cfg_criteria_init(FOR_WINDOW_COMMAND); CRITERIA
|
|
|
|
|
|
|
|
state FOR_WINDOW_COMMAND:
|
|
|
|
command = string
|
|
|
|
-> call cfg_for_window($command)
|
|
|
|
|
|
|
|
# assign <criteria> [→] workspace
|
|
|
|
state ASSIGN:
|
|
|
|
'['
|
|
|
|
-> call cfg_criteria_init(ASSIGN_WORKSPACE); CRITERIA
|
|
|
|
|
|
|
|
state ASSIGN_WORKSPACE:
|
|
|
|
'→'
|
|
|
|
->
|
2015-12-28 19:38:17 +01:00
|
|
|
'workspace'
|
|
|
|
->
|
2012-10-08 13:23:48 +02:00
|
|
|
workspace = string
|
|
|
|
-> call cfg_assign($workspace)
|
|
|
|
|
2015-03-29 17:30:14 +02:00
|
|
|
# no_focus <criteria>
|
|
|
|
state NO_FOCUS:
|
|
|
|
'['
|
|
|
|
-> call cfg_criteria_init(NO_FOCUS_END); CRITERIA
|
|
|
|
|
|
|
|
state NO_FOCUS_END:
|
|
|
|
end
|
|
|
|
-> call cfg_no_focus()
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
# Criteria: Used by for_window and assign.
|
|
|
|
state CRITERIA:
|
|
|
|
ctype = 'class' -> CRITERION
|
|
|
|
ctype = 'instance' -> CRITERION
|
|
|
|
ctype = 'window_role' -> CRITERION
|
|
|
|
ctype = 'con_id' -> CRITERION
|
|
|
|
ctype = 'id' -> CRITERION
|
2015-04-18 21:09:03 +02:00
|
|
|
ctype = 'window_type' -> CRITERION
|
2012-10-08 13:23:48 +02:00
|
|
|
ctype = 'con_mark' -> CRITERION
|
|
|
|
ctype = 'title' -> CRITERION
|
|
|
|
ctype = 'urgent' -> CRITERION
|
2015-06-29 23:58:48 +02:00
|
|
|
ctype = 'workspace' -> CRITERION
|
2012-10-08 13:23:48 +02:00
|
|
|
']'
|
|
|
|
-> call cfg_criteria_pop_state()
|
|
|
|
|
|
|
|
state CRITERION:
|
|
|
|
'=' -> CRITERION_STR
|
|
|
|
|
|
|
|
state CRITERION_STR:
|
|
|
|
cvalue = word
|
|
|
|
-> call cfg_criteria_add($ctype, $cvalue); CRITERIA
|
|
|
|
|
|
|
|
# focus_follows_mouse bool
|
|
|
|
state FOCUS_FOLLOWS_MOUSE:
|
|
|
|
value = word
|
|
|
|
-> call cfg_focus_follows_mouse($value)
|
|
|
|
|
2014-03-24 18:03:05 +01:00
|
|
|
# mouse_warping warping_t
|
|
|
|
state MOUSE_WARPING:
|
|
|
|
value = 'none', 'output'
|
|
|
|
-> call cfg_mouse_warping($value)
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
# force_focus_wrapping
|
|
|
|
state FORCE_FOCUS_WRAPPING:
|
|
|
|
value = word
|
|
|
|
-> call cfg_force_focus_wrapping($value)
|
|
|
|
|
|
|
|
# force_xinerama
|
|
|
|
state FORCE_XINERAMA:
|
|
|
|
value = word
|
|
|
|
-> call cfg_force_xinerama($value)
|
|
|
|
|
|
|
|
# workspace_back_and_forth
|
|
|
|
state WORKSPACE_BACK_AND_FORTH:
|
|
|
|
value = word
|
|
|
|
-> call cfg_workspace_back_and_forth($value)
|
|
|
|
|
|
|
|
|
|
|
|
# fake_outputs (for testcases)
|
|
|
|
state FAKE_OUTPUTS:
|
|
|
|
outputs = string
|
|
|
|
-> call cfg_fake_outputs($outputs)
|
|
|
|
|
|
|
|
# force_display_urgency_hint <timeout> ms
|
|
|
|
state FORCE_DISPLAY_URGENCY_HINT:
|
|
|
|
duration_ms = number
|
|
|
|
-> FORCE_DISPLAY_URGENCY_HINT_MS
|
|
|
|
|
2015-03-29 00:26:49 +01:00
|
|
|
# show_marks
|
|
|
|
state SHOW_MARKS:
|
|
|
|
value = word
|
|
|
|
-> call cfg_show_marks($value)
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
state FORCE_DISPLAY_URGENCY_HINT_MS:
|
|
|
|
'ms'
|
|
|
|
->
|
|
|
|
end
|
|
|
|
-> call cfg_force_display_urgency_hint(&duration_ms)
|
|
|
|
|
2015-03-30 22:07:48 +02:00
|
|
|
# focus_on_window_activation <smart|urgent|focus|none>
|
|
|
|
state FOCUS_ON_WINDOW_ACTIVATION:
|
|
|
|
mode = word
|
|
|
|
-> call cfg_focus_on_window_activation($mode)
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
# workspace <workspace> output <output>
|
|
|
|
state WORKSPACE:
|
|
|
|
workspace = word
|
|
|
|
-> WORKSPACE_OUTPUT
|
|
|
|
|
|
|
|
state WORKSPACE_OUTPUT:
|
|
|
|
'output'
|
|
|
|
-> WORKSPACE_OUTPUT_STR
|
|
|
|
|
|
|
|
state WORKSPACE_OUTPUT_STR:
|
2013-01-25 13:55:26 +01:00
|
|
|
output = word
|
2012-10-08 13:23:48 +02:00
|
|
|
-> call cfg_workspace($workspace, $output)
|
|
|
|
|
|
|
|
# ipc-socket <path>
|
|
|
|
state IPC_SOCKET:
|
|
|
|
path = string
|
|
|
|
-> call cfg_ipc_socket($path)
|
|
|
|
|
|
|
|
# restart_state <path> (for testcases)
|
|
|
|
state RESTART_STATE:
|
|
|
|
path = string
|
|
|
|
-> call cfg_restart_state($path)
|
|
|
|
|
|
|
|
# popup_during_fullscreen
|
|
|
|
state POPUP_DURING_FULLSCREEN:
|
2013-02-24 17:23:37 +01:00
|
|
|
value = 'ignore', 'leave_fullscreen', 'smart'
|
2012-10-08 13:23:48 +02:00
|
|
|
-> call cfg_popup_during_fullscreen($value)
|
|
|
|
|
|
|
|
# client.background <hexcolor>
|
|
|
|
state COLOR_SINGLE:
|
|
|
|
color = word
|
|
|
|
-> call cfg_color_single($colorclass, $color)
|
|
|
|
|
|
|
|
# colorclass border background text indicator
|
|
|
|
state COLOR_BORDER:
|
|
|
|
border = word
|
|
|
|
-> COLOR_BACKGROUND
|
|
|
|
|
|
|
|
state COLOR_BACKGROUND:
|
|
|
|
background = word
|
|
|
|
-> COLOR_TEXT
|
|
|
|
|
|
|
|
state COLOR_TEXT:
|
|
|
|
text = word
|
|
|
|
-> COLOR_INDICATOR
|
|
|
|
|
|
|
|
state COLOR_INDICATOR:
|
|
|
|
indicator = word
|
2016-01-09 22:47:33 +01:00
|
|
|
-> COLOR_CHILD_BORDER
|
2012-10-08 13:23:48 +02:00
|
|
|
end
|
2015-12-28 13:37:42 +01:00
|
|
|
-> call cfg_color($colorclass, $border, $background, $text, NULL, NULL)
|
|
|
|
|
2016-01-09 22:47:33 +01:00
|
|
|
state COLOR_CHILD_BORDER:
|
|
|
|
child_border = word
|
|
|
|
-> call cfg_color($colorclass, $border, $background, $text, $indicator, $child_border)
|
2015-12-28 13:37:42 +01:00
|
|
|
end
|
|
|
|
-> call cfg_color($colorclass, $border, $background, $text, $indicator, NULL)
|
2012-10-07 16:32:50 +02:00
|
|
|
|
|
|
|
# <exec|exec_always> [--no-startup-id] command
|
|
|
|
state EXEC:
|
|
|
|
no_startup_id = '--no-startup-id'
|
|
|
|
->
|
|
|
|
command = string
|
|
|
|
-> call cfg_exec($exectype, $no_startup_id, $command)
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
# font font
|
|
|
|
state FONT:
|
|
|
|
font = string
|
|
|
|
-> call cfg_font($font)
|
|
|
|
|
|
|
|
# bindsym/bindcode
|
|
|
|
state BINDING:
|
2012-12-14 21:41:56 +01:00
|
|
|
release = '--release'
|
|
|
|
->
|
2015-04-02 03:43:46 +02:00
|
|
|
border = '--border'
|
|
|
|
->
|
2015-01-30 02:52:52 +01:00
|
|
|
whole_window = '--whole-window'
|
|
|
|
->
|
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
|
|
|
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', 'Group1', 'Group2', 'Group3', 'Group4', '$mod'
|
2012-10-08 13:23:48 +02:00
|
|
|
->
|
|
|
|
'+'
|
|
|
|
->
|
|
|
|
key = word
|
|
|
|
-> BINDCOMMAND
|
|
|
|
|
|
|
|
state BINDCOMMAND:
|
|
|
|
release = '--release'
|
|
|
|
->
|
2015-04-02 03:43:46 +02:00
|
|
|
border = '--border'
|
|
|
|
->
|
2015-01-30 02:52:52 +01:00
|
|
|
whole_window = '--whole-window'
|
|
|
|
->
|
2012-10-08 13:23:48 +02:00
|
|
|
command = string
|
2015-04-02 03:43:46 +02:00
|
|
|
-> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command)
|
2012-10-08 13:23:48 +02:00
|
|
|
|
|
|
|
################################################################################
|
|
|
|
# Mode configuration
|
|
|
|
################################################################################
|
|
|
|
|
2012-10-07 16:32:50 +02:00
|
|
|
state MODENAME:
|
2015-10-12 23:43:47 +02:00
|
|
|
pango_markup = '--pango_markup'
|
|
|
|
->
|
2012-10-07 16:32:50 +02:00
|
|
|
modename = word
|
2015-10-12 23:43:47 +02:00
|
|
|
-> call cfg_enter_mode($pango_markup, $modename); MODEBRACE
|
2012-10-07 16:32:50 +02:00
|
|
|
|
|
|
|
state MODEBRACE:
|
2012-10-10 08:18:15 +02:00
|
|
|
end
|
|
|
|
->
|
2012-10-07 16:32:50 +02:00
|
|
|
'{'
|
|
|
|
-> MODE
|
|
|
|
|
|
|
|
state MODE:
|
2012-10-08 13:23:48 +02:00
|
|
|
end ->
|
2012-11-20 17:09:03 +01:00
|
|
|
error ->
|
2012-10-08 13:23:48 +02:00
|
|
|
'#' -> MODE_IGNORE_LINE
|
|
|
|
'set' -> MODE_IGNORE_LINE
|
2012-10-09 14:11:35 +02:00
|
|
|
bindtype = 'bindsym', 'bindcode', 'bind'
|
2012-10-07 16:32:50 +02:00
|
|
|
-> MODE_BINDING
|
|
|
|
'}'
|
|
|
|
-> INITIAL
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
# We ignore comments and 'set' lines (variables).
|
|
|
|
state MODE_IGNORE_LINE:
|
2013-04-01 14:42:41 +02:00
|
|
|
line
|
2012-10-08 13:23:48 +02:00
|
|
|
-> MODE
|
|
|
|
|
2012-10-07 16:32:50 +02:00
|
|
|
state MODE_BINDING:
|
2012-12-14 21:41:56 +01:00
|
|
|
release = '--release'
|
|
|
|
->
|
2015-04-02 03:43:46 +02:00
|
|
|
border = '--border'
|
|
|
|
->
|
2015-04-01 23:13:25 +02:00
|
|
|
whole_window = '--whole-window'
|
|
|
|
->
|
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
|
|
|
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', 'Group1', 'Group2', 'Group3', 'Group4', '$mod'
|
2012-10-07 16:32:50 +02:00
|
|
|
->
|
|
|
|
'+'
|
|
|
|
->
|
|
|
|
key = word
|
|
|
|
-> MODE_BINDCOMMAND
|
|
|
|
|
|
|
|
state MODE_BINDCOMMAND:
|
2012-10-08 13:23:48 +02:00
|
|
|
release = '--release'
|
|
|
|
->
|
2015-04-02 03:43:46 +02:00
|
|
|
border = '--border'
|
|
|
|
->
|
2015-01-30 02:52:52 +01:00
|
|
|
whole_window = '--whole-window'
|
|
|
|
->
|
2012-10-07 16:32:50 +02:00
|
|
|
command = string
|
2015-04-02 03:43:46 +02:00
|
|
|
-> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command); MODE
|
2012-10-07 16:32:50 +02:00
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
################################################################################
|
|
|
|
# Bar configuration (i3bar)
|
|
|
|
################################################################################
|
|
|
|
|
|
|
|
state BARBRACE:
|
2012-10-10 08:18:15 +02:00
|
|
|
end
|
|
|
|
->
|
2012-10-08 13:23:48 +02:00
|
|
|
'{'
|
2015-05-02 21:53:23 +02:00
|
|
|
-> call cfg_bar_start(); BAR
|
2012-10-08 13:23:48 +02:00
|
|
|
|
|
|
|
state BAR:
|
|
|
|
end ->
|
2012-11-20 17:09:03 +01:00
|
|
|
error ->
|
2012-10-08 13:23:48 +02:00
|
|
|
'#' -> BAR_IGNORE_LINE
|
|
|
|
'set' -> BAR_IGNORE_LINE
|
2013-08-09 05:30:14 +02:00
|
|
|
'i3bar_command' -> BAR_BAR_COMMAND
|
|
|
|
'status_command' -> BAR_STATUS_COMMAND
|
|
|
|
'socket_path' -> BAR_SOCKET_PATH
|
|
|
|
'mode' -> BAR_MODE
|
|
|
|
'hidden_state' -> BAR_HIDDEN_STATE
|
|
|
|
'id' -> BAR_ID
|
|
|
|
'modifier' -> BAR_MODIFIER
|
2014-07-04 11:53:22 +02:00
|
|
|
'wheel_up_cmd' -> BAR_WHEEL_UP_CMD
|
|
|
|
'wheel_down_cmd' -> BAR_WHEEL_DOWN_CMD
|
2015-05-02 21:53:23 +02:00
|
|
|
'bindsym' -> BAR_BINDSYM
|
2013-08-09 05:30:14 +02:00
|
|
|
'position' -> BAR_POSITION
|
|
|
|
'output' -> BAR_OUTPUT
|
|
|
|
'tray_output' -> BAR_TRAY_OUTPUT
|
2015-06-09 10:06:45 +02:00
|
|
|
'tray_padding' -> BAR_TRAY_PADDING
|
2013-08-09 05:30:14 +02:00
|
|
|
'font' -> BAR_FONT
|
2015-03-24 23:07:25 +01:00
|
|
|
'separator_symbol' -> BAR_SEPARATOR_SYMBOL
|
2013-08-09 05:30:14 +02:00
|
|
|
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
|
|
|
|
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
|
2014-05-05 19:56:47 +02:00
|
|
|
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
|
2013-08-09 05:30:14 +02:00
|
|
|
'verbose' -> BAR_VERBOSE
|
|
|
|
'colors' -> BAR_COLORS_BRACE
|
2012-10-08 13:23:48 +02:00
|
|
|
'}'
|
|
|
|
-> call cfg_bar_finish(); INITIAL
|
|
|
|
|
|
|
|
# We ignore comments and 'set' lines (variables).
|
|
|
|
state BAR_IGNORE_LINE:
|
2013-04-01 14:42:41 +02:00
|
|
|
line
|
2012-10-08 13:23:48 +02:00
|
|
|
-> BAR
|
|
|
|
|
|
|
|
state BAR_BAR_COMMAND:
|
|
|
|
command = string
|
|
|
|
-> call cfg_bar_i3bar_command($command); BAR
|
|
|
|
|
|
|
|
state BAR_STATUS_COMMAND:
|
|
|
|
command = string
|
|
|
|
-> call cfg_bar_status_command($command); BAR
|
|
|
|
|
|
|
|
state BAR_SOCKET_PATH:
|
|
|
|
path = string
|
|
|
|
-> call cfg_bar_socket_path($path); BAR
|
|
|
|
|
|
|
|
state BAR_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
|
|
|
mode = 'dock', 'hide', 'invisible'
|
2012-10-08 13:23:48 +02:00
|
|
|
-> call cfg_bar_mode($mode); BAR
|
|
|
|
|
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
|
|
|
state BAR_HIDDEN_STATE:
|
|
|
|
hidden_state = 'hide', 'show'
|
|
|
|
-> call cfg_bar_hidden_state($hidden_state); BAR
|
|
|
|
|
|
|
|
state BAR_ID:
|
|
|
|
bar_id = word
|
|
|
|
-> call cfg_bar_id($bar_id); BAR
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
state BAR_MODIFIER:
|
2012-10-09 14:05:49 +02:00
|
|
|
modifier = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Control', 'Ctrl', 'Shift'
|
2012-10-08 13:23:48 +02:00
|
|
|
-> call cfg_bar_modifier($modifier); BAR
|
|
|
|
|
2014-07-04 11:53:22 +02:00
|
|
|
state BAR_WHEEL_UP_CMD:
|
|
|
|
command = string
|
|
|
|
-> call cfg_bar_wheel_up_cmd($command); BAR
|
|
|
|
|
|
|
|
state BAR_WHEEL_DOWN_CMD:
|
|
|
|
command = string
|
|
|
|
-> call cfg_bar_wheel_down_cmd($command); BAR
|
|
|
|
|
2015-05-02 21:53:23 +02:00
|
|
|
state BAR_BINDSYM:
|
|
|
|
button = word
|
|
|
|
-> BAR_BINDSYM_COMMAND
|
|
|
|
|
|
|
|
state BAR_BINDSYM_COMMAND:
|
|
|
|
command = string
|
|
|
|
-> call cfg_bar_bindsym($button, $command); BAR
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
state BAR_POSITION:
|
|
|
|
position = 'top', 'bottom'
|
|
|
|
-> call cfg_bar_position($position); BAR
|
|
|
|
|
|
|
|
state BAR_OUTPUT:
|
|
|
|
output = string
|
|
|
|
-> call cfg_bar_output($output); BAR
|
|
|
|
|
|
|
|
state BAR_TRAY_OUTPUT:
|
2014-08-25 17:55:59 +02:00
|
|
|
output = word
|
2012-10-08 13:23:48 +02:00
|
|
|
-> call cfg_bar_tray_output($output); BAR
|
|
|
|
|
2015-06-09 10:06:45 +02:00
|
|
|
state BAR_TRAY_PADDING:
|
|
|
|
padding_px = number
|
|
|
|
-> BAR_TRAY_PADDING_PX
|
|
|
|
|
|
|
|
state BAR_TRAY_PADDING_PX:
|
|
|
|
'px'
|
|
|
|
->
|
|
|
|
end
|
|
|
|
-> call cfg_bar_tray_padding(&padding_px); BAR
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
state BAR_FONT:
|
2012-10-07 16:32:50 +02:00
|
|
|
font = string
|
2012-10-08 13:23:48 +02:00
|
|
|
-> call cfg_bar_font($font); BAR
|
|
|
|
|
2015-03-24 23:07:25 +01:00
|
|
|
state BAR_SEPARATOR_SYMBOL:
|
|
|
|
separator = string
|
|
|
|
-> call cfg_bar_separator_symbol($separator); BAR
|
|
|
|
|
2013-08-09 05:30:14 +02:00
|
|
|
state BAR_BINDING_MODE_INDICATOR:
|
|
|
|
value = word
|
|
|
|
-> call cfg_bar_binding_mode_indicator($value); BAR
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
state BAR_WORKSPACE_BUTTONS:
|
|
|
|
value = word
|
|
|
|
-> call cfg_bar_workspace_buttons($value); BAR
|
|
|
|
|
2014-05-05 19:56:47 +02:00
|
|
|
state BAR_STRIP_WORKSPACE_NUMBERS:
|
|
|
|
value = word
|
|
|
|
-> call cfg_bar_strip_workspace_numbers($value); BAR
|
|
|
|
|
2012-10-08 13:23:48 +02:00
|
|
|
state BAR_VERBOSE:
|
|
|
|
value = word
|
|
|
|
-> call cfg_bar_verbose($value); BAR
|
|
|
|
|
|
|
|
state BAR_COLORS_BRACE:
|
2012-10-10 08:18:15 +02:00
|
|
|
end
|
|
|
|
->
|
2012-10-08 13:23:48 +02:00
|
|
|
'{'
|
|
|
|
-> BAR_COLORS
|
|
|
|
|
|
|
|
state BAR_COLORS:
|
|
|
|
end ->
|
|
|
|
'#' -> BAR_COLORS_IGNORE_LINE
|
|
|
|
'set' -> BAR_COLORS_IGNORE_LINE
|
2015-10-26 21:55:01 +01:00
|
|
|
colorclass = 'background', 'statusline', 'separator', 'focused_background', 'focused_statusline', 'focused_separator'
|
2012-10-08 13:23:48 +02:00
|
|
|
-> BAR_COLORS_SINGLE
|
2015-05-31 16:07:23 +02:00
|
|
|
colorclass = 'focused_workspace', 'active_workspace', 'inactive_workspace', 'urgent_workspace', 'binding_mode'
|
2012-10-08 13:23:48 +02:00
|
|
|
-> BAR_COLORS_BORDER
|
|
|
|
'}'
|
|
|
|
-> BAR
|
|
|
|
|
|
|
|
# We ignore comments and 'set' lines (variables).
|
|
|
|
state BAR_COLORS_IGNORE_LINE:
|
2013-04-01 14:42:41 +02:00
|
|
|
line
|
2012-10-08 13:23:48 +02:00
|
|
|
-> BAR_COLORS
|
|
|
|
|
|
|
|
state BAR_COLORS_SINGLE:
|
|
|
|
color = word
|
|
|
|
-> call cfg_bar_color_single($colorclass, $color); BAR_COLORS
|
|
|
|
|
|
|
|
state BAR_COLORS_BORDER:
|
|
|
|
border = word
|
|
|
|
-> BAR_COLORS_BACKGROUND
|
|
|
|
|
|
|
|
state BAR_COLORS_BACKGROUND:
|
|
|
|
background = word
|
|
|
|
-> BAR_COLORS_TEXT
|
|
|
|
|
|
|
|
state BAR_COLORS_TEXT:
|
|
|
|
end
|
|
|
|
-> call cfg_bar_color($colorclass, $border, $background, NULL); BAR_COLORS
|
|
|
|
text = word
|
|
|
|
-> call cfg_bar_color($colorclass, $border, $background, $text); BAR_COLORS
|