Merge pull request #1632 from Deiz/binding-border

Add a --border flag to enable mouse binds to trigger on border click
This commit is contained in:
Michael Stapelberg 2015-04-19 09:28:08 -07:00
commit 8a608ee63a
9 changed files with 45 additions and 22 deletions

View File

@ -405,13 +405,16 @@ can configure mouse bindings in a similar way to key bindings.
*Syntax*: *Syntax*:
---------------------------------- ----------------------------------
bindsym [--release] [--whole-window] [Modifiers+]button[n] command bindsym [--release] [--border] [--whole-window] [Modifiers+]button[n] command
---------------------------------- ----------------------------------
By default, the binding will only run when you click on the titlebar of the By default, the binding will only run when you click on the titlebar of the
window. If the +--whole-window+ flag is given, it will run when any part of the window. If the +--release+ flag is given, it will run when the mouse button
window is clicked. If the +--release+ flag is given, it will run when the mouse is released.
button is released.
If the +--whole-window+ flag is given, the binding will also run when any part
of the window is clicked, with the exception of the border. To have a bind run
when the border is clicked, specify the +--border+ flag.
*Examples*: *Examples*:
-------------------------------- --------------------------------

View File

@ -24,7 +24,8 @@ const char *DEFAULT_BINDING_MODE;
* *
*/ */
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code, Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
const char *release, const char *whole_window, const char *command, const char *mode); const char *release, const char *border, const char *whole_window,
const char *command, const char *mode);
/** /**
* Grab the bound keys (tell X to send us keypress events for those keycodes) * Grab the bound keys (tell X to send us keypress events for those keycodes)

View File

@ -64,10 +64,10 @@ CFGFUN(color_single, const char *colorclass, const char *color);
CFGFUN(floating_modifier, const char *modifiers); CFGFUN(floating_modifier, const char *modifiers);
CFGFUN(new_window, const char *windowtype, const char *border, const long width); CFGFUN(new_window, const char *windowtype, const char *border, const long width);
CFGFUN(workspace, const char *workspace, const char *output); CFGFUN(workspace, const char *workspace, const char *output);
CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command); CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command);
CFGFUN(enter_mode, const char *mode); CFGFUN(enter_mode, const char *mode);
CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command); 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);
CFGFUN(bar_font, const char *font); CFGFUN(bar_font, const char *font);
CFGFUN(bar_separator_symbol, const char *separator); CFGFUN(bar_separator_symbol, const char *separator);

View File

@ -255,6 +255,10 @@ struct Binding {
B_UPON_KEYRELEASE_IGNORE_MODS = 2, B_UPON_KEYRELEASE_IGNORE_MODS = 2,
} release; } release;
/** If this is true for a mouse binding, the binding should be executed
* when the button is pressed over the window border. */
bool border;
/** If this is true for a mouse binding, the binding should be executed /** If this is true for a mouse binding, the binding should be executed
* when the button is pressed over any part of the window, not just the * when the button is pressed over any part of the window, not just the
* title bar (default). */ * title bar (default). */

View File

@ -300,6 +300,8 @@ state FONT:
state BINDING: state BINDING:
release = '--release' release = '--release'
-> ->
border = '--border'
->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', '$mod' modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', '$mod'
@ -312,10 +314,12 @@ state BINDING:
state BINDCOMMAND: state BINDCOMMAND:
release = '--release' release = '--release'
-> ->
border = '--border'
->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
command = string command = string
-> call cfg_binding($bindtype, $modifiers, $key, $release, $whole_window, $command) -> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command)
################################################################################ ################################################################################
# Mode configuration # Mode configuration
@ -349,6 +353,8 @@ state MODE_IGNORE_LINE:
state MODE_BINDING: state MODE_BINDING:
release = '--release' release = '--release'
-> ->
border = '--border'
->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', '$mod' modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', '$mod'
@ -361,10 +367,12 @@ state MODE_BINDING:
state MODE_BINDCOMMAND: state MODE_BINDCOMMAND:
release = '--release' release = '--release'
-> ->
border = '--border'
->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
command = string command = string
-> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $whole_window, $command); MODE -> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command); MODE
################################################################################ ################################################################################
# Bar configuration (i3bar) # Bar configuration (i3bar)

View File

@ -49,10 +49,12 @@ static struct Mode *mode_from_name(const char *name) {
* *
*/ */
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code, Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
const char *release, const char *whole_window, const char *command, const char *modename) { const char *release, const char *border, const char *whole_window,
const char *command, const char *modename) {
Binding *new_binding = scalloc(sizeof(Binding)); Binding *new_binding = scalloc(sizeof(Binding));
DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release); DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release);
new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS); new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
new_binding->border = (border != NULL);
new_binding->whole_window = (whole_window != NULL); new_binding->whole_window = (whole_window != NULL);
if (strcmp(bindtype, "bindsym") == 0) { if (strcmp(bindtype, "bindsym") == 0) {
new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0 new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0

View File

@ -185,12 +185,13 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
/* if the user has bound an action to this click, it should override the /* if the user has bound an action to this click, it should override the
* default behavior. */ * default behavior. */
if (dest == CLICK_DECORATION || dest == CLICK_INSIDE) { if (dest == CLICK_DECORATION || dest == CLICK_INSIDE || dest == CLICK_BORDER) {
Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event);
/* clicks over a window decoration will always trigger the binding and /* clicks over a window decoration will always trigger the binding and
* clicks on the inside of the window will only trigger a binding if * clicks on the inside of the window will only trigger a binding if
* the --whole-window flag was given for the binding. */ * the --whole-window flag was given for the binding. */
if (bind && (dest == CLICK_DECORATION || bind->whole_window)) { if (bind && ((dest == CLICK_DECORATION || bind->whole_window) ||
(dest == CLICK_BORDER && bind->border))) {
CommandResult *result = run_binding(bind, con); CommandResult *result = run_binding(bind, con);
/* ASYNC_POINTER eats the event */ /* ASYNC_POINTER eats the event */

View File

@ -171,8 +171,8 @@ CFGFUN(font, const char *font) {
font_pattern = sstrdup(font); font_pattern = sstrdup(font);
} }
CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command) { CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command) {
configure_binding(bindtype, modifiers, key, release, whole_window, command, DEFAULT_BINDING_MODE); configure_binding(bindtype, modifiers, key, release, border, whole_window, command, DEFAULT_BINDING_MODE);
} }
/******************************************************************************* /*******************************************************************************
@ -181,8 +181,8 @@ CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, co
static char *current_mode; static char *current_mode;
CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command) { 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) {
configure_binding(bindtype, modifiers, key, release, whole_window, command, current_mode); configure_binding(bindtype, modifiers, key, release, border, whole_window, command, current_mode);
} }
CFGFUN(enter_mode, const char *modename) { CFGFUN(enter_mode, const char *modename) {

View File

@ -47,16 +47,20 @@ mode "meh" {
bindsym --release Mod1+x exec foo bindsym --release Mod1+x exec foo
bindsym --whole-window button3 nop bindsym --whole-window button3 nop
bindsym --release --whole-window button3 nop bindsym --release --whole-window button3 nop
bindsym --border button3 nop
bindsym --release --border button3 nop
} }
EOT EOT
my $expected = <<'EOT'; my $expected = <<'EOT';
cfg_enter_mode(meh) cfg_enter_mode(meh)
cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), resize grow) cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), (null), resize grow)
cfg_mode_binding(bindcode, Mod1, 44, (null), (null), resize shrink) cfg_mode_binding(bindcode, Mod1, 44, (null), (null), (null), resize shrink)
cfg_mode_binding(bindsym, Mod1, x, --release, (null), exec foo) cfg_mode_binding(bindsym, Mod1, x, --release, (null), (null), exec foo)
cfg_mode_binding(bindsym, (null), button3, (null), --whole-window, nop) cfg_mode_binding(bindsym, (null), button3, (null), (null), --whole-window, nop)
cfg_mode_binding(bindsym, (null), button3, --release, --whole-window, nop) cfg_mode_binding(bindsym, (null), button3, --release, (null), --whole-window, nop)
cfg_mode_binding(bindsym, (null), button3, (null), --border, (null), nop)
cfg_mode_binding(bindsym, (null), button3, --release, --border, (null), nop)
EOT EOT
is(parser_calls($config), is(parser_calls($config),
@ -624,7 +628,7 @@ EOT
$expected = <<'EOT'; $expected = <<'EOT';
cfg_enter_mode(yo) cfg_enter_mode(yo)
cfg_mode_binding(bindsym, (null), x, (null), (null), resize shrink left) cfg_mode_binding(bindsym, (null), x, (null), (null), (null), resize shrink left)
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', '}' ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', '}'
ERROR: CONFIG: (in file <stdin>) ERROR: CONFIG: (in file <stdin>)
ERROR: CONFIG: Line 1: mode "yo" { ERROR: CONFIG: Line 1: mode "yo" {