Files
cthulhu/tests/ocr_review_fixture.py

102 lines
4.0 KiB
Python

"""Private Xorg key sink: focus, delivered keys and conflicting passive grabs."""
import json
import os
import select
import sys
from Xlib import X, Xatom, XK, display
from Xlib.ext import xtest
def main():
connection = display.Display()
root = connection.screen().root
activeAtom = connection.intern_atom('_NET_ACTIVE_WINDOW')
previousActive = root.get_full_property(activeAtom, X.AnyPropertyType)
pidAtom = connection.intern_atom('_NET_WM_PID')
keys = []
def make_window(x):
window = root.create_window(x, 30, 300, 200, 0,
connection.screen().root_depth,
X.InputOutput, X.CopyFromParent,
background_pixel=0xFFFFFF,
event_mask=X.KeyPressMask | X.KeyReleaseMask)
window.set_wm_name('OCR review fixture')
window.set_wm_class('example', 'example')
window.change_property(pidAtom, Xatom.CARDINAL, 32, [os.getpid()])
window.map()
return window
window = make_window(40)
other = make_window(380)
competitor = display.Display()
competitorRoot = competitor.screen().root
conflictCode = competitor.keysym_to_keycode(XK.string_to_keysym('c'))
def activate(target):
root.change_property(activeAtom, Xatom.WINDOW, 32, [target.id])
target.set_input_focus(X.RevertToParent, X.CurrentTime)
def drain():
connection.sync()
while connection.pending_events():
event = connection.next_event()
if event.type in (X.KeyPress, X.KeyRelease):
keys.append(dict(pressed=event.type == X.KeyPress,
symbol=connection.keycode_to_keysym(event.detail, 0),
modifiers=event.state, window=event.window.id))
activate(window)
connection.sync()
print(json.dumps(dict(window=window.id, other=other.id)), flush=True)
try:
while True:
drain()
readable, _, _ = select.select([sys.stdin, connection.fileno()], [], [])
if sys.stdin not in readable:
continue
line = sys.stdin.readline()
if not line:
break
command = json.loads(line)
action = command['action']
if action == 'activate':
activate(other if command.get('other') else window)
elif action == 'key':
keyCode = connection.keysym_to_keycode(XK.string_to_keysym(command['name']))
if not keyCode:
raise ValueError('Unknown fixture key')
xtest.fake_input(connection, X.KeyPress, keyCode)
xtest.fake_input(connection, X.KeyRelease, keyCode)
elif action == 'class':
window.set_wm_class(command['name'], command['name'])
elif action == 'unknown':
root.change_property(activeAtom, Xatom.WINDOW, 32, [X.NONE])
elif action == 'conflict':
competitorRoot.grab_key(conflictCode, X.ControlMask, False,
X.GrabModeAsync, X.GrabModeAsync)
competitor.sync()
elif action == 'unconflict':
competitorRoot.ungrab_key(conflictCode, X.ControlMask)
competitor.sync()
elif action not in ('state', 'clear'):
raise ValueError('unknown fixture action')
drain()
if action == 'clear':
keys.clear()
print(json.dumps(dict(focus=connection.get_input_focus().focus.id,
keys=keys)), flush=True)
finally:
if previousActive is None:
root.delete_property(activeAtom)
else:
root.change_property(activeAtom, previousActive.property_type,
previousActive.format, previousActive.value)
connection.sync()
competitor.close()
connection.close()
if __name__ == '__main__':
main()