Opened 10 years ago

Closed 9 years ago

#16 closed task (fixed)

Add xsystray support

Reported by: dmik Owned by:
Priority: blocker Milestone: odinized java
Component: odin Version:
Severity: Keywords:


Odin32 already supports the SystTray? eCenter plugin by MadInt? however we have a better implementation called xsystray (so far, it's part of our Qt4 port). We should add support for xsystray too.

Change History (17)

comment:1 Changed 10 years ago by Silvan Scherrer

eventually we should only support xsystray, as i guess not many (if any at all) odin apps use systray so far

comment:2 Changed 10 years ago by abwillis

Systray can work with any app regardless of whether Odin is used. In fact... originally the systray was developed as a standalone API and then added to Odin later. PMVNC server for instance uses it. Any windows app that works with Odin will automatically use the systray if it is installed (e.g. Realplayer, lotus notes, etc.) these I would expect to continue working with xsystray if it were integrated with Odin. PMVNC server is the only OS/2 app that I can think of that uses the systray so is the only app I can think of that would need to be looked at if someone were of a mind to.

comment:3 Changed 9 years ago by Silvan Scherrer

Milestone: odinized java

comment:4 Changed 9 years ago by dmik

I added a tray icon test case (testapp/gui/systray). This test case shows the main problem with the current Systray/WPS based implementation: it can only show the icon set as the window icon in the systray. Since this test application attempts to set the icon through the NOTIFYICONDATA, it fails: instead of this icon, an empty rectangle is displayed in the systray (it's empty because the window doesn't have an icon due to another bug discussed below).

The xsystray plugin solves this issue as well as many others (e.g. it supports resurrecting icons after the xcenter restart).

The reason why the systray example window doesn't have an icon is that Odin seems to process some dialog window flags incorrectly so that tha system menu area (where the window icon is drawn) is completely hidden. I will try to fix that too.

Also, there is another problem that needs to be solved in order to build the example, see #33.

comment:5 Changed 9 years ago by dmik

In Odin they actually overcome the single icon limitation by creating a hidden frame window per every icon (quite an overkill) and the reason why it is not shown is some LoadIcon?() issues...

comment:6 Changed 9 years ago by dmik

Turns out that the icon is not shown because the one sent to the tray is not loaded with the LR_SHARED flag. I can't yet find how exactly this makes problems. Perhaps a non-shared icon gets deleted somewhere before being passed to the tray while the shared one stays alive.

This is kind of not correct because there is no such restriction on the Shell_NotifyIcon API and the client code may pass it whatever icon it has, not necessarily shared, and it should work.

comment:7 Changed 9 years ago by dmik

Aha, the client explicitly calls DestroyIcon?() after passing the icon handle to Shell_NotifyIcon(). This seems to be pretty legal as the very same program works well on a real Windows machine which means Windows makes a copy of the supplied icon in Shell_NotifyIcon(). Odin should behave the same way.

comment:8 Changed 9 years ago by dmik

I fixed the above problem in r21590. Note that we will be falling back to the current SysTray? implementation if xsystray is not found so it makes sense.

comment:9 Changed 9 years ago by dmik

xsystray support is there since r21592.

Note that xsystray itself is hosted in Qt4 SVN so far and we will create a separate WPI for it out of there (see for details).

I will also look if it's possible to implement the global notification message in Win32 terms that informs all top level widgets that the systray was restarted to give them an opportunity to reinstall their icons on xcenter restart or after a crash (both xsystray itself and Qt4 are capable of that). this MSDN article contains information about the Win32 part of things (search for "TaskbarCreated?").

comment:10 Changed 9 years ago by dmik

Strange, but for some reason Java applications don't get messages from the xsystray server posted with WinPostMsg?(): WinPostMsg?() succeeds, but no message gets delivered to the window procedue of the proxy class within Odin32. In the same time, the systray test application works well (same Odin32 and xsystray binaries). Trying to understand what's going on.

comment:11 Changed 9 years ago by dmik

Hmm, the message from the xsystray server does not reach the PM input hook installed by the xsystray client. Looks like Odin32 is cheating by installing a PM input hook on top of ours and eating all messages, even those he knows nothing about.

comment:12 Changed 9 years ago by dmik

The previous comment is apparently related to the usage of the system tray API from Java. I don't know what it is, but shortly after creating a tray icon though Java, the proxy window maintained by Odin (it maps xsystray notification messages to Win32 ones) stops responding to anything including WinSendMsg?(WM_NULL) from the own process...

Also, I couldn't find any WinSetHook? usage in Odin that would be on the way; it must be something else. Doesn't show up with simple Odin applications like the test case, only with heavy ones like Java/AWT.

comment:13 Changed 9 years ago by dmik

More over, it not only stops responding to WinSendMsg?() -- the latter API call actually never returns so that you have to Ctrl-Break the client process. Really strange, haven't seen anything like that before.

comment:14 Changed 9 years ago by dmik

What might be wrong is that the proxy window gets created on a thread that is then suspended by Java so that messages never reach its message queue...

comment:15 Changed 9 years ago by dmik

This is indeed the case. The tray icon is added on Thread 4 (which is the main Java thread) and then all GUI work gets moved to Thread 15 (this is the AWT event thread AFAICS) while Thread 4 is placed to the wait state (waiting for other threads to terminate and then terminate the application). I don't know why exactly they are changing threads in the Java application I've been trying (smartsvn) but apparently that trick is intended to work w/o such problems.

BTW, the wait call ends up in a Win32 API call served by WGSS50. One would expect that WGSS would process the message queue during wait as this is done by the original call on Win32 but apparently it doesn't do that.

So I'm afraid we will have to move xsystray client code to a separate thread in Odin32 to make this thread switch in Java work.

comment:16 Changed 9 years ago by dmik

I created a couple of helper routines to manage asynchronous calls on a global AUX thread. See r21595 and r21596 for details.

When using these routines, xsystray works well now. Will commit the changes after some more checks.

comment:17 Changed 9 years ago by dmik

Resolution: fixed
Status: newclosed

Implemented the "TaskbarCreated?" functionality in r21601. Applications supporting it (such as Java) will now recreate their taskbar icons when xCenter is restarted (this is also useful if xCenter is for some reason started later than the applications).

Note though that there is a bug in XWP (and may be earlier) so that if the "Animate" option is enabled in xCenter, the icons will not be properly redrawn after the xCenter restart. Disabling this option works it around.

This is now enough for this ticket. It was quite a bit of work already but we've done all we wanted and even more.

Note: See TracTickets for help on using tickets.