main.py
    
    Python script, ASCII text executable
        
            1
            import gi 
        
            2
            gi.require_version("Gtk", "4.0") 
        
            3
            from gi.repository import GLib, Gio, GObject, Gtk 
        
            4
            from pydbus import SessionBus 
        
            5
            import pydbus.generic 
        
            6
             
        
            7
             
        
            8
            class StatusNotifierWatcher: 
        
            9
                StatusNotifierItemRegistered = pydbus.generic.signal() 
        
            10
                StatusNotifierHostRegistered = pydbus.generic.signal() 
        
            11
                StatusNotifierItemUnregistered = pydbus.generic.signal() 
        
            12
             
        
            13
                def __init__(self, bus): 
        
            14
                    super().__init__() 
        
            15
                    self.hosts = set() 
        
            16
                    self.items = set() 
        
            17
                    self.bus = bus 
        
            18
             
        
            19
                    dbus_proxy = self.bus.get("org.freedesktop.DBus", "/org/freedesktop/DBus") 
        
            20
                    dbus_proxy.NameOwnerChanged.connect(self._on_name_owner_changed) 
        
            21
             
        
            22
                def _on_name_owner_changed(self, name, old_owner, new_owner): 
        
            23
                    if new_owner == "": 
        
            24
                        removed = False 
        
            25
                        for lookup in (name, old_owner): 
        
            26
                            if lookup in self.items: 
        
            27
                                self.items.discard(lookup) 
        
            28
                                self.StatusNotifierItemUnregistered(lookup) 
        
            29
                            if lookup in self.hosts: 
        
            30
                                self.hosts.discard(lookup) 
        
            31
             
        
            32
                def RegisterStatusNotifierItem(self, service_name): 
        
            33
                    self.items.add(service_name) 
        
            34
                    self.StatusNotifierItemRegistered(service_name) 
        
            35
             
        
            36
                def RegisterStatusNotifierHost(self, service_name): 
        
            37
                    self.hosts.add(service_name) 
        
            38
                    self.StatusNotifierHostRegistered(service_name) 
        
            39
             
        
            40
                @property 
        
            41
                def RegisteredStatusNotifierItems(self): 
        
            42
                    return sorted(self.items) 
        
            43
             
        
            44
                @property 
        
            45
                def IsStatusNotifierHostRegistered(self): 
        
            46
                    return bool(self.hosts) 
        
            47
             
        
            48
                @property 
        
            49
                def ProtocolVersion(self): 
        
            50
                    return 0 
        
            51
             
        
            52
             
        
            53
            class KDEStatusNotifierWatcher(StatusNotifierWatcher): 
        
            54
                """ 
        
            55
                <node> 
        
            56
                    <interface name="org.kde.StatusNotifierWatcher"> 
        
            57
                        <method name="RegisterStatusNotifierItem"> 
        
            58
                            <arg type="s" name="service_name" direction="in"/> 
        
            59
                        </method> 
        
            60
                        <method name="RegisterStatusNotifierHost"> 
        
            61
                            <arg type="s" name="service_name" direction="in"/> 
        
            62
                        </method> 
        
            63
                        <property name="RegisteredStatusNotifierItems" type="as" access="read"/> 
        
            64
                        <property name="IsStatusNotifierHostRegistered" type="b" access="read"/> 
        
            65
                        <property name="ProtocolVersion" type="i" access="read"/> 
        
            66
                        <signal name="StatusNotifierItemRegistered"> 
        
            67
                            <arg type="s" name="service" direction="out"/> 
        
            68
                        </signal> 
        
            69
                        <signal name="StatusNotifierItemUnregistered"> 
        
            70
                            <arg type="s" name="service" direction="out"/> 
        
            71
                        </signal> 
        
            72
                        <signal name="StatusNotifierHostRegistered"> 
        
            73
                            <arg type="s" name="service" direction="out"/> 
        
            74
                        </signal> 
        
            75
                    </interface> 
        
            76
                </node> 
        
            77
                """ 
        
            78
             
        
            79
             
        
            80
            class FDStatusNotifierWatcher(StatusNotifierWatcher): 
        
            81
                """ 
        
            82
                <node> 
        
            83
                    <interface name="org.freedesktop.StatusNotifierWatcher"> 
        
            84
                        <method name="RegisterStatusNotifierItem"> 
        
            85
                            <arg type="s" name="service_name" direction="in"/> 
        
            86
                        </method> 
        
            87
                        <method name="RegisterStatusNotifierHost"> 
        
            88
                            <arg type="s" name="service_name" direction="in"/> 
        
            89
                        </method> 
        
            90
                        <property name="RegisteredStatusNotifierItems" type="as" access="read"/> 
        
            91
                        <property name="IsStatusNotifierHostRegistered" type="b" access="read"/> 
        
            92
                        <property name="ProtocolVersion" type="i" access="read"/> 
        
            93
                        <signal name="StatusNotifierItemRegistered"> 
        
            94
                            <arg type="s" name="service" direction="out"/> 
        
            95
                        </signal> 
        
            96
                        <signal name="StatusNotifierItemUnregistered"> 
        
            97
                            <arg type="s" name="service" direction="out"/> 
        
            98
                        </signal> 
        
            99
                        <signal name="StatusNotifierHostRegistered"> 
        
            100
                            <arg type="s" name="service" direction="out"/> 
        
            101
                        </signal> 
        
            102
                    </interface> 
        
            103
                </node> 
        
            104
                """ 
        
            105
             
        
            106
             
        
            107
            class WatcherApplication(Gtk.Application): 
        
            108
                def __init__(self): 
        
            109
                    super().__init__(application_id="com.roundabout_host.roundabout.PanoramaIndicatorService", 
        
            110
                                     flags=Gio.ApplicationFlags.FLAGS_NONE) 
        
            111
                    self.bus = None 
        
            112
                    self.kde_publishing = None 
        
            113
                    self.fd_publishing = None 
        
            114
                    self.kde_watcher = None 
        
            115
                    self.fd_watcher = None 
        
            116
             
        
            117
                def do_startup(self): 
        
            118
                    Gtk.Application.do_startup(self) 
        
            119
                    self.bus = SessionBus() 
        
            120
                    self.kde_watcher = KDEStatusNotifierWatcher(self.bus) 
        
            121
                    self.fd_watcher = FDStatusNotifierWatcher(self.bus) 
        
            122
                    self.kde_publishing = self.bus.publish( 
        
            123
                        f"org.kde.StatusNotifierWatcher", 
        
            124
                        ("/StatusNotifierWatcher", self.kde_watcher) 
        
            125
                    ) 
        
            126
                    self.fd_publishing = self.bus.publish( 
        
            127
                        f"org.freedesktop.StatusNotifierWatcher", 
        
            128
                        ("/StatusNotifierWatcher", self.fd_watcher) 
        
            129
                    ) 
        
            130
             
        
            131
                def do_activate(self): 
        
            132
                    print("StatusNotifierWatcher running...") 
        
            133
                    self.hold() 
        
            134
             
        
            135
                def do_shutdown(self): 
        
            136
                    if self.bus: 
        
            137
                        if self.kde_publishing: 
        
            138
                            self.bus.unpublish(self.kde_publishing) 
        
            139
                        if self.fd_publishing: 
        
            140
                            self.bus.unpublish(self.fd_publishing) 
        
            141
                        print("Unregistered") 
        
            142
                    Gtk.Application.do_shutdown(self) 
        
            143
             
        
            144
             
        
            145
            if __name__ == "__main__": 
        
            146
                app = WatcherApplication() 
        
            147
                app.run(None) 
        
            148