Skip to content

Instantly share code, notes, and snippets.

@ppwwyyxx
Created December 31, 2020 11:40
Show Gist options
  • Save ppwwyyxx/ef2f723b2286c7cb7b18a3e2291bf7b8 to your computer and use it in GitHub Desktop.
Save ppwwyyxx/ef2f723b2286c7cb7b18a3e2291bf7b8 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
from collections import namedtuple
from Xlib import X
import Xlib.display
from Xlib.ext.xtest import fake_input
class Screen(namedtuple('_Screen', ['x', 'y', 'w', 'h'])):
@property
def x2(self):
return self.x + self.w
@property
def y2(self):
return self.y + self.h
def contains(self, x, y):
return x >= self.x and y >= self.y and x < self.x2 and y < self.y2
def center(self):
return self.x + self.w // 2, self.y + self.h // 2
class MyWM:
def __init__(self):
self.display = Xlib.display.Display()
self.refresh_screens()
def refresh_screens(self):
data = self.display.xinerama_query_screens()._data['screens']
self.screens = [Screen(d.x, d.y, d.width, d.height) for d in data]
def moveMouse(self, x, y):
fake_input(self.display, X.MotionNotify, x=x, y=y)
self.display.sync()
def mousePos(self):
coord = self.display.screen().root.query_pointer()._data
return coord["root_x"], coord["root_y"]
WM = MyWM()
class MouseSwitchScreen:
_last_pos = {} # screen idx -> last pos
@classmethod
def trigger(self):
WM.refresh_screens()
x, y = WM.mousePos()
if len(WM.screens) == 1:
return
for idx, scr in enumerate(WM.screens):
if scr.contains(x, y):
self._last_pos[idx] = (x, y)
break
else:
assert False, (x, y)
idx = (idx + 1) % len(WM.screens)
next_screen = WM.screens[idx]
if idx in self._last_pos:
x, y = self._last_pos[idx]
if not next_screen.contains(x, y):
x, y = next_screen.center()
else:
x, y = next_screen.center()
WM.moveMouse(x, y)
if __name__ == '__main__':
MouseSwitchScreen.trigger()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment