90 lines
2.9 KiB
Python
90 lines
2.9 KiB
Python
"""GTK provider geometry paired with independently measured X11 rectangles."""
|
|
import json
|
|
import os
|
|
import sys
|
|
import gi
|
|
|
|
gi.require_version('Gtk', '3.0')
|
|
gi.require_version('GdkX11', '3.0')
|
|
gi.require_version('Gdk', '3.0')
|
|
from gi.repository import Gdk, GdkX11, GLib, Gtk
|
|
from Xlib import X, Xatom, display
|
|
|
|
|
|
def main():
|
|
window = Gtk.Window(title='OCR geometry fixture')
|
|
window.set_decorated(False)
|
|
window.set_default_size(300, 200)
|
|
window.move(40, 30)
|
|
fixed = Gtk.Fixed()
|
|
window.add(fixed)
|
|
painted = Gtk.DrawingArea()
|
|
painted.set_size_request(80, 50)
|
|
painted.set_can_focus(True)
|
|
painted.get_accessible().set_name('Painted target')
|
|
|
|
def draw(_widget, context):
|
|
context.set_source_rgb(0.2, 0.4, 0.6)
|
|
context.paint()
|
|
return False
|
|
|
|
painted.connect('draw', draw)
|
|
fixed.put(painted, 10, 15)
|
|
password = Gtk.Entry()
|
|
password.set_visibility(False)
|
|
password.get_accessible().set_name('Protected target')
|
|
fixed.put(password, 10, 90)
|
|
window.show_all()
|
|
painted.grab_focus()
|
|
Gdk.Display.get_default().sync()
|
|
connection = display.Display()
|
|
root = connection.screen().root
|
|
activeAtom = connection.intern_atom('_NET_ACTIVE_WINDOW')
|
|
clientId = GdkX11.X11Window.get_xid(window.get_window())
|
|
client = connection.create_resource_object('window', clientId)
|
|
root.change_property(activeAtom, Xatom.WINDOW, 32, [clientId])
|
|
client.change_property(connection.intern_atom('_NET_WM_PID'), Xatom.CARDINAL, 32, [os.getpid()])
|
|
client.set_input_focus(X.RevertToParent, X.CurrentTime)
|
|
connection.sync()
|
|
|
|
def rectangle(widget):
|
|
native = connection.create_resource_object('window', GdkX11.X11Window.get_xid(widget.get_window()))
|
|
origin = root.translate_coords(native, 0, 0)
|
|
geometry = native.get_geometry()
|
|
return [origin.x, origin.y, origin.x + geometry.width, origin.y + geometry.height]
|
|
|
|
def state():
|
|
connection.sync()
|
|
return dict(window=clientId, target=rectangle(painted), focus=connection.get_input_focus().focus.id)
|
|
|
|
GLib.idle_add(lambda: (print(json.dumps(state()), flush=True), False)[1])
|
|
|
|
def command_ready(_source, condition):
|
|
if condition & GLib.IO_HUP:
|
|
Gtk.main_quit()
|
|
return False
|
|
line = sys.stdin.readline()
|
|
if not line:
|
|
Gtk.main_quit()
|
|
return False
|
|
command = json.loads(line)
|
|
action = command['action']
|
|
if action == 'hide':
|
|
painted.hide()
|
|
elif action == 'password':
|
|
password.grab_focus()
|
|
elif action == 'move':
|
|
window.move(100, 60)
|
|
elif action != 'state':
|
|
raise ValueError('unknown fixture action')
|
|
GLib.idle_add(lambda: (print(json.dumps(state()), flush=True), False)[1])
|
|
return True
|
|
|
|
GLib.io_add_watch(sys.stdin, GLib.IO_IN | GLib.IO_HUP, command_ready)
|
|
Gtk.main()
|
|
connection.close()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|