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 |
|
---|
33 | DEFAULT_DEBUG_CHANNEL(shell);
|
---|
34 |
|
---|
35 |
|
---|
36 | struct _SystrayItem {
|
---|
37 | HWND hWnd;
|
---|
38 | HWND hWndToolTip;
|
---|
39 | NOTIFYICONDATAA notifyIcon;
|
---|
40 | UINT uIdx;
|
---|
41 | struct _SystrayItem *nextTrayItem;
|
---|
42 | };
|
---|
43 |
|
---|
44 | static SystrayItem *systray = NULL;
|
---|
45 |
|
---|
46 | BOOL (*SYSTRAY_ItemInit)(SystrayItem *ptrayItem) = 0;
|
---|
47 | void (*SYSTRAY_ItemTerm)(SystrayItem *ptrayItem) = 0;
|
---|
48 | void (*SYSTRAY_ItemUpdate)(SystrayItem *ptrayItem, ULONG uFlags) = 0;
|
---|
49 |
|
---|
50 | static 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 |
|
---|
57 | static 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 |
|
---|
144 | static 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 |
|
---|
175 | static 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 | */
|
---|
206 | BOOL SYSTRAY_Init(void)
|
---|
207 | {
|
---|
208 | return TRUE;
|
---|
209 | }
|
---|
210 | #endif
|
---|
211 |
|
---|
212 | /*************************************************************************
|
---|
213 | *
|
---|
214 | */
|
---|
215 | SystrayItem *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 |
|
---|
230 | static 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 | */
|
---|
255 | BOOL 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 | */
|
---|
269 | BOOL 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 |
|
---|
287 | BOOL 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
|
---|