1
0
monitor-lock/monitor-lock.py

135 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import os
import time
# Change path so we find Xlib
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from Xlib.display import Display
from Xlib.ext import xinerama, xinput, xfixes
from Xlib.protocol import rq
xfixes_extname = 'XFIXES'
BarrierPositiveX = (1 << 0)
BarrierPositiveY = (1 << 1)
BarrierNegativeX = (1 << 2)
BarrierNegativeY = (1 << 3)
class CreatePointerBarrier(rq.Request):
_request = rq.Struct(rq.Card8('opcode'),
rq.Opcode(31),
rq.RequestLength(),
rq.Resource('barrier'),
rq.Window('window'),
rq.Int16('x1'),
rq.Int16('y1'),
rq.Int16('x2'),
rq.Int16('y2'),
rq.Card32('directions'),
rq.Pad(2),
rq.LengthOf('devices', 2),
rq.List('devices', xinput.DEVICEID),
)
def create_pointer_barrier(self, x1, y1, x2, y2, barrier_directions, devices=None):
barrier = self.display.allocate_resource_id()
CreatePointerBarrier(
display=self.display,
opcode=self.display.get_extension_major(xfixes_extname),
window=self,
x1=x1,
y1=y1,
x2=x2,
y2=y2,
directions=barrier_directions,
devices=[] if not devices else devices,
barrier=barrier)
return barrier
def main(argv):
display = Display()
screen = display.screen()
window = screen.root
def check_extension(name):
if not display.has_extension(name):
sys.stderr.write('%s: server does not have the %s extension\n' % (sys.argv[0], name))
ext = display.query_extension(name)
print(ext)
sys.stderr.write("\n".join(display.list_extensions()))
if ext is None:
sys.exit(1)
check_extension('XFIXES')
check_extension('XInputExtension')
check_extension('XINERAMA')
xfixes_version = xfixes.QueryVersion(display=window.display, opcode=window.display.get_extension_major(xfixes_extname), major_version=5, minor_version=0)
print('Found XFIXES version %s.%s' % (
xfixes_version.major_version,
xfixes_version.minor_version,
), file=sys.stderr)
xinput_version = display.xinput_query_version()
print('Found XInputExtension version %s.%s' % (
xinput_version.major_version,
xinput_version.minor_version,
), file=sys.stderr)
xinerama_version = display.xinerama_query_version()
print('Found XINERAMA version %s.%s' % (
xinerama_version.major_version,
xinerama_version.minor_version,
), file=sys.stderr)
print()
print('Available screens:')
screens = xinerama.query_screens(window).screens
for (idx, screen) in enumerate(screens):
x, y, w, h = screen.x, screen.y, screen.width, screen.height
print('screen %d: %s' % (idx, screen))
print()
print('Available pointers:')
pointer_name = {}
devices = xinput.query_device(window, xinput.AllMasterDevices).devices
for device in devices:
if 'pointer' in device.name:
pointer_name[device.deviceid] = 'device %d: %s' % (device.deviceid, device.name)
print(pointer_name[device.deviceid])
if len(sys.argv) != 3:
print()
print('USAGE: %s [device] [screen]' % (sys.argv[0]))
return -2
lock_device = int(sys.argv[1])
lock_screen = int(sys.argv[2])
screen = screens[lock_screen]
print()
print('Creating barrier to force pointer %s to screen %d (%s)...' %\
(pointer_name[lock_device], lock_screen, screens[lock_screen]))
top = screen.y + 3
bottom = screen.y + screen.height - 3
left = screen.x + 1
right = screen.x + screen.width - 1
print('Barrier bounds: left=%d, top=%d, right=%d, bottom=%d' % (left, top, right, bottom))
# top
create_pointer_barrier(window, left, top, right, top, BarrierPositiveY, [lock_device])
# left
create_pointer_barrier(window, left, top, left, bottom, BarrierPositiveX, [lock_device])
# bottom
create_pointer_barrier(window, left, bottom, right, bottom, BarrierNegativeY, [lock_device])
# right
create_pointer_barrier(window, right, top, right, bottom, BarrierNegativeX, [lock_device])
display.sync()
print('Created barrier.')
input()
if __name__ == '__main__':
sys.exit(main(sys.argv))