source: trunk/src/shell32/systray.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.

File size: 7.8 KB
Line 
1/*
2 * Systray
3 *
4 * Copyright 1999 Kai Morich <kai.morich@bigfoot.de>
5 *
6 * Manage the systray window. That it actually appears in the docking
7 * area of KDE or GNOME is delegated to windows/x11drv/wnd.c,
8 * X11DRV_WND_DockWindow.
9 *
10 * Modified by ErOs2 and Dmitriy Kuminov for usage with systray_os2.c
11 *
12 */
13
14#ifndef __WIN32OS2__
15#include <unistd.h>
16#endif
17#include <stdlib.h>
18#include <string.h>
19
20#include "winnls.h"
21#include "shlobj.h"
22#include "shellapi.h"
23#include "shell32_main.h"
24#include "commctrl.h"
25#include "debugtools.h"
26#include "heap.h"
27#include "config.h"
28#include "winuser32.h"
29#include "auxthread.h"
30
31#include "systray.h"
32
33DEFAULT_DEBUG_CHANNEL(shell);
34
35
36struct _SystrayItem {
37 HWND hWnd;
38 HWND hWndToolTip;
39 NOTIFYICONDATAA notifyIcon;
40 UINT uIdx;
41 struct _SystrayItem *nextTrayItem;
42};
43
44static SystrayItem *systray = NULL;
45
46BOOL (*SYSTRAY_ItemInit)(SystrayItem *ptrayItem) = 0;
47void (*SYSTRAY_ItemTerm)(SystrayItem *ptrayItem) = 0;
48void (*SYSTRAY_ItemUpdate)(SystrayItem *ptrayItem, ULONG uFlags) = 0;
49
50static BOOL SYSTRAY_ItemIsEqual(PNOTIFYICONDATAA pnid1, PNOTIFYICONDATAA pnid2)
51{
52 if (pnid1->hWnd != pnid2->hWnd) return FALSE;
53 if (pnid1->uID != pnid2->uID) return FALSE;
54 return TRUE;
55}
56
57static BOOL SYSTRAY_Add(PNOTIFYICONDATAA pnid)
58{
59 SystrayItem *pItem = systray, *pPrevItem = NULL, *ptrayItem;
60 ULONG uIdx = 0;
61
62 /* Search for the first free index and also check if already in list */
63 while (pItem)
64 {
65 if (SYSTRAY_ItemIsEqual(pnid, &pItem->notifyIcon))
66 return FALSE;
67
68 uIdx = pPrevItem->uIdx + 1;
69
70 if (pPrevItem && pItem->uIdx - pPrevItem->uIdx > 1)
71 {
72 /* found a hole in the index row, will insert here */
73 break;
74 }
75
76 pPrevItem = pItem;
77 pItem = pItem->nextTrayItem;
78 }
79
80 /* check the rest (if any) for duplicates */
81 ptrayItem = pItem;
82 while (ptrayItem)
83 {
84 if (SYSTRAY_ItemIsEqual(pnid, &ptrayItem->notifyIcon))
85 return FALSE;
86 ptrayItem = ptrayItem->nextTrayItem;
87 }
88
89 /* Allocate SystrayItem for the new element and insert it */
90 ptrayItem = ( SystrayItem *)malloc(sizeof(SystrayItem));
91 memset(ptrayItem, 0, sizeof(SystrayItem));
92 ptrayItem->nextTrayItem = pItem;
93
94 if (pPrevItem)
95 {
96 pPrevItem->nextTrayItem = ptrayItem;
97 ptrayItem->uIdx = pPrevItem->uIdx + 1;
98 }
99 else
100 {
101 systray = ptrayItem;
102 ptrayItem->uIdx = 0;
103 }
104
105 /* Initialize and set data for the tray element. */
106 ptrayItem->uIdx = uIdx;
107
108 ptrayItem->notifyIcon.uID = pnid->uID;
109 ptrayItem->notifyIcon.hWnd = pnid->hWnd;
110
111 ptrayItem->notifyIcon.hIcon =
112 (pnid->uFlags & NIF_ICON) ? GetOS2Icon(pnid->hIcon) : 0;
113 ptrayItem->notifyIcon.uCallbackMessage =
114 (pnid->uFlags & NIF_MESSAGE) ? pnid->uCallbackMessage : 0;
115
116 if (pnid->uFlags & NIF_TIP)
117 CharToOemA(pnid->szTip, ptrayItem->notifyIcon.szTip);
118 else
119 ptrayItem->notifyIcon.szTip[0] = '\0';
120
121 /* Implementation specific initialization */
122 if (!SYSTRAY_ItemInit(ptrayItem))
123 {
124 free(ptrayItem);
125 if (pPrevItem)
126 pPrevItem->nextTrayItem = pItem;
127 else
128 systray = NULL;
129 return FALSE;
130 }
131
132 /* Trigger the data update (flags = 0 means it's the first time) */
133 SYSTRAY_ItemUpdate(ptrayItem, 0);
134
135 TRACE("SYSTRAY_Add %p: uIdx %u, hWnd 0x%08x, uID %d, hIcon 0x%08x, "
136 "uCallbackMessage 0x%08x, szTip [%s]\n",
137 ptrayItem, ptrayItem->uIdx, ptrayItem->hWnd, ptrayItem->notifyIcon.uID,
138 ptrayItem->notifyIcon.hIcon,ptrayItem->notifyIcon.uCallbackMessage,
139 ptrayItem->notifyIcon.szTip);
140
141 return TRUE;
142}
143
144static BOOL SYSTRAY_Modify(PNOTIFYICONDATAA pnid)
145{
146 SystrayItem *ptrayItem = systray;
147
148 while (ptrayItem)
149 {
150 if (SYSTRAY_ItemIsEqual(pnid, &ptrayItem->notifyIcon))
151 {
152 if (pnid->uFlags & NIF_ICON)
153 ptrayItem->notifyIcon.hIcon = GetOS2Icon(pnid->hIcon);
154 if (pnid->uFlags & NIF_MESSAGE)
155 ptrayItem->notifyIcon.uCallbackMessage = pnid->uCallbackMessage;
156 if (pnid->uFlags & NIF_TIP)
157 CharToOemA(pnid->szTip, ptrayItem->notifyIcon.szTip);
158
159 SYSTRAY_ItemUpdate(ptrayItem, pnid->uFlags);
160
161 TRACE("SYSTRAY_Modify %p: uIdx %u, hWnd 0x%08x, uID %d, hIcon 0x%08x, "
162 "uCallbackMessage 0x%08x, szTip [%s]\n",
163 ptrayItem, ptrayItem->uIdx, ptrayItem->hWnd, ptrayItem->notifyIcon.uID,
164 ptrayItem->notifyIcon.hIcon,ptrayItem->notifyIcon.uCallbackMessage,
165 ptrayItem->notifyIcon.szTip);
166
167 return TRUE;
168 }
169 ptrayItem = ptrayItem->nextTrayItem;
170 }
171
172 return FALSE; /* not found */
173}
174
175static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid)
176{
177 SystrayItem **ptrayItem = &systray;
178
179 while (*ptrayItem)
180 {
181 if (SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon))
182 {
183 SystrayItem *next = (*ptrayItem)->nextTrayItem;
184
185 TRACE("SYSTRAY_Delete %p: uIdx %u, hWnd 0x%08x, uID %d\n",
186 *ptrayItem, (*ptrayItem)->uIdx, (*ptrayItem)->notifyIcon.hWnd,
187 (*ptrayItem)->notifyIcon.uID);
188
189 SYSTRAY_ItemTerm(*ptrayItem);
190
191 free(*ptrayItem);
192 *ptrayItem = next;
193
194 return TRUE;
195 }
196 ptrayItem = &((*ptrayItem)->nextTrayItem);
197 }
198
199 return FALSE; /* not found */
200}
201
202#ifndef __WIN32OS2__
203/*************************************************************************
204 *
205 */
206BOOL SYSTRAY_Init(void)
207{
208 return TRUE;
209}
210#endif
211
212/*************************************************************************
213 *
214 */
215SystrayItem *SYSTRAY_FindItem(ULONG uIdx)
216{
217 SystrayItem *ptrayItem = systray;
218
219 while (ptrayItem)
220 {
221 if (ptrayItem->uIdx == uIdx)
222 return ptrayItem;
223
224 ptrayItem = ptrayItem->nextTrayItem;
225 }
226
227 return NULL; /* not found */
228}
229
230static PVOID Do_Shell_NotifyIconA(PVOID arg1, PVOID arg2,
231 PVOID arg3, PVOID arg4)
232{
233 DWORD dwMessage = (DWORD)arg1;
234 PNOTIFYICONDATAA pnid = (PNOTIFYICONDATAA)arg2;
235
236 BOOL flag = FALSE;
237 switch(dwMessage)
238 {
239 case NIM_ADD:
240 flag = SYSTRAY_Add(pnid);
241 break;
242 case NIM_MODIFY:
243 flag = SYSTRAY_Modify(pnid);
244 break;
245 case NIM_DELETE:
246 flag = SYSTRAY_Delete(pnid);
247 break;
248 }
249 return (PVOID)flag;
250}
251
252/*************************************************************************
253 * Shell_NotifyIconA [SHELL32.297][SHELL32.296]
254 */
255BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid )
256{
257 PVOID ret;
258 BOOL brc = RunOnAuxThreadAndWait(Do_Shell_NotifyIconA,
259 (PVOID)dwMessage, (PVOID)pnid,
260 NULL, NULL, &ret);
261 if (brc)
262 brc = (BOOL)ret;
263 return brc;
264}
265
266/*************************************************************************
267 * Shell_NotifyIconW [SHELL32.298]
268 */
269BOOL WINAPI Shell_NotifyIconW (DWORD dwMessage, PNOTIFYICONDATAW pnid )
270{
271 BOOL ret;
272
273 PNOTIFYICONDATAA p = HeapAlloc(GetProcessHeap(),0,sizeof(NOTIFYICONDATAA));
274 memcpy(p, pnid, sizeof(NOTIFYICONDATAA));
275 WideCharToMultiByte( CP_ACP, 0, pnid->szTip, -1, p->szTip, sizeof(p->szTip), NULL, NULL );
276 p->szTip[sizeof(p->szTip)-1] = 0;
277
278 ret = Shell_NotifyIconA(dwMessage, p );
279
280 HeapFree(GetProcessHeap(),0,p);
281 return ret;
282}
283
284
285#ifdef __WIN32OS2__
286
287BOOL DoWin32PostMessage(HWND w, ULONG m, WPARAM mp1, LPARAM mp2 )
288{
289 TRACE("DoWin32WinPostMsg: HWND 0x%08x MSG 0x%08x ID 0x%08x MMSG 0x%08x\n", w, m, mp1, mp2);
290 if ( w && m )
291 {
292 return PostMessageA( w, m, mp1, mp2 );
293 }
294 return FALSE;
295}
296
297#endif
Note: See TracBrowser for help on using the repository browser.