Add mouse binding pointer position configuration
Patch status: merged
Patch by Tony Crisci
Long description:
Add the `--whole-window` switch for mouse bindings. This switch controls what part of the container the pointer must be over to trigger a mouse binding. The default is to only trigger mouse bindings over the titlebars. With this switch, a mouse binding will be triggered over the main part of the window as well. This is a breaking change to the previous behavior, which would trigger a mouse binding with a modifier over any part of the window. fixes #1429
To apply this patch, use:
curl http://cr.i3wm.org/patch/706/raw.patch | git am
b/docs/userguide
| 31 |
@@ -404,12 +404,12 @@ can configure mouse bindings in a similar way to key bindings. |
| 32 |
|
| 33 |
*Syntax*: |
| 34 |
---------------------------------- |
| 35 |
-bindsym [Modifiers+]button[n] command |
| 36 |
+bindsym [--whole-window] [Modifiers+]button[n] command |
| 37 |
---------------------------------- |
| 38 |
|
| 39 |
-If the binding has no modifiers, it will only run when you click on the |
| 40 |
-titlebar of the window. Otherwise, it will run when any part of the window is |
| 41 |
-clicked. |
| 42 |
+By default, the binding will only run when you click on the titlebar of the |
| 43 |
+window. If the +--whole-window+ flag is given, it will run when any part of the |
| 44 |
+window is clicked. |
| 45 |
|
| 46 |
*Examples*: |
| 47 |
-------------------------------- |
| 48 |
@@ -417,7 +417,7 @@ clicked. |
| 49 |
bindsym button2 kill |
| 50 |
|
| 51 |
# The middle button and a modifer over any part of the window kills the window |
| 52 |
-bindsym $mod+button2 kill |
| 53 |
+bindsym --whole-window $mod+button2 kill |
| 54 |
|
| 55 |
# The right button toggles floating |
| 56 |
bindsym button3 floating toggle |
b/include/bindings.h
| 61 |
@@ -24,7 +24,7 @@ const char *DEFAULT_BINDING_MODE; |
| 62 |
* |
| 63 |
*/ |
| 64 |
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code, |
| 65 |
- const char *release, const char *command, const char *mode); |
| 66 |
+ const char *release, const char *whole_window, const char *command, const char *mode); |
| 67 |
|
| 68 |
/** |
| 69 |
* Grab the bound keys (tell X to send us keypress events for those keycodes) |
b/include/config_directives.h
| 74 |
@@ -61,10 +61,10 @@ CFGFUN(color_single, const char *colorclass, const char *color); |
| 75 |
CFGFUN(floating_modifier, const char *modifiers); |
| 76 |
CFGFUN(new_window, const char *windowtype, const char *border, const long width); |
| 77 |
CFGFUN(workspace, const char *workspace, const char *output); |
| 78 |
-CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *command); |
| 79 |
+CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command); |
| 80 |
|
| 81 |
CFGFUN(enter_mode, const char *mode); |
| 82 |
-CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *command); |
| 83 |
+CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command); |
| 84 |
|
| 85 |
CFGFUN(bar_font, const char *font); |
| 86 |
CFGFUN(bar_mode, const char *mode); |
b/include/data.h
| 91 |
@@ -255,6 +255,11 @@ struct Binding {
|
| 92 |
B_UPON_KEYRELEASE_IGNORE_MODS = 2, |
| 93 |
} release; |
| 94 |
|
| 95 |
+ /** If this is true for a mouse binding, the binding should be executed |
| 96 |
+ * when the button is pressed over any part of the window, not just the |
| 97 |
+ * title bar (default). */ |
| 98 |
+ bool whole_window; |
| 99 |
+ |
| 100 |
uint32_t number_keycodes; |
| 101 |
|
| 102 |
/** Keycode to bind */ |
b/parser-specs/config.spec
| 107 |
@@ -278,6 +278,8 @@ state FONT: |
| 108 |
state BINDING: |
| 109 |
release = '--release' |
| 110 |
-> |
| 111 |
+ whole_window = '--whole-window' |
| 112 |
+ -> |
| 113 |
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', '$mod' |
| 114 |
-> |
| 115 |
'+' |
| 116 |
@@ -288,8 +290,10 @@ state BINDING: |
| 117 |
state BINDCOMMAND: |
| 118 |
release = '--release' |
| 119 |
-> |
| 120 |
+ whole_window = '--whole-window' |
| 121 |
+ -> |
| 122 |
command = string |
| 123 |
- -> call cfg_binding($bindtype, $modifiers, $key, $release, $command) |
| 124 |
+ -> call cfg_binding($bindtype, $modifiers, $key, $release, $whole_window, $command) |
| 125 |
|
| 126 |
################################################################################ |
| 127 |
# Mode configuration |
| 128 |
@@ -333,8 +337,10 @@ state MODE_BINDING: |
| 129 |
state MODE_BINDCOMMAND: |
| 130 |
release = '--release' |
| 131 |
-> |
| 132 |
+ whole_window = '--whole-window' |
| 133 |
+ -> |
| 134 |
command = string |
| 135 |
- -> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $command); MODE |
| 136 |
+ -> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $whole_window, $command); MODE |
| 137 |
|
| 138 |
################################################################################ |
| 139 |
# Bar configuration (i3bar) |
b/src/bindings.c
| 144 |
@@ -49,10 +49,11 @@ static struct Mode *mode_from_name(const char *name) {
|
| 145 |
* |
| 146 |
*/ |
| 147 |
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code, |
| 148 |
- const char *release, const char *command, const char *modename) {
|
| 149 |
+ const char *release, const char *whole_window, const char *command, const char *modename) {
|
| 150 |
Binding *new_binding = scalloc(sizeof(Binding)); |
| 151 |
DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release);
|
| 152 |
new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS); |
| 153 |
+ new_binding->whole_window = (whole_window != NULL); |
| 154 |
if (strcmp(bindtype, "bindsym") == 0) {
|
| 155 |
new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0
|
| 156 |
? B_MOUSE |
b/src/click.c
| 161 |
@@ -182,9 +182,9 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod |
| 162 |
if (dest == CLICK_DECORATION || dest == CLICK_INSIDE) {
|
| 163 |
Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); |
| 164 |
/* clicks over a window decoration will always trigger the binding and |
| 165 |
- * clicks on the inside of the window will only trigger a binding if it |
| 166 |
- * has modifiers. */ |
| 167 |
- if (bind && (dest == CLICK_DECORATION || (bind->mods && dest == CLICK_INSIDE))) {
|
| 168 |
+ * clicks on the inside of the window will only trigger a binding if |
| 169 |
+ * the --whole-window flag was given for the binding. */ |
| 170 |
+ if (bind && (dest == CLICK_DECORATION || bind->whole_window)) {
|
| 171 |
CommandResult *result = run_binding(bind, con); |
| 172 |
|
| 173 |
/* ASYNC_POINTER eats the event */ |
b/src/config_directives.c
| 178 |
@@ -171,8 +171,8 @@ CFGFUN(font, const char *font) {
|
| 179 |
font_pattern = sstrdup(font); |
| 180 |
} |
| 181 |
|
| 182 |
-CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *command) {
|
| 183 |
- configure_binding(bindtype, modifiers, key, release, command, DEFAULT_BINDING_MODE); |
| 184 |
+CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command) {
|
| 185 |
+ configure_binding(bindtype, modifiers, key, release, whole_window, command, DEFAULT_BINDING_MODE); |
| 186 |
} |
| 187 |
|
| 188 |
/******************************************************************************* |
| 189 |
@@ -181,8 +181,8 @@ CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, co |
| 190 |
|
| 191 |
static char *current_mode; |
| 192 |
|
| 193 |
-CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *command) {
|
| 194 |
- configure_binding(bindtype, modifiers, key, release, command, current_mode); |
| 195 |
+CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command) {
|
| 196 |
+ configure_binding(bindtype, modifiers, key, release, whole_window, command, current_mode); |
| 197 |
} |
| 198 |
|
| 199 |
CFGFUN(enter_mode, const char *modename) {
|
b/testcases/t/201-config-parser.t
| 204 |
@@ -50,9 +50,9 @@ EOT |
| 205 |
|
| 206 |
my $expected = <<'EOT'; |
| 207 |
cfg_enter_mode(meh) |
| 208 |
-cfg_mode_binding(bindsym, Mod1,Shift, x, (null), resize grow) |
| 209 |
-cfg_mode_binding(bindcode, Mod1, 44, (null), resize shrink) |
| 210 |
-cfg_mode_binding(bindsym, Mod1, x, --release, exec foo) |
| 211 |
+cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), resize grow) |
| 212 |
+cfg_mode_binding(bindcode, Mod1, 44, (null), (null), resize shrink) |
| 213 |
+cfg_mode_binding(bindsym, Mod1, x, --release, (null), exec foo) |
| 214 |
EOT |
| 215 |
|
| 216 |
is(parser_calls($config), |
| 217 |
@@ -618,7 +618,7 @@ EOT |
| 218 |
|
| 219 |
$expected = <<'EOT'; |
| 220 |
cfg_enter_mode(yo) |
| 221 |
-cfg_mode_binding(bindsym, (null), x, (null), resize shrink left) |
| 222 |
+cfg_mode_binding(bindsym, (null), x, (null), (null), resize shrink left) |
| 223 |
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', '}' |
| 224 |
ERROR: CONFIG: (in file <stdin>) |
| 225 |
ERROR: CONFIG: Line 1: mode "yo" {
|