69 lines
2.4 KiB
Python
69 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Capture one frame through GNOME Shell or the Screenshot portal and print its path."""
|
|
import sys
|
|
from gi.repository import Gio, GLib
|
|
|
|
target = sys.argv[1]
|
|
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
|
|
|
|
|
def gnome_shell_screenshot():
|
|
proxy = Gio.DBusProxy.new_sync(
|
|
bus, Gio.DBusProxyFlags.NONE, None,
|
|
'org.gnome.Shell.Screenshot', '/org/gnome/Shell/Screenshot',
|
|
'org.gnome.Shell.Screenshot', None,
|
|
)
|
|
ok, path = proxy.call_sync(
|
|
'Screenshot',
|
|
GLib.Variant('(bbs)', (False, False, target)),
|
|
Gio.DBusCallFlags.NONE,
|
|
5000,
|
|
None,
|
|
).unpack()
|
|
if not ok:
|
|
raise RuntimeError('GNOME Shell screenshot failed')
|
|
return path or target
|
|
|
|
|
|
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(7000, 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 (gnome_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')
|