Skip to content

Implement the Activate D-Bus method for primary click handling#4

Open
mikhailnov wants to merge 1 commit into
AyatanaIndicators:mainfrom
mikhailnov:activate-signal
Open

Implement the Activate D-Bus method for primary click handling#4
mikhailnov wants to merge 1 commit into
AyatanaIndicators:mainfrom
mikhailnov:activate-signal

Conversation

@mikhailnov
Copy link
Copy Markdown

Handle the org.kde.StatusNotifierItem Activate() method that KDE Plasma calls on left-click. When a signal handler is connected, emit the "activate" GObject signal and return success. When no handler is connected, return an error so the panel falls back to showing the context menu for backward compatibility.

This fixes the dual menu+toggle issue for applications like Onboard that need left-click to perform a custom action instead of showing the context menu.

Co-authored-by: Z.AI GLM


Why did I need this?

The Onboard https://github.com/onboard-osk/onboard virtual on-screen keyboard uses AppIndicator and can easily be switched to using Ayatana:

Description: Switch to AyatanaAppIndicator.
Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>

--- a/Onboard/Indicator.py
+++ b/Onboard/Indicator.py
@@ -294,7 +294,7 @@
         BackendBase.__init__(self, menu)
 
         try:
-            from gi.repository import AppIndicator3 as AppIndicator
+            from gi.repository import AyatanaAppIndicator3 as AppIndicator
         except ImportError as ex:
             raise RuntimeError(ex)
 
@@ -350,7 +350,7 @@
 
     def _set_indicator_active(self, active):
         try:
-            from gi.repository import AppIndicator3 as AppIndicator
+            from gi.repository import AyatanaAppIndicator3 as AppIndicator
         except ImportError:
             pass
         else:
--- a/Onboard/Version.py
+++ b/Onboard/Version.py
@@ -33,9 +33,9 @@
     except ValueError:
         pass
 
-    # AppIndicator3 is not required
+    # AyatanaAppIndicator3 is not required
     try:
-        gi.require_version('AppIndicator3', '0.1')
+        gi.require_version('AyatanaAppIndicator3', '0.1')
     except ValueError:
         pass

ROSA Linux package of onboard has used such patch for a long time.

Onboard can draw a tray icon either via the obsolete GtkStatusIcon, or via AppIndicator. GtkStatusIcon draws a pixelled, not high quality icon. AppIdincator draws a good icon.

Onboard tray icon opens and hides the keyboard via a left click (by a mouse or a finger on touch screens). With Ayatana AppIndicator, both a context menu and hide/show were triggered on right click. With this patch for AppIndicator it became possible to:

  • hide/show the keyboard via left click
  • show a context menu via right click

The patch for onboard is the following (it just removes hacks and simplifies its code):

diff --git a/Onboard/Indicator.py b/Onboard/Indicator.py
index ff620c3d..44891abe 100644
--- a/Onboard/Indicator.py
+++ b/Onboard/Indicator.py
@@ -25,11 +25,6 @@ import os
 import shutil
 import subprocess
 
-try:
-    import dbus
-except ImportError:
-    pass
-
 from Onboard.Version import require_gi_versions
 require_gi_versions()
 from gi.repository import GObject, Gtk
@@ -313,10 +308,6 @@ class BackendAppIndicator(BackendBase):
 
     _indicator = None
 
-    STATUSNOTIFIER_OBJECT = "/org/ayatana/NotificationItem/Onboard"
-    STATUSNOTIFIER_IFACE = "org.kde.StatusNotifierItem"
-    ACTIVATE_METHOD = "Activate"
-
     def __init__(self, menu):
         BackendBase.__init__(self, menu)
 
@@ -336,42 +327,16 @@ class BackendAppIndicator(BackendBase):
         self._indicator.set_secondary_activate_target(
             menu._menu.get_children()[0])
 
-        if "dbus" in globals():
-            # Watch left-click Activate() calls on desktops that send them
-            # (KDE Plasma). There is still "No such method 'Activate'" in
-            # AppIndicator.
-            try:
-                self._bus = dbus.SessionBus()
-            except dbus.exceptions.DBusException as ex:
-                _logger.warning("D-Bus session bus unavailable, "
-                                "no left-click Activate() for AppIndicator: " +
-                                unicode_str(ex))
-            else:
-                try:
-                    self._bus.add_match_string(
-                        "type='method_call',"
-                        "eavesdrop=true,"
-                        "path='{}',"
-                        "interface='{}',"
-                        "member='{}'"
-                        .format(self.STATUSNOTIFIER_OBJECT,
-                                self.STATUSNOTIFIER_IFACE,
-                                self.ACTIVATE_METHOD))
-                    self._bus.add_message_filter(self._on_activate_method)
-                except dbus.exceptions.DBusException as ex:
-                    _logger.warning("Failed to setup D-Bus match rule, "
-                                    "no left-click Activate() for AppIndicator: " +
-                                    unicode_str(ex))
+        # Connect to the "activate" signal for left-click handling.
+        # The library handles the D-Bus Activate method and emits this
+        # signal when the tray icon is left-clicked (e.g. in KDE Plasma).
+        self._indicator.connect("activate",
+                                lambda indicator, x, y:
+                                menu.on_show_keyboard_toggle())
 
     def cleanup(self):
         pass
 
-    def _on_activate_method(self, bus, message):
-        if message.get_path() == self.STATUSNOTIFIER_OBJECT and \
-           message.get_member() == self.ACTIVATE_METHOD:
-            self._menu.on_show_keyboard_toggle()
-        return dbus.connection.HANDLER_RESULT_NOT_YET_HANDLED
-
     def set_visible(self, visible):
         self._set_indicator_active(visible)

I will try to upstreamize it into Onboard (https://github.com/onboard-osk/onboard) if this PR is merged here.

Handle the org.kde.StatusNotifierItem Activate() method that KDE Plasma
calls on left-click. When a signal handler is connected, emit the
"activate" GObject signal and return success. When no handler is
connected, return an error so the panel falls back to showing the
context menu for backward compatibility.

This fixes the dual menu+toggle issue for applications like Onboard
that need left-click to perform a custom action instead of showing
the context menu.

Co-authored-by: Z.AI GLM
@mikhailnov
Copy link
Copy Markdown
Author

I undertstand that libayatana-appindicator is depreceated, but libayatana-appindicator-glib cannot be used, because KDE cannot work with otg.gtk.Menus - context menus do not work.

Similar PR to ibayatana-appindicator-glib: AyatanaIndicators/libayatana-appindicator-glib#101 (but it seems to be not suitable for onboard until KDE becomes able to read context menus from org.gtk.Menus, if ever)

@mikhailnov
Copy link
Copy Markdown
Author

mikhailnov commented Apr 28, 2026

org.kde.StatusNotifierItem has X and Y coordinates, but I am not sure if they can work in Wayland... Onboard is for X11 only - ther eis no good alternative for Wayland.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant