2 * SHAppBarMessage implementation
4 * Copyright 2008 Vincent Povirk for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * TODO: freedesktop _NET_WM_STRUT integration
22 * TODO: find when a fullscreen app is in the foreground and send FULLSCREENAPP
25 * TODO: detect changes in the screen size and send ABN_POSCHANGED ?
27 * TODO: multiple monitor support
30 #include "wine/unicode.h"
33 #include <wine/debug.h>
34 #include "explorer_private.h"
36 #include "wine/list.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(appbar
);
47 struct appbar_response
53 static HWND appbarmsg_window
= NULL
;
66 static struct list appbars
= LIST_INIT(appbars
);
68 static struct appbar_data
* get_appbar(HWND hwnd
)
70 struct appbar_data
* data
;
72 LIST_FOR_EACH_ENTRY(data
, &appbars
, struct appbar_data
, entry
)
74 if (data
->hwnd
== hwnd
)
81 /* send_poschanged: send ABN_POSCHANGED to every appbar except one */
82 static void send_poschanged(HWND hwnd
)
84 struct appbar_data
* data
;
85 LIST_FOR_EACH_ENTRY(data
, &appbars
, struct appbar_data
, entry
)
87 if (data
->hwnd
!= hwnd
)
89 PostMessageW(data
->hwnd
, data
->callback_msg
, ABN_POSCHANGED
, 0);
94 /* appbar_cliprect: cut out parts of the rectangle that interfere with existing appbars */
95 static void appbar_cliprect(PAPPBARDATA abd
)
97 struct appbar_data
* data
;
98 LIST_FOR_EACH_ENTRY(data
, &appbars
, struct appbar_data
, entry
)
100 if (data
->hwnd
== abd
->hWnd
)
102 /* we only care about appbars that were added before this one */
105 if (data
->space_reserved
)
107 /* move in the side that corresponds to the other appbar's edge */
111 abd
->rc
.bottom
= min(abd
->rc
.bottom
, data
->rc
.top
);
114 abd
->rc
.left
= max(abd
->rc
.left
, data
->rc
.right
);
117 abd
->rc
.right
= min(abd
->rc
.right
, data
->rc
.left
);
120 abd
->rc
.top
= max(abd
->rc
.top
, data
->rc
.bottom
);
127 static UINT_PTR
handle_appbarmessage(DWORD msg
, PAPPBARDATA abd
)
129 struct appbar_data
* data
;
134 if (get_appbar(abd
->hWnd
))
136 /* fail when adding an hwnd the second time */
140 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct appbar_data
));
143 WINE_ERR("out of memory\n");
146 data
->hwnd
= abd
->hWnd
;
147 data
->callback_msg
= abd
->uCallbackMessage
;
149 list_add_tail(&appbars
, &data
->entry
);
153 if ((data
= get_appbar(abd
->hWnd
)))
155 list_remove(&data
->entry
);
157 send_poschanged(abd
->hWnd
);
159 HeapFree(GetProcessHeap(), 0, data
);
162 WINE_WARN("removing hwnd %p not on the list\n", abd
->hWnd
);
165 if (abd
->uEdge
> ABE_BOTTOM
)
166 WINE_WARN("invalid edge %i for %p\n", abd
->uEdge
, abd
->hWnd
);
167 appbar_cliprect(abd
);
170 if (abd
->uEdge
> ABE_BOTTOM
)
172 WINE_WARN("invalid edge %i for %p\n", abd
->uEdge
, abd
->hWnd
);
175 if ((data
= get_appbar(abd
->hWnd
)))
177 /* calculate acceptable space */
178 appbar_cliprect(abd
);
180 if (!EqualRect(&abd
->rc
, &data
->rc
))
181 send_poschanged(abd
->hWnd
);
183 /* reserve that space for this appbar */
184 data
->edge
= abd
->uEdge
;
186 data
->space_reserved
= TRUE
;
190 WINE_WARN("app sent ABM_SETPOS message for %p without ABM_ADD\n", abd
->hWnd
);
194 WINE_FIXME("SHAppBarMessage(ABM_GETSTATE): stub\n");
195 return ABS_ALWAYSONTOP
| ABS_AUTOHIDE
;
196 case ABM_GETTASKBARPOS
:
197 WINE_FIXME("SHAppBarMessage(ABM_GETTASKBARPOS, hwnd=%p): stub\n", abd
->hWnd
);
200 WINE_FIXME("SHAppBarMessage(ABM_ACTIVATE, hwnd=%p, lparam=%lx): stub\n", abd
->hWnd
, abd
->lParam
);
202 case ABM_GETAUTOHIDEBAR
:
203 WINE_FIXME("SHAppBarMessage(ABM_GETAUTOHIDEBAR, hwnd=%p, edge=%x): stub\n", abd
->hWnd
, abd
->uEdge
);
205 case ABM_SETAUTOHIDEBAR
:
206 WINE_FIXME("SHAppBarMessage(ABM_SETAUTOHIDEBAR, hwnd=%p, edge=%x, lparam=%lx): stub\n", abd
->hWnd
, abd
->uEdge
, abd
->lParam
);
208 case ABM_WINDOWPOSCHANGED
:
209 WINE_FIXME("SHAppBarMessage(ABM_WINDOWPOSCHANGED, hwnd=%p): stub\n", abd
->hWnd
);
212 WINE_FIXME("SHAppBarMessage(%x) unimplemented\n", msg
);
217 LRESULT CALLBACK
appbar_wndproc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
224 struct appbar_cmd cmd
;
229 struct appbar_response
* response
;
231 cds
= (COPYDATASTRUCT
*)lparam
;
232 if (cds
->cbData
!= sizeof(struct appbar_cmd
))
234 CopyMemory(&cmd
, cds
->lpData
, cds
->cbData
);
236 result
= handle_appbarmessage(cds
->dwData
, &cmd
.abd
);
238 return_hproc
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, cmd
.return_process
);
239 if (return_hproc
== NULL
)
241 WINE_ERR("couldn't open calling process\n");
245 if (!DuplicateHandle(return_hproc
, cmd
.return_map
, GetCurrentProcess(), &return_map
, 0, FALSE
, DUPLICATE_SAME_ACCESS
))
247 WINE_ERR("couldn't duplicate handle\n");
248 CloseHandle(return_hproc
);
251 CloseHandle(return_hproc
);
253 return_view
= MapViewOfFile(return_map
, FILE_MAP_WRITE
, 0, 0, sizeof(struct appbar_response
));
257 response
= (struct appbar_response
*)return_view
;
258 response
->result
= result
;
259 response
->rc
= cmd
.abd
.rc
;
261 UnmapViewOfFile(return_view
);
264 WINE_ERR("couldn't map view of file\n");
266 CloseHandle(return_map
);
273 return DefWindowProcW(hwnd
, msg
, wparam
, lparam
);
276 void initialize_appbar(void)
279 static const WCHAR classname
[] = {'W','i','n','e','A','p','p','B','a','r',0};
281 /* register the appbar window class */
282 ZeroMemory(&class, sizeof(class));
283 class.cbSize
= sizeof(class);
284 class.lpfnWndProc
= appbar_wndproc
;
285 class.hInstance
= NULL
;
286 class.lpszClassName
= classname
;
288 if (!RegisterClassExW(&class))
290 WINE_ERR("Could not register appbar message window class\n");
294 appbarmsg_window
= CreateWindowW(classname
, classname
, 0, 0, 0, 0, 0, HWND_MESSAGE
, NULL
, NULL
, NULL
);
295 if (!appbarmsg_window
)
297 WINE_ERR("Could not create appbar message window\n");