vdi-cloud/docs/evidence/native-cursor-20261105/source.py

93 lines
2.8 KiB
Python
Raw Normal View History

"""Controlled GTK test window: real native cursors and unique click sequences."""
import gi
import json
import time
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib
win = Gtk.Window(title='VDI native cursor acceptance')
area = Gtk.DrawingArea()
win.add(area)
area.set_can_focus(True)
area.set_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK |
Gdk.EventMask.BUTTON_RELEASE_MASK)
display = Gdk.Display.get_default()
names = ['default', 'text', 'ew-resize', 'wait', 'none', 'crosshair', 'custom']
cursors = {name: Gdk.Cursor.new_from_name(display, name) for name in names[:4] + ['crosshair']}
cursors['none'] = Gdk.Cursor.new_for_display(display, Gdk.CursorType.BLANK_CURSOR)
pix = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 24, 24)
pix.fill(0xff5030ff)
cursors['custom'] = Gdk.Cursor.new_from_pixbuf(display, pix, 7, 9)
current = None
sequence = 0
def report(**kw):
kw['t'] = time.monotonic()
print(json.dumps(kw), flush=True)
def motion(widget, event):
global current
index = min(6, int(event.x // (2560/7)))
name = names[index]
if name != current:
area.get_window().set_cursor(cursors[name])
current = name
report(event='shape', name=name)
return False
def button(widget, event):
global sequence
if event.type in (Gdk.EventType.BUTTON_PRESS, Gdk.EventType.DOUBLE_BUTTON_PRESS,
Gdk.EventType.TRIPLE_BUTTON_PRESS):
# GTK emits an extra double/triple notification, not another input.
if event.type == Gdk.EventType.BUTTON_PRESS:
sequence += 1
area.queue_draw_area(0, 1300, 1000, 140)
report(event=event.type.value_nick, seq=sequence, x=event.x_root,
y=event.y_root, button=event.button)
return False
def draw(widget, cr):
cr.set_source_rgb(.94, .96, .98)
cr.paint()
cr.select_font_face('sans')
cr.set_font_size(25)
for i, name in enumerate(names):
cr.set_source_rgb(.1, .15, .2)
cr.move_to(40 + i*2560/7, 100)
cr.show_text(name)
cr.set_source_rgb(.65, .7, .8)
cr.rectangle(i*2560/7, 120, 2, 1100)
cr.fill()
# Unique monotonic sequence, read from the actual decoded video.
for bit in range(16):
v = 1 if sequence & (1 << bit) else 0
cr.set_source_rgb(v, v, v)
cr.rectangle(40 + bit*40, 1340, 40, 60)
cr.fill()
return False
def key(widget, event):
if event.keyval == Gdk.KEY_Escape:
Gtk.main_quit()
return False
win.connect('destroy', Gtk.main_quit)
win.connect('key-press-event', key)
area.connect('motion-notify-event', motion)
area.connect('button-press-event', button)
area.connect('button-release-event', button)
area.connect('draw', draw)
win.fullscreen()
win.show_all()
win.present()
area.grab_focus()
report(event='ready')
Gtk.main()