diff --git a/base/shell/explorer/CMakeLists.txt b/base/shell/explorer/CMakeLists.txt index b3f2982..1856249 100644 --- a/base/shell/explorer/CMakeLists.txt +++ b/base/shell/explorer/CMakeLists.txt @@ -5,6 +5,7 @@ add_definitions(-D_ATL_NO_EXCEPTIONS) include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl) list(APPEND SOURCE + appbar.cpp desktop.cpp explorer.cpp notifyiconscust.cpp diff --git a/base/shell/explorer/appbar.cpp b/base/shell/explorer/appbar.cpp new file mode 100644 index 0000000..f3a3e88 --- /dev/null +++ b/base/shell/explorer/appbar.cpp @@ -0,0 +1,268 @@ +/* + * SHAppBarMessage implementation + * + * Copyright 2008 Vincent Povirk for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: freedesktop _NET_WM_STRUT integration + * + * TODO: find when a fullscreen app is in the foreground and send FULLSCREENAPP + * notifications + * + * TODO: detect changes in the screen size and send ABN_POSCHANGED ? + * + * TODO: multiple monitor support + */ + +// +// Adapted from Wine appbar.c . +// + +#include "precomp.h" + +#include + +struct appbar_cmd +{ + DWORD dwMsg; + ULONG return_map; + DWORD return_process; + struct _AppBarData abd; +}; + +struct appbar_response +{ + ULONGLONG result; + struct _AppBarData abd; +}; + +struct appbar_data +{ + struct list entry; + HWND hwnd; + UINT callback_msg; + UINT edge; + RECT rc; + BOOL space_reserved; + /* BOOL autohide; */ +}; + +static struct list appbars = LIST_INIT(appbars); + +static struct appbar_data* get_appbar(HWND hwnd) +{ + struct appbar_data* data; + + LIST_FOR_EACH_ENTRY(data, &appbars, struct appbar_data, entry) + { + if (data->hwnd == hwnd) + return data; + } + + return NULL; +} + +/* send_poschanged: send ABN_POSCHANGED to every appbar except one */ +static void send_poschanged(HWND hwnd) +{ + struct appbar_data* data; + LIST_FOR_EACH_ENTRY(data, &appbars, struct appbar_data, entry) + { + if (data->hwnd != hwnd) + { + PostMessageW(data->hwnd, data->callback_msg, ABN_POSCHANGED, 0); + } + } +} + +/* appbar_cliprect: cut out parts of the rectangle that interfere with existing appbars */ +static void appbar_cliprect( HWND hwnd, RECT *rect ) +{ + struct appbar_data* data; + LIST_FOR_EACH_ENTRY(data, &appbars, struct appbar_data, entry) + { + if (data->hwnd == hwnd) + { + /* we only care about appbars that were added before this one */ + return; + } + if (data->space_reserved) + { + /* move in the side that corresponds to the other appbar's edge */ + switch (data->edge) + { + case ABE_BOTTOM: + rect->bottom = min(rect->bottom, data->rc.top); + break; + case ABE_LEFT: + rect->left = max(rect->left, data->rc.right); + break; + case ABE_RIGHT: + rect->right = min(rect->right, data->rc.left); + break; + case ABE_TOP: + rect->top = max(rect->top, data->rc.bottom); + break; + } + } + } +} + +static UINT_PTR handle_appbarmessage(DWORD msg, _AppBarData *abd) +{ + struct appbar_data* data; + HWND hwnd = abd->hWnd; + + switch (msg) + { + case ABM_NEW: + if (get_appbar(hwnd)) + { + /* fail when adding an hwnd the second time */ + return FALSE; + } + + data = (struct appbar_data*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct appbar_data)); + if (!data) + { + ERR("out of memory\n"); + return FALSE; + } + data->hwnd = hwnd; + data->callback_msg = abd->uCallbackMessage; + + list_add_tail(&appbars, &data->entry); + + return TRUE; + case ABM_REMOVE: + if ((data = get_appbar(hwnd))) + { + list_remove(&data->entry); + + send_poschanged(hwnd); + + HeapFree(GetProcessHeap(), 0, data); + } + else + WARN("removing hwnd %p not on the list\n", hwnd); + return TRUE; + case ABM_QUERYPOS: + if (abd->uEdge > ABE_BOTTOM) + WARN("invalid edge %i for %p\n", abd->uEdge, hwnd); + appbar_cliprect( hwnd, &abd->rc ); + return TRUE; + case ABM_SETPOS: + if (abd->uEdge > ABE_BOTTOM) + { + WARN("invalid edge %i for %p\n", abd->uEdge, hwnd); + return TRUE; + } + if ((data = get_appbar(hwnd))) + { + /* calculate acceptable space */ + appbar_cliprect( hwnd, &abd->rc ); + + if (!EqualRect(&abd->rc, &data->rc)) + send_poschanged(hwnd); + + /* reserve that space for this appbar */ + data->edge = abd->uEdge; + data->rc = abd->rc; + data->space_reserved = TRUE; + } + else + { + WARN("app sent ABM_SETPOS message for %p without ABM_ADD\n", hwnd); + } + return TRUE; + case ABM_GETSTATE: + FIXME("SHAppBarMessage(ABM_GETSTATE): stub\n"); + return ABS_ALWAYSONTOP | ABS_AUTOHIDE; + case ABM_GETTASKBARPOS: + FIXME("SHAppBarMessage(ABM_GETTASKBARPOS, hwnd=%p): stub\n", hwnd); + /* Report the taskbar is at the bottom of the screen. */ + abd->rc.left = 0; + abd->rc.right = GetSystemMetrics(SM_CXSCREEN); + abd->rc.bottom = GetSystemMetrics(SM_CYSCREEN); + abd->rc.top = abd->rc.bottom-1; + abd->uEdge = ABE_BOTTOM; + return TRUE; + case ABM_ACTIVATE: + return TRUE; + case ABM_GETAUTOHIDEBAR: + FIXME("SHAppBarMessage(ABM_GETAUTOHIDEBAR, hwnd=%p, edge=%x): stub\n", hwnd, abd->uEdge); + return 0; + case ABM_SETAUTOHIDEBAR: + FIXME("SHAppBarMessage(ABM_SETAUTOHIDEBAR, hwnd=%p, edge=%x, lparam=%s): stub\n", + hwnd, abd->uEdge, wine_dbgstr_longlong(abd->lParam)); + return TRUE; + case ABM_WINDOWPOSCHANGED: + return TRUE; + default: + FIXME("SHAppBarMessage(%x) unimplemented\n", msg); + return FALSE; + } +} + +LRESULT appbar_message ( COPYDATASTRUCT* cds ) +{ + struct appbar_cmd cmd; + UINT_PTR result; + HANDLE return_hproc; + HANDLE return_map; + LPVOID return_view; + struct appbar_response* response; + + if (cds->cbData != sizeof(struct appbar_cmd)) + return TRUE; + + RtlCopyMemory(&cmd, cds->lpData, cds->cbData); + + result = handle_appbarmessage(cmd.dwMsg, &cmd.abd); + + return_hproc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, cmd.return_process); + if (return_hproc == NULL) + { + ERR("couldn't open calling process\n"); + return TRUE; + } + + if (!DuplicateHandle(return_hproc, UlongToHandle(cmd.return_map), GetCurrentProcess(), &return_map, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + ERR("couldn't duplicate handle\n"); + CloseHandle(return_hproc); + return TRUE; + } + CloseHandle(return_hproc); + + return_view = MapViewOfFile(return_map, FILE_MAP_WRITE, 0, 0, sizeof(struct appbar_response)); + + if (return_view) + { + response = (struct appbar_response*)return_view; + response->result = result; + response->abd = cmd.abd; + + UnmapViewOfFile(return_view); + } + else + { + ERR("couldn't map view of file\n"); + } + + CloseHandle(return_map); + return TRUE; +} diff --git a/base/shell/explorer/syspager.cpp b/base/shell/explorer/syspager.cpp index 8d4f914..8d507c5 100644 --- a/base/shell/explorer/syspager.cpp +++ b/base/shell/explorer/syspager.cpp @@ -1531,17 +1531,27 @@ LRESULT CSysPagerWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa return 0; } +LRESULT appbar_message( COPYDATASTRUCT* cds ); + LRESULT CSysPagerWnd::OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { PCOPYDATASTRUCT cpData = (PCOPYDATASTRUCT)lParam; - if (cpData->dwData == 1) + if (cpData->dwData == TABDMC_NOTIFY) { /* A taskbar NotifyIcon notification */ PTRAYNOTIFYDATAW pData = (PTRAYNOTIFYDATAW)cpData->lpData; if (pData->dwSignature == NI_NOTIFY_SIG) return NotifyIcon(pData->dwMessage, &pData->nid); } - // TODO: Handle other types of taskbar notifications + else if (cpData->dwData == TABDMC_APPBAR) + { + FIXME("Taskbar Tray Application Bar\n"); + return appbar_message( cpData ); + } + else if (cpData->dwData == TABDMC_LOADINPROC) + { + FIXME("Taskbar Load In Proc\n"); + } return FALSE; } diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt index ea2fe80..7913127 100644 --- a/dll/win32/shell32/CMakeLists.txt +++ b/dll/win32/shell32/CMakeLists.txt @@ -93,6 +93,7 @@ add_rc_deps(shell32.rc ${shell32_rc_deps}) add_library(shell32 MODULE ${SOURCE} + wine/appbar.c wine/brsfolder.c wine/changenotify.c wine/classes.c diff --git a/dll/win32/shell32/systray.cpp b/dll/win32/shell32/systray.cpp index a64d689..0d4f214 100644 --- a/dll/win32/shell32/systray.cpp +++ b/dll/win32/shell32/systray.cpp @@ -197,7 +197,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid) } /* Send the data */ - data.dwData = 1; + data.dwData = TABDMC_NOTIFY; data.cbData = sizeof(tnid); data.lpData = &tnid; if (SendMessageW(hShellTrayWnd, WM_COPYDATA, (WPARAM)pnid->hWnd, (LPARAM)&data)) diff --git a/dll/win32/shell32/wine/appbar.c b/dll/win32/shell32/wine/appbar.c new file mode 100644 index 0000000..78ca967 --- /dev/null +++ b/dll/win32/shell32/wine/appbar.c @@ -0,0 +1,167 @@ +/* + * SHAppBarMessage implementation + * + * Copyright 2008 Vincent Povirk for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// +// Adapted from Wine appbar.c . +// + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "undocshell.h" + +#include +#include + +WINE_DEFAULT_DEBUG_CHANNEL(appbar); + +struct appbar_cmd +{ + DWORD dwMsg; + ULONG return_map; + DWORD return_process; + struct _AppBarData abd; +}; + +struct appbar_response +{ + ULONGLONG result; + struct _AppBarData abd; +}; + +/************************************************************************* + * SHAppBarMessage [SHELL32.@] + */ +UINT_PTR WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data) +{ + struct appbar_cmd command; + struct appbar_response* response; + HANDLE return_map; + LPVOID return_view; + HWND appbarmsg_window; + COPYDATASTRUCT cds; + + UINT_PTR ret = 0; + + TRACE("msg=%d, data={cb=%d, hwnd=%p}\n", msg, data->cbSize, data->hWnd); + + /* These members are message dependent */ + switch(msg) + { + case ABM_NEW: + TRACE("callback: %x\n", data->uCallbackMessage); + break; + + case ABM_GETAUTOHIDEBAR: + TRACE("edge: %d\n", data->uEdge); + break; + + case ABM_QUERYPOS: + case ABM_SETPOS: + TRACE("edge: %d, rc: %s\n", data->uEdge, wine_dbgstr_rect(&data->rc)); + break; + + case ABM_GETTASKBARPOS: + TRACE("rc: %s\n", wine_dbgstr_rect(&data->rc)); + break; + + case ABM_SETAUTOHIDEBAR: + TRACE("edge: %d, lParam: %lx\n", data->uEdge, data->lParam); + break; + + default: + FIXME("unknown msg: %d\n", msg); + break; + } + + if (data->cbSize < sizeof(APPBARDATA)) + { + WARN("data at %p is too small\n", data); + return FALSE; + } + + command.dwMsg = msg; + command.abd.hWnd = data->hWnd; + command.abd.uCallbackMessage = data->uCallbackMessage; + command.abd.uEdge = data->uEdge; + command.abd.rc = data->rc; + command.abd.lParam = data->lParam; + + return_map = CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, sizeof(struct appbar_response), NULL); + if (return_map == NULL) + { + ERR("couldn't create file mapping\n"); + return 0; + } + command.return_map = HandleToUlong( return_map ); + + command.return_process = GetCurrentProcessId(); + + appbarmsg_window = FindWindowW(L"Shell_TrayWnd", NULL); + if (appbarmsg_window == NULL) + { + ERR("couldn't find appbar window\n"); + CloseHandle(return_map); + return 0; + } + + cds.dwData = TABDMC_APPBAR; + cds.cbData = sizeof(command); + cds.lpData = &command; + + SendMessageW(appbarmsg_window, WM_COPYDATA, (WPARAM)data->hWnd, (LPARAM)&cds); + + return_view = MapViewOfFile(return_map, FILE_MAP_READ, 0, 0, sizeof(struct appbar_response)); + if (return_view == NULL) + { + ERR("MapViewOfFile failed\n"); + CloseHandle(return_map); + return 0; + } + + response = return_view; + + ret = response->result; + if (ret) + { + data->hWnd = response->abd.hWnd; + data->uCallbackMessage = response->abd.uCallbackMessage; + data->uEdge = response->abd.uEdge; + data->rc = response->abd.rc; + data->lParam = response->abd.lParam; + } + UnmapViewOfFile(return_view); + + CloseHandle(return_map); + + return ret; +} diff --git a/dll/win32/shell32/wine/shell32_main.c b/dll/win32/shell32/wine/shell32_main.c index 4ae3ea0..e3b39fa 100644 --- a/dll/win32/shell32/wine/shell32_main.c +++ b/dll/win32/shell32/wine/shell32_main.c @@ -971,7 +971,7 @@ typedef struct /************************************************************************* * SHAppBarMessage [SHELL32.@] */ -UINT_PTR WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data) +UINT_PTR WINAPI OLD_SHAppBarMessage(DWORD msg, PAPPBARDATA data) { int width=data->rc.right - data->rc.left; int height=data->rc.bottom - data->rc.top; diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h index 570c69d..e9ea0d3 100644 --- a/sdk/include/reactos/undocshell.h +++ b/sdk/include/reactos/undocshell.h @@ -676,6 +676,11 @@ BOOL WINAPI GUIDFromStringW( #define TRAYCMD_SEARCH_FILES 41093 #define TRAYCMD_SEARCH_COMPUTERS 41094 +// Explorer Tray Application Bar Data Message Commands +#define TABDMC_APPBAR 0 +#define TABDMC_NOTIFY 1 +#define TABDMC_LOADINPROC 2 + void WINAPI ShellDDEInit(BOOL bInit); DWORD WINAPI WinList_Init(void);