65 lines
4.8 KiB
Python
65 lines
4.8 KiB
Python
# The test's stand-in for the person: screenshots through the portal, clicks and keys through
|
|
# Mutter's own remote desktop interface. op.py shot out.png | click x y | key keysym
|
|
import sys, time, shutil, urllib.parse
|
|
from gi.repository import Gio, GLib
|
|
bus = Gio.bus_get_sync(Gio.BusType.SESSION)
|
|
def call(dest, path, iface, method, args=None, sig=None):
|
|
return bus.call_sync(dest, path, iface, method, args, None, 0, -1, None)
|
|
def shot(out):
|
|
token = 'op%d' % int(time.time() * 1000)
|
|
sender = bus.get_unique_name()[1:].replace('.', '_')
|
|
req = '/org/freedesktop/portal/desktop/request/%s/%s' % (sender, token)
|
|
loop = GLib.MainLoop(); res = {}
|
|
def on(conn, snd, path, iface, sig, params, *a):
|
|
res['r'] = params.unpack(); loop.quit()
|
|
bus.signal_subscribe(None, 'org.freedesktop.portal.Request', 'Response', req, None, 0, on)
|
|
call('org.freedesktop.portal.Desktop', '/org/freedesktop/portal/desktop', 'org.freedesktop.portal.Screenshot', 'Screenshot',
|
|
GLib.Variant('(sa{sv})', ('', {'handle_token': GLib.Variant('s', token), 'interactive': GLib.Variant('b', False)})))
|
|
GLib.timeout_add_seconds(10, loop.quit); loop.run()
|
|
uri = res['r'][1]['uri']
|
|
shutil.move(urllib.parse.unquote(uri[7:]), out)
|
|
def session():
|
|
path = call('org.gnome.Mutter.RemoteDesktop', '/org/gnome/Mutter/RemoteDesktop', 'org.gnome.Mutter.RemoteDesktop', 'CreateSession').unpack()[0]
|
|
call('org.gnome.Mutter.RemoteDesktop', path, 'org.gnome.Mutter.RemoteDesktop.Session', 'Start')
|
|
return lambda m, a: call('org.gnome.Mutter.RemoteDesktop', path, 'org.gnome.Mutter.RemoteDesktop.Session', m, a)
|
|
def eye(out):
|
|
# Mutter's own screen cast (the operator's view, no portal), one frame through GStreamer.
|
|
import subprocess
|
|
sp = call('org.gnome.Mutter.ScreenCast', '/org/gnome/Mutter/ScreenCast', 'org.gnome.Mutter.ScreenCast', 'CreateSession', GLib.Variant('(a{sv})', ({},))).unpack()[0]
|
|
st = call('org.gnome.Mutter.ScreenCast', sp, 'org.gnome.Mutter.ScreenCast.Session', 'RecordMonitor', GLib.Variant('(sa{sv})', ('Meta-0', {}))).unpack()[0]
|
|
loop = GLib.MainLoop(); res = {}
|
|
def on(conn, snd, path, iface, sig, params, *a):
|
|
res['node'] = params.unpack()[0]; loop.quit()
|
|
bus.signal_subscribe(None, 'org.gnome.Mutter.ScreenCast.Stream', 'PipeWireStreamAdded', st, None, 0, on)
|
|
call('org.gnome.Mutter.ScreenCast', sp, 'org.gnome.Mutter.ScreenCast.Session', 'Start')
|
|
GLib.timeout_add_seconds(5, loop.quit); loop.run()
|
|
subprocess.run(['gst-launch-1.0', '-q', 'pipewiresrc', 'path=%d' % res['node'], 'num-buffers=3', '!', 'videoconvert', '!', 'pngenc', 'snapshot=true', '!', 'filesink', 'location=' + out], timeout=20)
|
|
call('org.gnome.Mutter.ScreenCast', sp, 'org.gnome.Mutter.ScreenCast.Session', 'Stop')
|
|
cmd = sys.argv[1]
|
|
if cmd == 'eye':
|
|
eye(sys.argv[2])
|
|
if cmd == 'shot':
|
|
shot(sys.argv[2])
|
|
elif cmd == 'click':
|
|
# Absolute moves need a screen cast stream tied to the remote desktop session.
|
|
rdp = call('org.gnome.Mutter.RemoteDesktop', '/org/gnome/Mutter/RemoteDesktop', 'org.gnome.Mutter.RemoteDesktop', 'CreateSession').unpack()[0]
|
|
sid = call('org.gnome.Mutter.RemoteDesktop', rdp, 'org.freedesktop.DBus.Properties', 'Get', GLib.Variant('(ss)', ('org.gnome.Mutter.RemoteDesktop.Session', 'SessionId'))).unpack()[0]
|
|
sp = call('org.gnome.Mutter.ScreenCast', '/org/gnome/Mutter/ScreenCast', 'org.gnome.Mutter.ScreenCast', 'CreateSession', GLib.Variant('(a{sv})', ({'remote-desktop-session-id': GLib.Variant('s', sid)},))).unpack()[0]
|
|
st = call('org.gnome.Mutter.ScreenCast', sp, 'org.gnome.Mutter.ScreenCast.Session', 'RecordMonitor', GLib.Variant('(sa{sv})', ('Meta-0', {}))).unpack()[0]
|
|
loop = GLib.MainLoop()
|
|
bus.signal_subscribe(None, 'org.gnome.Mutter.ScreenCast.Stream', 'PipeWireStreamAdded', st, None, 0, lambda *a: loop.quit())
|
|
call('org.gnome.Mutter.RemoteDesktop', rdp, 'org.gnome.Mutter.RemoteDesktop.Session', 'Start')
|
|
GLib.timeout_add_seconds(5, loop.quit); loop.run()
|
|
import subprocess
|
|
gst = subprocess.Popen(['gst-launch-1.0', '-q', 'pipewiresrc', 'path=%d' % 0, '!', 'fakesink'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
s = lambda m, a: call('org.gnome.Mutter.RemoteDesktop', rdp, 'org.gnome.Mutter.RemoteDesktop.Session', m, a)
|
|
time.sleep(0.5)
|
|
s('NotifyPointerMotionAbsolute', GLib.Variant('(sdd)', (st, float(sys.argv[2]), float(sys.argv[3])))); time.sleep(0.2)
|
|
s('NotifyPointerButton', GLib.Variant('(ib)', (0x110, True))); time.sleep(0.05)
|
|
s('NotifyPointerButton', GLib.Variant('(ib)', (0x110, False))); time.sleep(0.3)
|
|
elif cmd == 'key':
|
|
s = session(); time.sleep(0.3)
|
|
for k in sys.argv[2:]:
|
|
s('NotifyKeyboardKeysym', GLib.Variant('(ub)', (int(k, 16), True))); time.sleep(0.05)
|
|
s('NotifyKeyboardKeysym', GLib.Variant('(ub)', (int(k, 16), False))); time.sleep(0.1)
|