mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-07 01:15:33 +00:00
Python 3.6 (used in Bionic) accepts `@dbus.service.signal(BUS_NAME)`, and it accepts the `-> None` syntax, but not both together!?
88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
#!/usr/bin/python3
|
|
import logging
|
|
import os
|
|
|
|
import dbus
|
|
import dbus.bus
|
|
import dbus.mainloop.glib
|
|
import dbus.service
|
|
|
|
BUS_NAME = 'com.Keyman.Config'
|
|
OBJECT_PATH = '/com/Keyman/Config'
|
|
|
|
|
|
__keyman_config_service = None
|
|
|
|
|
|
class KeymanConfigService(dbus.service.Object):
|
|
def __init__(self, bus, handler) -> None:
|
|
self.__keyboard_list_changed_handler = handler
|
|
self.__bus = bus
|
|
bus_name = dbus.service.BusName(BUS_NAME, bus=self.__bus, do_not_queue=True)
|
|
dbus.service.Object.__init__(self, bus_name, OBJECT_PATH)
|
|
|
|
@dbus.service.signal(BUS_NAME)
|
|
def KeyboardListChangedSignal(self):
|
|
pass
|
|
|
|
@dbus.service.method(BUS_NAME)
|
|
def keyboard_list_changed(self):
|
|
logging.debug("%s: -------------keyboard_list_changed--------------------" % os.getpid())
|
|
if self.__keyboard_list_changed_handler:
|
|
self.__keyboard_list_changed_handler()
|
|
self.KeyboardListChangedSignal()
|
|
|
|
|
|
class KeymanConfigServiceManager:
|
|
def __init__(self, handler):
|
|
self.__name_owner_watch = None
|
|
self.__signal_receiver = None
|
|
self.__service = None
|
|
self.__keyboard_list_changed_handler = handler
|
|
loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
|
self.__bus = dbus.SessionBus(loop)
|
|
self.__name_owner_watch = self.__bus.watch_name_owner(BUS_NAME, self.__name_owner_changed)
|
|
|
|
def __is_name_owner(self) -> bool:
|
|
retval = self.__bus.request_name(BUS_NAME, dbus.bus.NAME_FLAG_DO_NOT_QUEUE)
|
|
return (
|
|
retval == dbus.bus.REQUEST_NAME_REPLY_ALREADY_OWNER or
|
|
retval == dbus.bus.REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
|
|
|
def __create_service(self) -> None:
|
|
if self.__signal_receiver:
|
|
self.__signal_receiver.remove()
|
|
self.__signal_receiver = None
|
|
if self.__is_name_owner():
|
|
logging.debug('%s: I am now owner (%s)' % (os.getpid(), self.__bus.get_name_owner(BUS_NAME)))
|
|
if self.__name_owner_watch:
|
|
self.__name_owner_watch.cancel()
|
|
self.__name_owner_watch = None
|
|
self.__service = KeymanConfigService(self.__bus, self.__keyboard_list_changed_handler)
|
|
else:
|
|
logging.debug('%s: Not owner. Owner is %s. Connecting signal' %
|
|
(os.getpid(), self.__bus.get_name_owner(BUS_NAME)))
|
|
self.__service = self.__bus.get_object(BUS_NAME, OBJECT_PATH, introspect=False)
|
|
if self.__keyboard_list_changed_handler:
|
|
self.__signal_receiver = self.__service.connect_to_signal(
|
|
'KeyboardListChangedSignal', self.__keyboard_list_changed_handler, dbus_interface=BUS_NAME)
|
|
|
|
def __name_owner_changed(self, new_owner) -> None:
|
|
logging.debug('%s: Owner changed. Recreating service.' % os.getpid())
|
|
self.__create_service()
|
|
|
|
def __verify_service_exists(self) -> None:
|
|
if not self.__service:
|
|
self.__create_service()
|
|
|
|
def keyboard_list_changed(self) -> None:
|
|
self.__verify_service_exists()
|
|
if self.__service:
|
|
self.__service.keyboard_list_changed()
|
|
|
|
|
|
def get_keyman_config_service(handler=None) -> KeymanConfigServiceManager:
|
|
global __keyman_config_service
|
|
if not __keyman_config_service:
|
|
__keyman_config_service = KeymanConfigServiceManager(handler)
|
|
return __keyman_config_service
|