Eto: Add a tray icon control

Created on 7 Mar 2015  ·  33Comments  ·  Source: picoe/Eto

enhancement

Most helpful comment

Wpf implementation done:
wpf

All 33 comments

Yes, there is NotifyIcon class in .Net framework, but i was unable to use it properly.

"The common NotifyIcon isn't visible if you're running a default KDE-desktop;
it requires a Gnome Panel called Notification Area Applet"
http://www.codeproject.com/Articles/466805/AmberIndicator-a-systray-app-under-Linux

"On openSUSE, Fedora and Ubuntu, NotifyIcon is not usable"
https://bugzilla.novell.com/show_bug.cgi?id=590093

"NotifyIcon does not show up in the systray (Tested on OS: Fedora, Arch. DE: MATE, Cinnamon)"
https://bugzilla.xamarin.com/show_bug.cgi?id=14976

There should be something more integrated with DBus.

The basic idea is that creating an icon in the notification area
is less annoying than popping up a dialog (dialog interrupts current work, and icon can be ignored by user for some time). However icon is also harder to notice, so there is a feature allowing tray icons to pop up small message balloons (can the balloon contain images or video streams from entry door camera? or it display strings only?). In particular, that mean that balloon should dissapear after some time (but Rigo manager does wrong - it requires user to close it's balloon manually)

There is also _Workspace Switcher Applet_ which would be nice to integrate with through DBus. Usage scenario - MDI programs which should show different set of documents on different workspaces. I created another feature request for workspaces - https://github.com/picoe/Eto/issues/409

"GNOME system tray can be horizontal or vertical"

"The system tray coordinates balloon messages to ensure that they have a consistent look-and-feel, and to avoid displaying multiple balloon messages at once. ... System trays may receive portions of messages from several tray icons at once, so are required to reassemble the messages based on the window ID of the tray icon.... A balloon message is a short text message. ... The message may have a timeout; if so, the message will be taken down after the timeout expires. ...The tray icon may wish to cancel a previously-sent balloon message."

mono's NotifyIcon on Notification Area

some urls:

  1. GNOME Human Interface Guidelines 2.2.3 Desktop Integration
    https://developer.gnome.org/hig-book/unstable/desktop-notification-area.html.en
  2. System Tray Protocol Specification
    http://standards.freedesktop.org/systemtray-spec/latest/
  3. Inter-Client Communication Conventions Manual
    http://www.x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html
  4. XEmbed Protocol Specification (protocol for cross-toolkit widget embedding)
    http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
  5. Extended Window Manager Hints
    http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
  6. System.Windows.Forms.NotifyIcon (MSDN)
    https://msdn.microsoft.com/ru-ru/library/system.windows.forms.notifyicon%28v=vs.110%29.aspx
  7. NotifyIcon implementation in mono
    https://github.com/mono/mono/blob/ef380e3712af86ef7f8064fab19400523c7510c0/mcs/class/System.Windows.Forms/System.Windows.Forms/NotifyIcon.cs#L38
  8. Examples for mono's NotifyIcon
    https://github.com/mono/winforms/blob/master/notifyicon/swf-notifyicon.cs
    https://github.com/mono/winforms/blob/master/notifyicon/swf-balloon.cs
  9. KeePass uses NotifyIcon:
    http://sourceforge.net/p/keepass/bugs/1212/
  10. Gtk# example
    http://www.mono-project.com/docs/gui/gtksharp/widgets/notification-icon/
    Gtk.StatusIcon
    http://askubuntu.com/questions/13197
    https://developer.gnome.org/gtk3/stable/GtkStatusIcon.html

According to GNOME HIG, there are 2 ways to add an icon to the panel:
panels-and-area

a. The panel applet (these are on left from "Wanda-the-fish")
b. Notification area icon (Notification panel itself is added to the panel as panel appet)

Mono implements the "Notification area icon" on top of X11 specification (directly, without Gtk#).

mono uses XplatUI interface with methods
SystrayAdd, SystrayRemove, SystrayChange, SystrayBalloon, SendMessage, SetForegroundWindow
https://github.com/mono/mono/blob/ef380e3712af86ef7f8064fab19400523c7510c0/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUI.cs#L1106-L1128
the calls are forwarded to member

 static XplatUIDriver driver;

which is of type ??? for MATE environment.

I don't know what chooses which driver to use. Probably it is XplatUIX11, which is selected in this line:
https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUI.cs#L112

tray icon is a window

The tray icon is a window to be embedded in the system tray.

internal class NotifyIconWindow : Form { ... // line 57
private NotifyIconWindow window; // line 45
window = new NotifyIconWindow(this); // line 389
XplatUI.SystrayAdd(window.Handle, text, icon, out tooltip); // line 524

Problem with drawing:
https://bugzilla.novell.com/show_bug.cgi?id=324237#c13
"On 64bit machines, the icon does NOT show up in the tray at all."

Problem with transparency:
http://lists.ximian.com/pipermail/mono-winforms-list/2007-December/003173.html
the reason of the problem is the line 189
(this is unfixed bug with 8 years history)
but, the attachment in the mailing list message contains example code of application.
see also
http://standards.freedesktop.org/systemtray-spec/latest/ar01s06.html

Problem with redrawing:
http://mono.1490590.n4.nabble.com/NotifyIcon-and-ContextMenu-redrawing-issues-in-gnome-td1541474.html
https://bugzilla.novell.com/show_bug.cgi?id=324237
https://bugzilla.novell.com/show_bug.cgi?id=MONO81668

_NET_SYSTEM_TRAY_S

The conventions for manager selections are defined in the ICCCM ( http://www.x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#manager_selections ).
The system tray is an X client which owns a special manager selection on a given screen.
An application wishing to provide an icon to the system tray should first locate the system tray
by requesting the owner window of the manager selection.
If the manager selection has no owner, clients may use the method described in the ICCCM (watching for a MANAGER client message) to be notified when a system tray appears.

the selection owner window will not be the same as any of the user-visible windows provided by the system tray (in other words - manager selection probably is not the same window that's used to contain the system tray icons), because the selection owner window should be destroyed when the manager selection is lost.

the system tray must acquire a manager selection called _NET_SYSTEM_TRAY_Sn, replacing n with the screen number the tray wants to use:

  • https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUIX11.cs#L729

XGrabServer(DisplayHandle); SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S); XUngrabServer(DisplayHandle); XFlush(DisplayHandle);

  • https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/mcs/class/System.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs#L345

Xlib.XGrabServer (display); IntPtr SystrayMgrWindow = Xlib.XGetSelectionOwner (display, Atoms._NET_SYSTEM_TRAY_S); Xlib.XUngrabServer (display);

SYSTEM_TRAY_REQUEST_DOCK

the message format is described here:
http://standards.freedesktop.org/systemtray-spec/latest/ar01s04.html
Is it possible to send X messages without using Xlib and it's underlaying XCB library
i.e. directly from C# code to "wire"?

https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/mcs/class/System.Windows.Forms/System.Windows.Forms/XplatUIX11.cs#L6259

    SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);

https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/mcs/class/System.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs#L413-L417

    SendNetClientMessage (SystrayMgrWindow,
        Atoms._NET_SYSTEM_TRAY_OPCODE,
        IntPtr.Zero,
        (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK,
        hwnd.WholeWindow);

Icon as Panel Applet

https://en.wikipedia.org/wiki/D-Bus
D-BUS is an interprocess communication (IPC) system, providing a simple yet powerful mechanism allowing applications to talk to one another, communicate information and request services.
"D-BUS can become a unified and agnostic IPC mechanism used by both desktops (GNOME and KDE)"
_but, but, but - ICCCM is also interprocess, unified and agnostic..._
see The Kernel Event Layer - DBus a single bus shared by the entire system allows for propagation of events, from the kernel to the uppermost applications on the system.
Events such as disk full and printer queue empty or even battery power low can bubble up the system stack, available for whatever application cares, allowing the system to respond and react.

  1. The D-Bus specification
    http://dbus.freedesktop.org/doc/dbus-specification.html

  2. DBus library for C# (not a wrapper, pure C#)
    https://github.com/mono/dbus-sharp

  3. Panel Applet Library Reference Manual
    https://developer.gnome.org/panel-applet/stable/

  4. GnomeGoal is to port all Gnome applets to the new DBUS api (from Bonobo).
    https://wiki.gnome.org/Initiatives/GnomeGoals/AppletsDbusMigration

is there such thing as Ubuntu-panel applets?

Gnome- vs Unity-panel (applet) compatibility
http://ubuntu.itsprite.com/ubuntugnome-vs-unity-panel-applet-compatibility/

Application Indicators
(Ayatana, Unity, Ubuntu)

Status Notifier Specification (SNI, org.freedesktop.StatusNotifierItem)
http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/
"It is intended to be a replacement to the Freedesktop System tray specification ...
it’s used in production by at least KDE Plasma and Unity"

  1. Application Panel Indicators
    https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators

libappindicator Reference Manual
http://developer.ubuntu.com/api/devel/ubuntu-12.04/c/appindicator/

Ayatana Indicators in the Gnome Panel:
https://launchpad.net/indicator-applet

There is an panel applet for MATE:
https://github.com/mate-desktop/mate-indicator-applet
to display information from various applications consistently in the panel.

Notification icon in Ubuntu with Unity and Mono C# example:
http://www.arvydas.co.uk/2012/08/notification-icon-in-ubuntu-with-unity-and-mono-c-sharp-example/

Each indicator installs a small file in /usr/share/unity/indicators which defines where to find it on DBus and how it should be displayed in the panel. Indicator process are managed by the session init daemon.

Desktop Notifications Specification
http://www.galago-project.org/specs/notification/0.9/index.html
" Images may be placed in the notification, but this should be done with caution. The image should never exceed 200x100, but this should be thought of as a maximum size."

https://wiki.ubuntu.com/MessagingMenu/

How to make menu panel transparent:
http://www.linuxandlife.com/2012/05/ubuntu-panel-transparent.html

"indicators can only contain a label or an icon in the panel
no custom rendering or other widgets"
Application Indicators use a fixed icon size of 22 pixels.
https://bugs.launchpad.net/ubuntu/+source/indicator-application/+bug/533439
"Libindicator API does not allow to specify the icon size and
therefore the convention is that all icon sizes are 22px."

alter and update the status icon of a running indicator applet
http://www.helptouser.com/ubuntu/11162-is-it-possible-to-alter-and-update-the-status-icon-of-a-running-indicator-applet.html

The System Tray widget (Plasma/KDE)

  1. The System Tray widget displays system information, notifications, and services
    https://userbase.kde.org/Plasma/SystemTray

xembed items are hard coded to 22×22 pixels

Status Notifier Specification, KStatusNotifierItem class
https://github.com/lxde/lxqt/issues/359

March 2014-03-04, System Tray in Plasma Next
http://blog.martin-graesslin.com/blog/2014/03/system-tray-in-plasma-next/

"we do not want to invest the time in implementing the legacy (xembed) system for Plasma Next"
"most GTK+ applications also use the appindicator library for unity integration, so they just work the way we want it"
"Though it will take until Qt 5.4 till the feature will be working properly."
"it’s possible that there are applications which still use the legacy protocol and that will break."

GNOME Shell Message Tray

https://wiki.gnome.org/Design/OS/MessageTray
"The Message Tray design pages are out of date, and are being retained for reference purposes only. For up to date designs, see the notifications page"
https://wiki.gnome.org/Design/OS/Notifications

There is also 3-rd party "Indicator Applet" for Gnome 3 in repositories of Ubuntu:
https://code.launchpad.net/~jconti/indicator-applet/gnome3

http://live.gnome.org/GnomeShell/Extensions

GNOME Shell allows for very limited customization (by design) and the system tray is not one of those areas. In fact the very fact that it exists is only to support certain legacy applications.

"Systray icons are seen as common source of distraction, which the devs want to get rid of."

"if we are going to deal with the problem properly, we need to establish a new API and give applications time to port over to it. We are currently working on a plan for this."

http://worldofgnome.org/shell-new-notifications-goodbye-message-tray/
2014-01-05, "GNOME developers are planning some significant changes towards to a completely new notifications system."

https://blogs.gnome.org/aday/2014/06/18/a-notifications-update/
Fedora 22 (GNOME 3.16) introduced this expandable legacy icon bar in the bottom-left corner of the screen:

legacy "tray" icons are displayed in a "drawer" that uses autohide in the bottom left corner of the screen.
Gnome 3.16 release notes

https://github.com/gnome-design-team/gnome-mockups/tree/master/notifications

gnome-design or #gnome-shell IRC channels

https://developer.gnome.org/notification-spec/

WingPanel from Elementary OS

Stylish top panel that holds indicators and spawns an application launcher

elementary OS deprecating ayatana indicators:
https://github.com/dyson/indicator-workspaces/issues/3

These new indicators have quite a bit more freedom (You're not confined to a menu design, can have any widget in them now), so that might be something for you to look out for. ;) Ayatana indicators will still technically be supported

One example of working with panels is Workrave application.
it have a class for each type of panel.
there https://github.com/rcaelers/workrave/tree/7cb9aef971f21c9a473146f9b72693b86a4a76f6/frontend/applets are
"cinnamon", "common", "gnome-shell", "gnome2", "gnome3", "indicator", "mate", "win32", "xfce"

Can somebody answer for my simple questions?

1) Can we now create tray icons with Eto?
2) Which OS are supported?
3) Where can I read that? Maybe class name?

Bad news, still no support, good news, I was gonna implement this for Linux and Windows over this weekend :)

Really cool! :) Is only merge required now?

And MAC OS?

I do not think we need tray emulation in Android :)

Really cool! :) Is only merge required now?

I still haven't started working on it... however I do know what needs to be done and I had to do #714 beforehand.

And MAC OS?

Someone else will need to implement it for MacOS, the only MacOS I have is on a VirtualBox, which is slow as hell.

Linux Gtk version almost done :D

indicator

Good work! :)

Is it regular window or popup with limited content allowed?

Good work! :)

Is it regular window or popup with limited content allowed?

That's just how context menu looks on GNOME with libappindicator extension on :P

Without the weird extensions I have on my system it looks like:

withoutextension

That's just how context menu looks on GNOME with libappindicator extension on :P

Not sure I understand... I mentioned if it is possible to display any content there for example image instead of Hello World? For example in Windows we cannot do that (only menu items with icons).. to get that we have to implement own window and display it near tray icon or mouse click. In addition we will have to translate coordinates because tray icon (which most likely will be used) is part of Windows.Forms not WPF.

Again... it's just how a context menu looks on my system... look at the second screenshot, it's showing the exact same thing except with part of my theming disabled.

@hardhub afaik, you can put custom controls in a menu item with winforms (and macOS). I don't know if this would work on GTK# though.

@cwensley I just have to report one negative thing on this, appindicator does not allow loading icons from memory... so I had to make Eto's API for TrayIcon load it from an actual filepath...

@cra0zy well that is pretty sucky. Perhaps we can write to a temp file or something..

@cwensley,

I mean this:
https://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.windows.forms.menuitem(v=vs.110).aspx

You can put only text and icon there...

@cra0zy well that is pretty sucky. Perhaps we can write to a temp file or something..

That's what I already did.

@hardhub ah right, it uses MenuItem, not ToolStripMenuItem.. ugh. Either way, we can just build in the custom window functionality into the windows platform so it won't have to be manually implemented when you want to use it.

Are you guys talking about a left click window like volume mixer was in Windows 7? I am a bit confused...

Anyway the following is the stucture of the API:
```c#
public bool Visible { get; set; }

public string Title { get; set; }

public event Activated { get; set; }

public void SetMenu(ContextMenu menu);

public void SetIcon(Icon icon);

public void Show();

public void Hide();
```

@cra0zy, I think left click opens custom window. I wrote about right click. At least you example with "Quit" item looks like right-click menu.

@cwensley

We can try to use ContextMenuStrip property... but I think it will not be able to add anything custom...
https://msdn.microsoft.com/en-us/library/system.windows.forms.contextmenustrip(v=vs.110).aspx

I think you mentioned we can add image on the left of menu item... yes we can.. but I said about custom layout of popup available from system tray. I mentioned image as custom content not as some small icon on the left of item.

WinForms implementation done:
winforms

Gtk Mac/Windows implementation done:
2

Wpf implementation done:
wpf

PR up: #731

@cwensley This can be closed.

@cra0zy still need to do Mac port but that's covered with #750

Was this page helpful?
0 / 5 - 0 ratings