Skip to content

Commit 3b5c560

Browse files
committed
Add keyboard shortcuts for warping the mouse pointer between
monitors. When working with multiple monitors, it is tedious and fatiguing to move your pointer manually when changing focus from one monitor to another - especially if you have more than two. This will enable the user to assign shortcuts to warp the pointer to the next and previous logical monitors. An additional setting will specify either centering the pointer on the new monitor, or maintaining the relative position it had on the previous one.
1 parent f84c97d commit 3b5c560

File tree

4 files changed

+105
-1
lines changed

4 files changed

+105
-1
lines changed

data/org.cinnamon.gschema.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,12 @@
515515
</description>
516516
</key>
517517

518+
<key type="b" name="center-warped-pointer">
519+
<default>true</default>
520+
<summary>Center the pointer on the new monitor</summary>
521+
<description>If true, the pointer will be set to the center of the new monitor when using pointer next/previous shortcuts.</description>
522+
</key>
523+
518524
<child name="theme" schema="org.cinnamon.theme"/>
519525
<child name="recorder" schema="org.cinnamon.recorder"/>
520526
<child name="keyboard" schema="org.cinnamon.keyboard"/>

files/usr/share/cinnamon/cinnamon-settings/modules/cs_keyboard.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
[_("Sound and Media"), "media", None, "applications-multimedia"],
4444
[_("Quiet Keys"), "media-quiet", "media", None],
4545
[_("Universal Access"), "accessibility", None, "preferences-desktop-accessibility"],
46-
[_("Custom Shortcuts"), "custom", None, "cinnamon-panel-launcher"]
46+
[_("Custom Shortcuts"), "custom", None, "cinnamon-panel-launcher"],
47+
[_("Pointer"), "pointer", "general", None]
4748
]
4849

4950
KEYBINDINGS = [
@@ -62,6 +63,9 @@
6263
[_("Run dialog"), MUFFIN_KEYBINDINGS_SCHEMA, "panel-run-dialog", "general"],
6364
# General - Troubleshooting
6465
[_("Toggle Looking Glass"), CINNAMON_SCHEMA, "looking-glass-keybinding", "trouble"],
66+
# General - Pointer
67+
[_("Move pointer to the next monitor"), CINNAMON_SCHEMA, "pointer-next-monitor", "pointer"],
68+
[_("Move pointer to the previous monitor"), CINNAMON_SCHEMA, "pointer-previous-monitor", "pointer"],
6569
# Windows
6670
[_("Maximize window"), MUFFIN_KEYBINDINGS_SCHEMA, "maximize", "windows"],
6771
[_("Unmaximize window"), MUFFIN_KEYBINDINGS_SCHEMA, "unmaximize", "windows"],

js/misc/pointerTracker.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
22
const Gdk = imports.gi.Gdk;
3+
const Gio = imports.gi.Gio;
4+
const Keybindings = imports.ui.keybindings;
5+
const Main = imports.ui.main;
36

47
function PointerTracker(){
58
this._init();
@@ -31,3 +34,91 @@ PointerTracker.prototype = {
3134
};
3235
}
3336
};
37+
38+
39+
var PointerSwitcher = class {
40+
constructor(wm) {
41+
this.settings = new Gio.Settings({ schema_id: "org.cinnamon.desktop.keybindings" });
42+
this.settings.connect("changed", (settings, key) => {
43+
if (["pointer-next-monitor", "pointer-previous-monitor"].includes(key)) {
44+
this.update_settings();
45+
}
46+
});
47+
48+
this.update_settings()
49+
}
50+
51+
update_settings() {
52+
Main.keybindingManager.addHotKeyArray(
53+
"pointer-next-monitor",
54+
this.settings.get_strv("pointer-next-monitor"),
55+
() => this.next_monitor()
56+
);
57+
58+
Main.keybindingManager.addHotKeyArray(
59+
"pointer-previous-monitor",
60+
this.settings.get_strv("pointer-previous-monitor"),
61+
() => this.previous_monitor()
62+
);
63+
}
64+
65+
get_normalized_pointer_position_for_monitor(index) {
66+
let [global_x, global_y, mods] = global.get_pointer();
67+
const monitor = Main.layoutManager.monitors[index];
68+
69+
let rx = global_x - monitor.x;
70+
let ry = global_y - monitor.y;
71+
72+
let nx = rx / monitor.width;
73+
let ny = ry / monitor.height;
74+
75+
if (nx < 0 || nx > 1.0)
76+
nx = 0.5;
77+
if (ny < 0 || ny > 1.0)
78+
ny = 0.5;
79+
80+
return [nx, ny];
81+
}
82+
83+
get_real_pointer_position(index, nx, ny) {
84+
const monitor = Main.layoutManager.monitors[index];
85+
86+
let real_x = (nx * monitor.width) + monitor.x;
87+
let real_y = (nx * monitor.height) + monitor.y;
88+
89+
return [real_x, real_y];
90+
}
91+
92+
next_monitor() {
93+
const current = global.display.get_current_monitor();
94+
const max = global.display.get_n_monitors() - 1;
95+
const new_mon = current + 1 <= max ? current + 1 : 0;
96+
97+
this.move_from_to_monitor(current, new_mon);
98+
}
99+
100+
previous_monitor() {
101+
const current = global.display.get_current_monitor();
102+
const max = global.display.get_n_monitors() - 1;
103+
const new_mon = current - 1 >= 0 ? current - 1 : max;
104+
105+
this.move_from_to_monitor(current, new_mon);
106+
}
107+
108+
move_from_to_monitor(from_i, to_i) {
109+
const center = global.settings.get_boolean("center-warped-pointer")
110+
111+
let nx, ny;
112+
113+
if (global.settings.get_boolean("center-warped-pointer")) {
114+
nx = ny = 0.5;
115+
} else {
116+
[nx, ny] = this.get_normalized_pointer_position_for_monitor(from_i);
117+
}
118+
119+
let [x, y] = this.get_real_pointer_position(to_i, nx, ny);
120+
121+
global.set_pointer(x, y);
122+
}
123+
};
124+

js/ui/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ var tracker = null;
168168
var settingsManager = null;
169169
var systrayManager = null;
170170
var wmSettings = null;
171+
var pointerSwitcher = null;
171172

172173
var workspace_names = [];
173174

@@ -383,6 +384,8 @@ function start() {
383384
pointerTracker.setPosition(layoutManager.primaryMonitor.x + layoutManager.primaryMonitor.width/2,
384385
layoutManager.primaryMonitor.y + layoutManager.primaryMonitor.height/2);
385386

387+
pointerSwitcher = new PointerTracker.PointerSwitcher();
388+
386389
xdndHandler = new XdndHandler.XdndHandler();
387390
osdWindowManager = new OsdWindow.OsdWindowManager();
388391
// This overview object is just a stub for non-user sessions

0 commit comments

Comments
 (0)