Issue
I have a simple Python code that creates a Linux tray indicator with AppIndicator3 from GI. That works fine. But I would like to detect and handle a simple user click or a double-click on this tray icon.
From what I know, for example, Telegram uses Qt class QSystemTrayIcon, and it supports this functionality because Telegram window shows itself when user double-clicks the tray icon.
- I know AppIndicator3 supports
scroll_event
signal that triggers when the user scrolls mouse wheel over the tray icon.
Signaled when the
AyatanaAppIndicator3.Indicator
receives a scroll event.
- There is also a
set_secondary_activate_target(menuitem)
method that indicates there is somehow handled middle-click event.
Set the
menuitem
to be activated when a secondary activation event (i.e. a middle-click) is emitted over theAyatanaAppIndicator3.Indicator
icon/label.
Is there somebody who understands how it works? Both previous examples make me wonder why there is not a simple mouse click signal/event. I'm thinking if it could be possible to go deeper, maybe inherit AyatanaAppIndicator3.Indicator class and rewrite some event handling? Or maybe dig even deeper into StatusNotifierItem and Activate method, if it is what AppIndicator implements?
Or is there any tricky workaround for this? Because this seems to be an unanswered question for more than ten years and I am not satisfied with only the "It is not possible" answer.
I'm also aware I'm not the first one asking this question. I made small research and found multiple related threads:
Python AppIndicator bindings -> howto check if the menu is open?
How to run an action when clicking on an appindicator
How to program a one click indicator (add middle click functionality)?
indicator-application does not send signals when a menu is shown/hidden
handle click events and modifiers
Solution
The perceived restrictions of AppIndicator are deliberate design choices (see Background information).
Listening to mouse click events will not work.
With AppIndicator you can have the following interactions:
- Primary action: Show a context menu (which may consist only of regular menu items, no arbitrary widgets can be placed).
- Secondary action: Activate one specific item in this context menu (usually middle mouse click on Desktops).
- Listen to mouse scroll events on the icon.
You will need to switch to another solution for detecting arbitrary mouse clicks. Here I assume you want to stick to Python/GTK as you tagged your question accordingly.
One solution is to use Gtk.StatusIcon which is based on the rather old System Tray Protocol Specification. Problem is this solution is slowly being phased out. It's marked deprecated in GTK3 and has been removed in GTK4.
The only other viable solution I know of is libxapps (by Mint Linux). It features XApp.StatusIcon which has been specifically designed to be a modern replacement for Gtk.StatusIcon. It supports all Desktop Environments that can show tray icons.
Background information
The Ubuntu Desktop Experience Team deemed the Linux Desktop notification area a "problem-area". Specifically they criticized the inconsistency of different application status icon in user experience and style. They proposed to restrict user interactions to a few standardized ways. This effort led to the development of AppIndicator. (Source)
By the way, here is another old (2011) albeit interesting blog post about different solutions:
StatusNotifierItem (aka App Indicators) for Qt applications
Answered By - buzz Answer Checked By - Willingham (WPSolving Volunteer)