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

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

shell32: Implemented xsystray support (#16).

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