/usr/share/cinnamon-screensaver/service.py is in cinnamon-screensaver 3.2.13-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | #! /usr/bin/python3
import gi
gi.require_version('CScreensaver', '1.0')
from gi.repository import Gtk, CScreensaver, Gio, GObject
import constants as c
from manager import ScreensaverManager
class ScreensaverService(GObject.Object):
"""
This is the dbus service we run ourselves. It is the owner
of our ScreensaverManager, and implements the org.cinnamon.Screensaver
dbus interface. It is through this service that the screensaver
is controlled.
"""
def __init__(self):
"""
Immediately attempt to own org.cinnamon.Screensaver.
Failure to do so will result in simply quitting the program,
as we can't run more than one instance at a time.
Upon success we export our interface to the session bus.
"""
super(ScreensaverService, self).__init__()
self.bus = Gio.bus_get_sync(Gio.BusType.SESSION)
Gio.bus_own_name(Gio.BusType.SESSION,
c.SS_SERVICE,
Gio.BusNameOwnerFlags.NONE,
self.on_bus_acquired,
self.on_name_acquired,
self.on_name_lost)
def on_name_lost(self, connection, name, data=None):
"""
Failed to acquire our name - just exit.
"""
print("A screensaver is already running! Exiting...")
Gtk.main_quit()
def on_name_acquired(self, connection, name, data=None):
"""
Acquired our name - pass... The real work will begin
on our bus_acquired callback.
"""
print("Starting screensaver...")
def on_bus_acquired(self, connection, name, data=None):
"""
Export our interface to the session bus. Creates the
ScreensaverManager. We are now ready to respond to requests
by cinnamon-session and cinnamon-screensaver-command.
"""
self.bus = connection
self.interface = CScreensaver.ScreenSaverSkeleton.new()
self.interface.connect("handle-lock", self.handle_lock)
self.interface.connect("handle-quit", self.handle_quit)
self.interface.connect("handle-set-active", self.handle_set_active)
self.interface.connect("handle-get-active", self.handle_get_active)
self.interface.connect("handle-get-active-time", self.handle_get_active_time)
self.interface.connect("handle-simulate-user-activity", self.handle_simulate_user_activity)
self.manager = ScreensaverManager()
self.manager.connect("active-changed", self.on_active_changed)
"""
The stage constructs itself and fades in asynchronously, and most importantly,
as an idle callback. This can cause the screensaver to not be fully active when
a call to suspend is made. Cinnamon-session calls to lock the screensaver
synchronously, and if we don't completely finish construction before returning
the dbus call completion, there's a chance the idle callback won't run until
after the computer is resumed.
We get an active-changed signal whenever the screensaver becomes completely active
or inactive, so we'll queue up running iface.complete_lock() until we receive that signal.
This allows the screensaver to be fully activated prior to cinnamon-session allowing
the suspend/hibernate/whatever process to continue.
For reference, this is called in cinnamon-session's csm-manager.c "manager_perhaps_lock"
method.
"""
self.lock_queue = []
self.interface.export(self.bus, c.SS_PATH)
# Interface handlers
def handle_lock(self, iface, inv, msg):
self.lock_queue.append(inv)
self.manager.lock(msg)
return True
def handle_quit(self, iface, inv):
self.manager.unlock()
iface.complete_quit(inv)
Gtk.main_quit()
return True
def handle_set_active(self, iface, inv, active):
self.manager.set_active(active)
iface.complete_set_active(inv)
return True
def handle_get_active(self, iface, inv):
active = self.manager.get_active()
iface.complete_get_active(inv, active)
return True
def handle_get_active_time(self, iface, inv):
atime = self.manager.get_active_time()
iface.complete_get_active_time(inv, atime)
return True
def handle_simulate_user_activity(self, iface, inv):
if self.manager.is_locked():
self.manager.simulate_user_activity()
iface.complete_simulate_user_activity(inv)
return True
def on_active_changed(self, manager, state, data=None):
GObject.idle_add(self.on_active_changed_idle, state)
def on_active_changed_idle(self, state):
self.lock_queue.reverse()
while len(self.lock_queue) > 0:
invocation = self.lock_queue.pop()
self.interface.complete_lock(invocation)
self.lock_queue = []
self.interface.emit_active_changed(state)
|