source: trunk/src/shell32/systray.c@ 21602

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

shell32: systray: Added support for the "TaskbarCreated" system notificaiton message that Windows broadcasts to all top-level windows when the taskbar (xcenter in case of OS/2) is (re)started. This allows applications supporting this message (including Java applications) recreate their taskbar icons.

File size: 8.3 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
193 *ptrayItem = next;
194
195 return TRUE;
196 }
197
198 ptrayItem = &((*ptrayItem)->nextTrayItem);
199 }
200
201 return FALSE; /* not found */
202}
203
204#ifndef __WIN32OS2__
205/*************************************************************************
206 *
207 */
208BOOL SYSTRAY_Init(void)
209{
210 return TRUE;
211}
212#endif
213
214/*************************************************************************
215 *
216 */
217SystrayItem *SYSTRAY_FindItem(ULONG uIdx)
218{
219 SystrayItem *ptrayItem = systray;
220
221 while (ptrayItem)
222 {
223 if (ptrayItem->uIdx == uIdx)
224 return ptrayItem;
225
226 ptrayItem = ptrayItem->nextTrayItem;
227 }
228
229 return NULL; /* not found */
230}
231
232/*************************************************************************
233 *
234 */
235void SYSTRAY_PruneAllItems(void)
236{
237 SystrayItem *ptrayItem = systray;
238
239 while (ptrayItem)
240 {
241 SystrayItem *next = ptrayItem->nextTrayItem;
242
243 TRACE("SYSTRAY_PruneAllItems %p: uIdx %u, hWnd 0x%08x, uID %d\n",
244 ptrayItem, ptrayItem->uIdx, ptrayItem->notifyIcon.hWnd,
245 ptrayItem->notifyIcon.uID);
246
247 SYSTRAY_ItemTerm(ptrayItem);
248
249 free(ptrayItem);
250
251 ptrayItem = next;
252 }
253
254 systray = NULL;
255}
256
257static PVOID Do_Shell_NotifyIconA(PVOID arg1, PVOID arg2,
258 PVOID arg3, PVOID arg4)
259{
260 DWORD dwMessage = (DWORD)arg1;
261 PNOTIFYICONDATAA pnid = (PNOTIFYICONDATAA)arg2;
262
263 BOOL flag = FALSE;
264 switch(dwMessage)
265 {
266 case NIM_ADD:
267 flag = SYSTRAY_Add(pnid);
268 break;
269 case NIM_MODIFY:
270 flag = SYSTRAY_Modify(pnid);
271 break;
272 case NIM_DELETE:
273 flag = SYSTRAY_Delete(pnid);
274 break;
275 }
276 return (PVOID)flag;
277}
278
279/*************************************************************************
280 * Shell_NotifyIconA [SHELL32.297][SHELL32.296]
281 */
282BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid )
283{
284 PVOID ret;
285 BOOL brc = RunOnAuxThreadAndWait(Do_Shell_NotifyIconA,
286 (PVOID)dwMessage, (PVOID)pnid,
287 NULL, NULL, &ret);
288 if (brc)
289 brc = (BOOL)ret;
290 return brc;
291}
292
293/*************************************************************************
294 * Shell_NotifyIconW [SHELL32.298]
295 */
296BOOL WINAPI Shell_NotifyIconW (DWORD dwMessage, PNOTIFYICONDATAW pnid )
297{
298 BOOL ret;
299
300 PNOTIFYICONDATAA p = HeapAlloc(GetProcessHeap(),0,sizeof(NOTIFYICONDATAA));
301 memcpy(p, pnid, sizeof(NOTIFYICONDATAA));
302 WideCharToMultiByte( CP_ACP, 0, pnid->szTip, -1, p->szTip, sizeof(p->szTip), NULL, NULL );
303 p->szTip[sizeof(p->szTip)-1] = 0;
304
305 ret = Shell_NotifyIconA(dwMessage, p );
306
307 HeapFree(GetProcessHeap(),0,p);
308 return ret;
309}
310
311
312#ifdef __WIN32OS2__
313
314BOOL DoWin32PostMessage(HWND w, ULONG m, WPARAM mp1, LPARAM mp2 )
315{
316 TRACE("DoWin32WinPostMsg: HWND 0x%08x MSG 0x%08x ID 0x%08x MMSG 0x%08x\n", w, m, mp1, mp2);
317 if ( w && m )
318 {
319 return PostMessageA( w, m, mp1, mp2 );
320 }
321 return FALSE;
322}
323
324#endif
Note: See TracBrowser for help on using the repository browser.