#!/usr/bin/env python3 """Capture one frame through the Jarvis GNOME Shell helper, then the Screenshot portal.""" import sys from gi.repository import Gio, GLib target = sys.argv[1] bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) def jarvis_shell_screenshot(): proxy = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, 'io.qvac.Jarvis.Shell', '/io/qvac/Jarvis/Shell', 'io.qvac.Jarvis.Shell', None, ) path = proxy.call_sync( 'Screenshot', GLib.Variant('(s)', (target,)), Gio.DBusCallFlags.NONE, 5000, None, ).unpack()[0] if not path: raise RuntimeError('Jarvis Shell screenshot returned no path') return path def portal_screenshot(): proxy = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, 'org.freedesktop.portal.Desktop', '/org/freedesktop/portal/desktop', 'org.freedesktop.portal.Screenshot', None, ) options = {'interactive': GLib.Variant('b', False)} try: request = proxy.call_sync('Screenshot', GLib.Variant('(a{sv})', (options,)), Gio.DBusCallFlags.NONE, 8000, None).unpack()[0] except Exception: request = proxy.call_sync('Screenshot', GLib.Variant('(sa{sv})', ('', options)), Gio.DBusCallFlags.NONE, 8000, None).unpack()[0] loop = GLib.MainLoop() result = {'uri': None} def response(_conn, _sender, _path, _interface, _member, params): code, values = params.unpack() if code == 0: result['uri'] = values.get('uri') loop.quit() sub = bus.signal_subscribe(None, 'org.freedesktop.portal.Request', 'Response', request, None, Gio.DBusSignalFlags.NONE, response) GLib.timeout_add(4000, loop.quit) loop.run() bus.signal_unsubscribe(sub) if not result['uri']: raise RuntimeError('Screenshot portal returned no image URI') ok, contents, _etag = Gio.File.new_for_uri(result['uri']).load_contents(None) if not ok: raise RuntimeError('could not read screenshot portal URI') Gio.File.new_for_path(target).replace_contents(contents, None, False, Gio.FileCreateFlags.REPLACE_DESTINATION, None) return target errors = [] for capture in (jarvis_shell_screenshot, portal_screenshot): try: print(capture()) raise SystemExit(0) except Exception as exc: errors.append(f'{capture.__name__}: {exc}') raise SystemExit('; '.join(errors) or 'screenshot unavailable')