]> git.sur5r.net Git - i3/i3/commitdiff
Introduce --exclude-titlebar flag for mouse bindings. (#2703)
authorIngo Bürk <admin@airblader.de>
Tue, 2 May 2017 07:08:42 +0000 (09:08 +0200)
committerMichael Stapelberg <stapelberg@users.noreply.github.com>
Tue, 2 May 2017 07:08:42 +0000 (09:08 +0200)
This introduces the flag --exclude-titlebar for mouse bindings which
allows bindings like

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

fixes #2347

docs/userguide
include/bindings.h
include/config_directives.h
include/data.h
parser-specs/config.spec
src/bindings.c
src/click.c
src/config_directives.c
testcases/t/201-config-parser.t

index 4946a1bae938438f81019358c489bcdce8d6e5f2..d2ad7d41ccc7b349bd72acf910184cc1a9ec6f06 100644 (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.
 
 *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
 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
 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*:
 --------------------------------
 # The middle button over a titlebar kills the window
index 0fcc4df4c94f390d43648503c65fd27c95b1e303..df3c32a5a88c8edea7048a39fb7b8d40aefb1883 100644 (file)
@@ -27,7 +27,8 @@ extern const char *DEFAULT_BINDING_MODE;
  */
 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 *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)
index 0bf521686855fed4b3dd4540017e96979e600e33..f35666f3612000c21c4837c592a5b22261bf6d33 100644 (file)
@@ -67,10 +67,10 @@ CFGFUN(color_single, const char *colorclass, const char *color);
 CFGFUN(floating_modifier, const char *modifiers);
 CFGFUN(new_window, const char *windowtype, const char *border, const long width);
 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(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_separator_symbol, const char *separator);
index 3d67e315733893a85be3ef1124f6d145eb76cea8..69a79ade09faabf22bca2ddbbebef2243a65c14c 100644 (file)
@@ -298,6 +298,10 @@ struct Binding {
      * title bar (default). */
     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 */
     uint32_t keycode;
 
index 19e2d21a09166290b1251422a3ec01bcc30680f9..53828221236fb621d56d8fb1d76c6f028c293c15 100644 (file)
@@ -321,6 +321,8 @@ state BINDING:
       ->
   whole_window = '--whole-window'
       ->
+  exclude_titlebar = '--exclude-titlebar'
+      ->
   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'
       ->
+  exclude_titlebar = '--exclude-titlebar'
+      ->
   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
@@ -376,6 +380,8 @@ state MODE_BINDING:
       ->
   whole_window = '--whole-window'
       ->
+  exclude_titlebar = '--exclude-titlebar'
+      ->
   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'
       ->
+  exclude_titlebar = '--exclude-titlebar'
+      ->
   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)
index bfec27e1edb797dff744d852ff1a05491a6bdce5..36bcc5d175bbc0c75bef8209c3a0bdfcbd3e4985 100644 (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,
                            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));
     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->border = (border != NULL);
     new_binding->whole_window = (whole_window != NULL);
+    new_binding->exclude_titlebar = (exclude_titlebar != NULL);
     if (strcmp(bindtype, "bindsym") == 0) {
         new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0
                                        ? B_MOUSE
index e989b88d987aa15877e565e9e743e991b0367cca..e5cdc8b2f39e82dbe880fb184337f3f8363380f2 100644 (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) {
         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_BORDER && bind->border))) {
             CommandResult *result = run_binding(bind, con);
index 879d225e64e60796e61b104ab6a2257c28fc0462..7ca6e102785a674daa3741e5f884fd68ebc958ab 100644 (file)
@@ -106,8 +106,8 @@ CFGFUN(font, const char *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) {
-    configure_binding(bindtype, modifiers, key, release, border, whole_window, command, DEFAULT_BINDING_MODE, false);
+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, 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 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) {
-    configure_binding(bindtype, modifiers, key, release, border, whole_window, command, current_mode, 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 *exclude_titlebar, const char *command) {
+    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) {
index 1de86c653c2fde44e78e4608167fdda3dd18cd17..159de0466b42d47b815d5bd2a79cfa1f0e3ef8a4 100644 (file)
@@ -49,18 +49,22 @@ mode "meh" {
     bindsym --release --whole-window button3 nop
     bindsym --border button3 nop
     bindsym --release --border button3 nop
+    bindsym --exclude-titlebar button3 nop
+    bindsym --whole-window --border --exclude-titlebar button3 nop
 }
 EOT
 
 my $expected = <<'EOT';
 cfg_enter_mode((null), meh)
-cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), (null), resize grow)
-cfg_mode_binding(bindcode, Mod1, 44, (null), (null), (null), resize shrink)
-cfg_mode_binding(bindsym, Mod1, x, --release, (null), (null), exec foo)
-cfg_mode_binding(bindsym, (null), button3, (null), (null), --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)
+cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), (null), (null), resize grow)
+cfg_mode_binding(bindcode, Mod1, 44, (null), (null), (null), (null), resize shrink)
+cfg_mode_binding(bindsym, Mod1, x, --release, (null), (null), (null), exec foo)
+cfg_mode_binding(bindsym, (null), button3, (null), (null), --whole-window, (null), nop)
+cfg_mode_binding(bindsym, (null), button3, --release, (null), --whole-window, (null), nop)
+cfg_mode_binding(bindsym, (null), button3, (null), --border, (null), (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
 
 is(parser_calls($config),
@@ -674,7 +678,7 @@ EOT
 
 $expected = <<'EOT';
 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: (in file <stdin>)
 ERROR: CONFIG: Line   1: mode "yo" {