source: trunk/src/shell32/systray_os2ex.c@ 21600

Last change on this file since 21600 was 21600, checked in by dmik, 14 years ago

shell32: systray: Fixed non-working systray notifications in modern Java apps by maintaining the xsystray proxy window on a dedicated thread that is never suspended by Java. Also added support for context menu (normally, RMB) notifications used in many Java applications.

  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
1/*
2 * OS/2 System Tray support.
3 * A better implementaiton using the xsystray XCenter/eCenter widget API.
4 *
5 * Author: Dmitriy Kuminov
6 */
7
8#define INCL_PM
9#define INCL_DOS
10#define INCL_DOSERRORS
11#include <os2wrap.h> // Odin32 OS/2 api wrappers
12
13#include <win32api.h>
14
15#include <string.h>
16
17// declare function pointers for dynamic linking to xsystray DLL
18#define XSTAPI_FPTRS_STATIC
19#include <xsystray.h>
20
21#include "systray_os2.h"
22
23#include "dbglog.h"
24
25#define WM_XST_MYNOTIFY (WM_USER + 1000)
26
27static ULONG WM_XST_CREATED = 0;
28
29static HWND hwndProxy = NULLHANDLE;
30static ULONG hwndProxyRefs = 0;
31
32static PFNWP OldProxyWndProc = NULL;
33
34static MRESULT EXPENTRY ProxyWndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
35{
36 switch (msg)
37 {
38 case WM_XST_MYNOTIFY:
39 {
40 USHORT usIconID = SHORT1FROMMP(mp1);
41 USHORT usNotifyCode = SHORT2FROMMP(mp1);
42
43 SystrayItem *ptrayItem = SYSTRAY_FindItem(usIconID);
44 if (!ptrayItem)
45 return (MRESULT)FALSE;
46
47 switch (usNotifyCode)
48 {
49 case XST_IN_MOUSE:
50 {
51 PXSTMOUSEMSG pmmsg = (PXSTMOUSEMSG)mp2;
52 ULONG winMsg = 0;
53
54 switch (pmmsg->ulMouseMsg)
55 {
56 case WM_BUTTON1DBLCLK: winMsg = WM_LBUTTONDBLCLK_W; break;
57 case WM_BUTTON2DBLCLK: winMsg = WM_RBUTTONDBLCLK_W; break;
58 case WM_BUTTON3DBLCLK: winMsg = WM_MBUTTONDBLCLK_W; break;
59 case WM_BUTTON1UP: winMsg = WM_LBUTTONUP_W; break;
60 case WM_BUTTON2UP: winMsg = WM_RBUTTONUP_W; break;
61 case WM_BUTTON3UP: winMsg = WM_MBUTTONUP_W; break;
62 case WM_BUTTON1DOWN: winMsg = WM_LBUTTONDOWN_W; break;
63 case WM_BUTTON2DOWN: winMsg = WM_RBUTTONDOWN_W; break;
64 case WM_BUTTON3DOWN: winMsg = WM_MBUTTONDOWN_W; break;
65 default: break;
66 }
67
68 if (winMsg)
69 {
70 DoWin32PostMessage(ptrayItem->notifyIcon.hWnd,
71 ptrayItem->notifyIcon.uCallbackMessage,
72 (MPARAM)ptrayItem->notifyIcon.uID,
73 (MPARAM)winMsg);
74 return (MRESULT)TRUE;
75 }
76 break;
77 }
78 case XST_IN_CONTEXT:
79 {
80 DoWin32PostMessage(ptrayItem->notifyIcon.hWnd,
81 ptrayItem->notifyIcon.uCallbackMessage,
82 (MPARAM)ptrayItem->notifyIcon.uID,
83 (MPARAM)WM_CONTEXTMENU_W);
84 return (MRESULT)TRUE;
85 }
86 default:
87 break;
88 }
89
90 return (MRESULT)FALSE;
91 }
92 default:
93 {
94 if (msg == WM_XST_CREATED)
95 {
96 return (MRESULT)TRUE;
97 }
98 break;
99 }
100 }
101
102 return WinDefWindowProc(hWnd, msg, mp1, mp2);
103}
104
105static BOOL SYSTRAY_Ex_ItemInit(SystrayItem *ptrayItem)
106{
107 if (hwndProxyRefs == 0)
108 {
109 if (!WinRegisterClass(NULLHANDLE, "OdinXSysTrayProxy", ProxyWndProc,
110 0, 0))
111 {
112 dprintf(("SHELL32: SYSTRAY: WinRegisterClass() failed with %x",
113 WinGetLastError(0)));
114 return FALSE;
115 }
116
117 hwndProxy = WinCreateWindow(HWND_DESKTOP, "OdinXSysTrayProxy", NULL,
118 0, 0, 0, 0, 0, NULLHANDLE, HWND_BOTTOM, 0,
119 NULL, NULL);
120
121 if (hwndProxy == NULLHANDLE)
122 {
123 dprintf(("SHELL32: SYSTRAY: WinCreateWindow() failed with %x",
124 WinGetLastError(0)));
125 return FALSE;
126 }
127 }
128
129 ++ hwndProxyRefs;
130
131 return TRUE;
132}
133
134static void SYSTRAY_Ex_ItemTerm(SystrayItem *ptrayItem)
135{
136 xstRemoveSysTrayIcon(hwndProxy, ptrayItem->uIdx);
137
138 if (-- hwndProxyRefs == 0)
139 {
140 WinDestroyWindow(hwndProxy);
141 hwndProxy = NULLHANDLE;
142 }
143}
144
145static void SYSTRAY_Ex_ItemUpdate(SystrayItem *ptrayItem, ULONG uFlags)
146{
147 if (uFlags == 0 || (uFlags & (NIF_ICON | NIF_TIP) == NIF_ICON | NIF_TIP))
148 {
149 // uFlags = 0 means it's the first time so add the icon. The other case
150 // is true when a bunch of the parameters is changed at once so use
151 // xstAdd... too to save a few IPC calls.
152 xstAddSysTrayIcon(hwndProxy, ptrayItem->uIdx,
153 ptrayItem->notifyIcon.hIcon,
154 ptrayItem->notifyIcon.szTip,
155 WM_XST_MYNOTIFY,
156 XST_IN_MOUSE | XST_IN_CONTEXT);
157 return;
158 }
159
160 if (uFlags & NIF_ICON)
161 {
162 xstReplaceSysTrayIcon(hwndProxy, ptrayItem->uIdx,
163 ptrayItem->notifyIcon.hIcon);
164 }
165 if (uFlags & NIF_TIP)
166 {
167 xstSetSysTrayIconToolTip(hwndProxy, ptrayItem->uIdx,
168 ptrayItem->notifyIcon.szTip);
169 }
170}
171
172BOOL SYSTRAY_Ex_Init(void)
173{
174 static BOOL tried = FALSE;
175 if (!tried) {
176 char err[CCHMAXPATH];
177 HMODULE hmod;
178
179 tried = TRUE;
180
181 // link to the xsystray DLL at runtime
182 if (DosLoadModule(err, sizeof(err), "XSYSTRAY", &hmod) != NO_ERROR)
183 return FALSE;
184
185 #define R(f) if (DosQueryProcAddr(hmod, 0, #f, (PFN*)&f) != NO_ERROR) return FALSE
186
187 R(xstQuerySysTrayVersion);
188 R(xstAddSysTrayIcon);
189 R(xstReplaceSysTrayIcon);
190 R(xstRemoveSysTrayIcon);
191 R(xstSetSysTrayIconToolTip);
192 R(xstQuerySysTrayIconRect);
193 R(xstGetSysTrayCreatedMsgId);
194 R(xstGetSysTrayMaxTextLen);
195
196 #undef R
197 }
198
199 // check if xsystray is there
200 if (!xstQuerySysTrayVersion(NULL, NULL, NULL))
201 return FALSE;
202
203 // initialize some constants
204 WM_XST_CREATED = xstGetSysTrayCreatedMsgId();
205
206 SYSTRAY_ItemInit = SYSTRAY_Ex_ItemInit;
207 SYSTRAY_ItemTerm = SYSTRAY_Ex_ItemTerm;
208 SYSTRAY_ItemUpdate = SYSTRAY_Ex_ItemUpdate;
209
210 return TRUE;
211}
212
Note: See TracBrowser for help on using the repository browser.