Introduce --exclude-titlebar flag for mouse bindings. (#2703)

This introduces the flag --exclude-titlebar for mouse bindings which
allows bindings like

    bindsym --whole-window --border --exclude-titlebar button3 focus

fixes #2347
This commit is contained in:
Ingo Bürk 2017-05-02 09:08:42 +02:00 committed by Michael Stapelberg
parent 1d4e9f5de0
commit d78fd8d91f
9 changed files with 44 additions and 22 deletions

View File

@ -412,9 +412,9 @@ button in the scope of the clicked container (see <<command_criteria>>). You
can configure mouse bindings in a similar way to key bindings. can configure mouse bindings in a similar way to key bindings.
*Syntax*: *Syntax*:
------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
bindsym [--release] [--border] [--whole-window] [<Modifiers>+]button<n> command bindsym [--release] [--border] [--whole-window] [--exclude-titlebar] [<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 +--release+ flag is given, it will run when the mouse button window. If the +--release+ flag is given, it will run when the mouse button
@ -424,6 +424,9 @@ 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 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. when the border is clicked, specify the +--border+ flag.
If the +--exclude-titlebar+ flag is given, the titlebar will not be considered
for the keybinding.
*Examples*: *Examples*:
-------------------------------- --------------------------------
# The middle button over a titlebar kills the window # The middle button over a titlebar kills the window

View File

@ -27,7 +27,8 @@ extern 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 *border, const char *whole_window, const char *release, const char *border, const char *whole_window,
const char *command, const char *mode, bool pango_markup); const char *exclude_titlebar, const char *command, const char *mode,
bool pango_markup);
/** /**
* 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

@ -67,10 +67,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 *border, 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 *exclude_titlebar, const char *command);
CFGFUN(enter_mode, const char *pango_markup, const char *mode); CFGFUN(enter_mode, const char *pango_markup, const char *mode);
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(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, 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

@ -298,6 +298,10 @@ struct Binding {
* title bar (default). */ * title bar (default). */
bool whole_window; bool whole_window;
/** If this is true for a mouse binding, the binding should only be
* executed if the button press was not on the titlebar. */
bool exclude_titlebar;
/** Keycode to bind */ /** Keycode to bind */
uint32_t keycode; uint32_t keycode;

View File

@ -321,6 +321,8 @@ state BINDING:
-> ->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
exclude_titlebar = '--exclude-titlebar'
->
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', 'Group1', 'Group2', 'Group3', 'Group4', '$mod' modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', 'Group1', 'Group2', 'Group3', 'Group4', '$mod'
-> ->
'+' '+'
@ -335,8 +337,10 @@ state BINDCOMMAND:
-> ->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
exclude_titlebar = '--exclude-titlebar'
->
command = string command = string
-> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command) -> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $exclude_titlebar, $command)
################################################################################ ################################################################################
# Mode configuration # Mode configuration
@ -376,6 +380,8 @@ state MODE_BINDING:
-> ->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
exclude_titlebar = '--exclude-titlebar'
->
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', 'Group1', 'Group2', 'Group3', 'Group4', '$mod' modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', 'Group1', 'Group2', 'Group3', 'Group4', '$mod'
-> ->
'+' '+'
@ -390,8 +396,10 @@ state MODE_BINDCOMMAND:
-> ->
whole_window = '--whole-window' whole_window = '--whole-window'
-> ->
exclude_titlebar = '--exclude-titlebar'
->
command = string command = string
-> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command); MODE -> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $exclude_titlebar, $command); MODE
################################################################################ ################################################################################
# Bar configuration (i3bar) # Bar configuration (i3bar)

View File

@ -56,12 +56,14 @@ static struct Mode *mode_from_name(const char *name, bool pango_markup) {
*/ */
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 *border, const char *whole_window, const char *release, const char *border, const char *whole_window,
const char *command, const char *modename, bool pango_markup) { const char *exclude_titlebar, const char *command, const char *modename,
bool pango_markup) {
Binding *new_binding = scalloc(1, sizeof(Binding)); Binding *new_binding = scalloc(1, sizeof(Binding));
DLOG("Binding %p bindtype %s, modifiers %s, input code %s, release %s\n", new_binding, bindtype, modifiers, input_code, release); DLOG("Binding %p bindtype %s, modifiers %s, input code %s, release %s\n", new_binding, 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->border = (border != NULL);
new_binding->whole_window = (whole_window != NULL); new_binding->whole_window = (whole_window != NULL);
new_binding->exclude_titlebar = (exclude_titlebar != 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
? B_MOUSE ? B_MOUSE

View File

@ -186,7 +186,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod
if (dest == CLICK_DECORATION || dest == CLICK_INSIDE || dest == CLICK_BORDER) { 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);
if (bind != NULL && (dest == CLICK_DECORATION || if (bind != NULL && ((dest == CLICK_DECORATION && !bind->exclude_titlebar) ||
(dest == CLICK_INSIDE && bind->whole_window) || (dest == CLICK_INSIDE && bind->whole_window) ||
(dest == CLICK_BORDER && bind->border))) { (dest == CLICK_BORDER && bind->border))) {
CommandResult *result = run_binding(bind, con); CommandResult *result = run_binding(bind, con);

View File

@ -106,8 +106,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 *border, 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 *exclude_titlebar, const char *command) {
configure_binding(bindtype, modifiers, key, release, border, whole_window, command, DEFAULT_BINDING_MODE, false); configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, DEFAULT_BINDING_MODE, false);
} }
/******************************************************************************* /*******************************************************************************
@ -117,8 +117,8 @@ CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, co
static char *current_mode; static char *current_mode;
static bool current_mode_pango_markup; static bool current_mode_pango_markup;
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(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command) {
configure_binding(bindtype, modifiers, key, release, border, whole_window, command, current_mode, current_mode_pango_markup); configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, current_mode, current_mode_pango_markup);
} }
CFGFUN(enter_mode, const char *pango_markup, const char *modename) { CFGFUN(enter_mode, const char *pango_markup, const char *modename) {

View File

@ -49,18 +49,22 @@ mode "meh" {
bindsym --release --whole-window button3 nop bindsym --release --whole-window button3 nop
bindsym --border button3 nop bindsym --border button3 nop
bindsym --release --border button3 nop bindsym --release --border button3 nop
bindsym --exclude-titlebar button3 nop
bindsym --whole-window --border --exclude-titlebar button3 nop
} }
EOT EOT
my $expected = <<'EOT'; my $expected = <<'EOT';
cfg_enter_mode((null), meh) cfg_enter_mode((null), meh)
cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), (null), resize grow) cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), (null), (null), resize grow)
cfg_mode_binding(bindcode, Mod1, 44, (null), (null), (null), resize shrink) cfg_mode_binding(bindcode, Mod1, 44, (null), (null), (null), (null), resize shrink)
cfg_mode_binding(bindsym, Mod1, x, --release, (null), (null), exec foo) cfg_mode_binding(bindsym, Mod1, x, --release, (null), (null), (null), exec foo)
cfg_mode_binding(bindsym, (null), button3, (null), (null), --whole-window, nop) cfg_mode_binding(bindsym, (null), button3, (null), (null), --whole-window, (null), nop)
cfg_mode_binding(bindsym, (null), button3, --release, (null), --whole-window, nop) cfg_mode_binding(bindsym, (null), button3, --release, (null), --whole-window, (null), nop)
cfg_mode_binding(bindsym, (null), button3, (null), --border, (null), nop) cfg_mode_binding(bindsym, (null), button3, (null), --border, (null), (null), nop)
cfg_mode_binding(bindsym, (null), button3, --release, --border, (null), nop) cfg_mode_binding(bindsym, (null), button3, --release, --border, (null), (null), nop)
cfg_mode_binding(bindsym, (null), button3, (null), (null), (null), --exclude-titlebar, nop)
cfg_mode_binding(bindsym, (null), button3, (null), --border, --whole-window, --exclude-titlebar, nop)
EOT EOT
is(parser_calls($config), is(parser_calls($config),
@ -674,7 +678,7 @@ EOT
$expected = <<'EOT'; $expected = <<'EOT';
cfg_enter_mode((null), yo) cfg_enter_mode((null), yo)
cfg_mode_binding(bindsym, (null), x, (null), (null), (null), resize shrink left) cfg_mode_binding(bindsym, (null), x, (null), (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" {