Example #1
0
    def __init__(self):
        self._click_type_callbacks = []

        if not "dbus" in globals():
            raise ImportError("python-dbus unavailable")

        MouseController.__init__(self)

        self.launcher = DelayedLauncher()
        self._daemon_running_notify_callbacks = []

        # Check if mousetweaks' schema is installed.
        # Raises SchemaError if it isn't.

        # connect to session bus
        self._bus = dbus.SessionBus()
        self._bus.add_signal_receiver(self._on_name_owner_changed,
                                      "NameOwnerChanged",
                                      dbus.BUS_DAEMON_IFACE,
                                      arg0=self.MT_DBUS_NAME)
        # Initial state
        proxy = self._bus.get_object(dbus.BUS_DAEMON_NAME, dbus.BUS_DAEMON_PATH)
        result = proxy.NameHasOwner(self.MT_DBUS_NAME, dbus_interface=dbus.BUS_DAEMON_IFACE)
        self._set_connection(bool(result))
Example #2
0
class Mousetweaks(MouseController):
    """ Mousetweaks settings, D-bus control and signal handling """

    CLICK_TYPE_RIGHT  = 0
    CLICK_TYPE_MIDDLE = 4

    MOUSE_A11Y_SCHEMA_ID = "org.gnome.desktop.a11y.mouse"
    MOUSETWEAKS_SCHEMA_ID = "org.gnome.mousetweaks"

    MT_DBUS_NAME  = "org.gnome.Mousetweaks"
    MT_DBUS_PATH  = "/org/gnome/Mousetweaks"
    MT_DBUS_IFACE = "org.gnome.Mousetweaks"
    MT_DBUS_PROP  = "ClickType"

    def __init__(self):
        self._click_type_callbacks = []

        if not "dbus" in globals():
            raise ImportError("python-dbus unavailable")

        MouseController.__init__(self)

        self.launcher = DelayedLauncher()
        self._daemon_running_notify_callbacks = []

        # Check if mousetweaks' schema is installed.
        # Raises SchemaError if it isn't.

        # connect to session bus
        self._bus = dbus.SessionBus()
        self._bus.add_signal_receiver(self._on_name_owner_changed,
                                      "NameOwnerChanged",
                                      dbus.BUS_DAEMON_IFACE,
                                      arg0=self.MT_DBUS_NAME)
        # Initial state
        proxy = self._bus.get_object(dbus.BUS_DAEMON_NAME, dbus.BUS_DAEMON_PATH)
        result = proxy.NameHasOwner(self.MT_DBUS_NAME, dbus_interface=dbus.BUS_DAEMON_IFACE)
        self._set_connection(bool(result))

    def init_defaults(self):
        """ Create gsettings key descriptions """

        self.dwell_click_enabled = False
        self.dwell_time = 1.2
        self.dwell_threshold = 10
        self.click_type_window_visible = False

    def on_properties_initialized(self):
        ConfigObject.on_properties_initialized(self)

        # launch mousetweaks on startup if necessary
        if not self._iface and \
           self.dwell_click_enabled:
            self._launch_daemon(0.5)

    def cleanup(self):
        self._daemon_running_notify_callbacks = []

    def _launch_daemon(self, delay):
        self.launcher.launch_delayed(["mousetweaks"], delay)

    def _set_connection(self, active):
        ''' Update interface object, state and notify listeners '''
        if active:
            proxy = self._bus.get_object(self.MT_DBUS_NAME, self.MT_DBUS_PATH)
            self._iface = dbus.Interface(proxy, dbus.PROPERTIES_IFACE)
            self._iface.connect_to_signal("PropertiesChanged",
                                          self._on_click_type_prop_changed)
            self._click_type = self._iface.Get(self.MT_DBUS_IFACE, self.MT_DBUS_PROP)
        else:
            self._iface = None
            self._click_type = self.CLICK_TYPE_SINGLE

    def _on_name_owner_changed(self, name, old, new):
        '''
        The daemon has de/registered the name.
        Called when dwell-click-enabled changes in gsettings.
        '''
        active = old == ""
        if active:
            self.launcher.stop()
        self._set_connection(active)

        # update hover click button
        for callback in self._daemon_running_notify_callbacks:
            callback(active)

    def daemon_running_notify_add(self, callback):
        self._daemon_running_notify_callbacks.append(callback)

    def _on_click_type_prop_changed(self, iface, changed_props, invalidated_props):
        ''' Either we or someone else has change the click-type. '''
        if self.MT_DBUS_PROP in changed_props:
            self._click_type = changed_props.get(self.MT_DBUS_PROP)

            # notify listeners
            for callback in self._click_type_callbacks:
                callback(self._click_type)

    def _get_mt_click_type(self):
        return self._click_type;

    def _set_mt_click_type(self, click_type):
        if click_type != self._click_type:# and self.is_active():
            self._click_type = click_type
            self._iface.Set(self.MT_DBUS_IFACE, self.MT_DBUS_PROP, click_type)

    ##########
    # Public
    ##########

    def state_notify_add(self, callback):
        """ Convenience function to subscribes to all notifications """
        self.dwell_click_enabled_notify_add(callback)
        self.click_type_notify_add(callback)
        self.daemon_running_notify_add(callback)

    def click_type_notify_add(self, callback):
        self._click_type_callbacks.append(callback)

    def is_active(self):
        return self.dwell_click_enabled and bool(self._iface)

    def set_active(self, active):
        self.dwell_click_enabled = active

        # try to launch mousetweaks if it isn't running yet
        if active and not self._iface:
            self._launch_daemon(1.0)
        else:
            self.launcher.stop()

    def supports_click_params(self, button, click_type):
        # mousetweaks since 3.3.90 supports middle click button too.
        return True

    def set_click_params(self, button, click_type):
        mt_click_type = click_type
        if button == self.SECONDARY_BUTTON:
            mt_click_type = self.CLICK_TYPE_RIGHT
        if button == self.MIDDLE_BUTTON:
            mt_click_type = self.CLICK_TYPE_MIDDLE
        self._set_mt_click_type(mt_click_type)

    def get_click_button(self):
        mt_click_type = self._get_mt_click_type()
        if mt_click_type == self.CLICK_TYPE_RIGHT:
            return self.SECONDARY_BUTTON
        if mt_click_type == self.CLICK_TYPE_MIDDLE:
            return self.MIDDLE_BUTTON
        return self.PRIMARY_BUTTON

    def get_click_type(self):
        mt_click_type = self._get_mt_click_type()
        if mt_click_type in [self.CLICK_TYPE_RIGHT, self.CLICK_TYPE_MIDDLE]:
            return self.CLICK_TYPE_SINGLE
        return mt_click_type