i3 - improved tiling WM


Add configuration option for disabling mouse warping

Patch status: needinfo

Patch by Atte Peltomaki

Long description:

This patch fixes ticket #780 by adding a new configuration option
"mouse_warping [yes|no]".

When mouse warping is disabled, mouse cursor does not jump to middle of current
screen when changing workspaces on multiple monitors. This introduces a
"special" cursor state, where focus is in one window and cursor on another.
Useful for eg. scrolling a web page with mouse wheel while typing into another
window on keyboard.

To apply this patch, use:
curl http://cr.i3wm.org/patch/495/raw.patch | git am

b/include/config.h

26
@@ -108,6 +108,13 @@ struct Config {
27
      * It is not planned to add any different focus models. */
28
     bool disable_focus_follows_mouse;
29
 
30
+    /** By default, mouse cursor is placed on middle of current screen/workspace
31
+     * when switching workspaces with multiple monitors, along with focus. This
32
+     * option disables mouse warping and introduces a new "special" state: keyboard
33
+     * focus moves to new workspace, but cursor remains on old workspace and is
34
+     * usable, eg. scroll web pages with mouse wheel. */
35
+    bool disable_mouse_warping;
36
+
37
     /** Remove borders if they are adjacent to the screen edge.
38
      * This is useful if you are reaching scrollbar on the edge of the
39
      * screen or do not want to waste a single pixel of displayspace.

b/include/config_directives.h

44
@@ -46,6 +46,7 @@ CFGFUN(default_orientation, const char *orientation);
45
 CFGFUN(workspace_layout, const char *layout);
46
 CFGFUN(workspace_back_and_forth, const char *value);
47
 CFGFUN(focus_follows_mouse, const char *value);
48
+CFGFUN(mouse_warping, const char *value);
49
 CFGFUN(force_focus_wrapping, const char *value);
50
 CFGFUN(force_xinerama, const char *value);
51
 CFGFUN(fake_outputs, const char *outputs);

b/parser-specs/config.spec

56
@@ -32,6 +32,7 @@ state INITIAL:
57
   'for_window'                             -> FOR_WINDOW
58
   'assign'                                 -> ASSIGN
59
   'focus_follows_mouse'                    -> FOCUS_FOLLOWS_MOUSE
60
+  'mouse_warping'			   -> MOUSE_WARPING
61
   'force_focus_wrapping'                   -> FORCE_FOCUS_WRAPPING
62
   'force_xinerama', 'force-xinerama'       -> FORCE_XINERAMA
63
   'workspace_auto_back_and_forth'          -> WORKSPACE_BACK_AND_FORTH
64
@@ -172,6 +173,11 @@ state FOCUS_FOLLOWS_MOUSE:
65
   value = word
66
       -> call cfg_focus_follows_mouse($value)
67
 
68
+# mouse_warping bool
69
+state MOUSE_WARPING:
70
+  value = word
71
+      -> call cfg_mouse_warping($value)
72
+
73
 # force_focus_wrapping
74
 state FORCE_FOCUS_WRAPPING:
75
   value = word

b/src/config_directives.c

80
@@ -299,6 +299,10 @@ CFGFUN(focus_follows_mouse, const char *value) {
81
     config.disable_focus_follows_mouse = !eval_boolstr(value);
82
 }
83
 
84
+CFGFUN(mouse_warping, const char *value) {
85
+    config.disable_mouse_warping = !eval_boolstr(value);
86
+}
87
+
88
 CFGFUN(force_xinerama, const char *value) {
89
     config.force_xinerama = eval_boolstr(value);
90
 }

b/src/x.c

95
@@ -1127,7 +1127,7 @@ void x_set_i3_atoms(void) {
96
  */
97
 void x_set_warp_to(Rect *rect)
98
 {
99
-    if (!config.disable_focus_follows_mouse)
100
+    if (!config.disable_focus_follows_mouse && !config.disable_mouse_warping)
101
         warp_to = rect;
102
 }
103
 

b/testcases/t/201-config-parser.t

108
@@ -310,6 +310,24 @@ is(parser_calls($config),
109
    'focus_follows_mouse ok');
110
 
111
 ################################################################################
112
+# mouse_warping
113
+################################################################################
114
+
115
+$config = <<'EOT';
116
+mouse_warping yes
117
+mouse_warping no
118
+EOT
119
+
120
+$expected = <<'EOT';
121
+cfg_mouse_warping(yes)
122
+cfg_mouse_warping(no)
123
+EOT
124
+
125
+is(parser_calls($config),
126
+   $expected,
127
+   'mouse_warping ok');
128
+
129
+################################################################################
130
 # force_display_urgency_hint
131
 ################################################################################
132
 
133
@@ -413,7 +431,7 @@ client.focused          #4c7899 #285577 #ffffff #2e9ef4
134
 EOT
135
 
136
 my $expected_all_tokens = <<'EOT';
137
-ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'focus_follows_mouse', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent'
138
+ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent'
139
 EOT
140
 
141
 my $expected_end = <<'EOT';