Fix Excel 2007 and 2010 showing an extra taskbar icon when opening multiple documents in one instance.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/explorerframe/Makefile.in | 2 +- dlls/explorerframe/taskbarlist.c | 57 +++++++++++++++++++++++++- dlls/explorerframe/tests/taskbarlist.c | 8 ---- dlls/winex11.drv/window.c | 22 +++++++++- dlls/winex11.drv/winex11.drv.spec | 3 ++ dlls/winex11.drv/x11drv.h | 1 + 6 files changed, 80 insertions(+), 13 deletions(-)
diff --git a/dlls/explorerframe/Makefile.in b/dlls/explorerframe/Makefile.in index 18d054c7fad..9f683f9c229 100644 --- a/dlls/explorerframe/Makefile.in +++ b/dlls/explorerframe/Makefile.in @@ -1,5 +1,5 @@ MODULE = explorerframe.dll -IMPORTS = uuid ole32 comctl32 shell32 user32 +IMPORTS = uuid ole32 comctl32 shell32 user32 advapi32
C_SRCS = \ explorerframe_main.c \ diff --git a/dlls/explorerframe/taskbarlist.c b/dlls/explorerframe/taskbarlist.c index 6f24f359927..04dbb182cc2 100644 --- a/dlls/explorerframe/taskbarlist.c +++ b/dlls/explorerframe/taskbarlist.c @@ -25,6 +25,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(explorerframe);
+static void (CDECL *pwine_taskbar_delete_tab)(HWND); + struct taskbar_list { ITaskbarList4 ITaskbarList4_iface; @@ -87,6 +89,47 @@ static ULONG STDMETHODCALLTYPE taskbar_list_Release(ITaskbarList4 *iface)
/* ITaskbarList methods */
+static HMODULE load_graphics_driver(void) +{ + static const WCHAR key_pathW[] = L"System\CurrentControlSet\Control\Video\{"; + static const WCHAR displayW[] = L"}\0000"; + + HMODULE ret = 0; + HKEY hkey; + DWORD size; + WCHAR path[MAX_PATH]; + WCHAR key[ARRAY_SIZE(key_pathW) + ARRAY_SIZE(displayW) + 40]; + UINT guid_atom = HandleToULong(GetPropW(GetDesktopWindow(), L"__wine_display_device_guid")); + + if (!guid_atom) return 0; + memcpy(key, key_pathW, sizeof(key_pathW)); + if (!GlobalGetAtomNameW(guid_atom, key + lstrlenW(key), 40)) return 0; + lstrcatW(key, displayW); + if (RegOpenKeyW(HKEY_LOCAL_MACHINE, key, &hkey)) return 0; + size = sizeof(path); + if (!RegQueryValueExW(hkey, L"GraphicsDriver", NULL, NULL, (BYTE *)path, &size)) + ret = LoadLibraryW(path); + RegCloseKey(hkey); + TRACE("%s %p\n", debugstr_w(path), ret); + return ret; +} + +static BOOL WINAPI init_taskbar_driver_once(INIT_ONCE *once, void *param, void **context) +{ + HMODULE module; + + module = load_graphics_driver(); + pwine_taskbar_delete_tab = (void *)GetProcAddress(module, "wine_taskbar_delete_tab"); + return TRUE; +} + +static void init_taskbar_driver(void) +{ + static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; + + InitOnceExecuteOnce(&init_once, init_taskbar_driver_once, NULL, NULL); +} + static HRESULT STDMETHODCALLTYPE taskbar_list_HrInit(ITaskbarList4 *iface) { TRACE("iface %p\n", iface); @@ -103,9 +146,17 @@ static HRESULT STDMETHODCALLTYPE taskbar_list_AddTab(ITaskbarList4 *iface, HWND
static HRESULT STDMETHODCALLTYPE taskbar_list_DeleteTab(ITaskbarList4 *iface, HWND hwnd) { - FIXME("iface %p, hwnd %p stub!\n", iface, hwnd); + TRACE("iface %p, hwnd %p\n", iface, hwnd);
- return E_NOTIMPL; + if (!IsWindow(hwnd)) + return S_OK; + + if (pwine_taskbar_delete_tab) + pwine_taskbar_delete_tab(hwnd); + else + FIXME("wine_taskbar_delete_tab() is unimplemented for the current graphics driver.\n"); + + return S_OK; }
static HRESULT STDMETHODCALLTYPE taskbar_list_ActivateTab(ITaskbarList4 *iface, HWND hwnd) @@ -315,6 +366,8 @@ HRESULT TaskbarList_Constructor(IUnknown *outer, REFIID riid, void **taskbar_lis object->ITaskbarList4_iface.lpVtbl = &taskbar_list_vtbl; object->refcount = 1; EFRAME_LockModule(); + /* ITaskbarList methods are usable even before calling ITaskbarList::HrInit() */ + init_taskbar_driver();
TRACE("Created ITaskbarList4 %p\n", object);
diff --git a/dlls/explorerframe/tests/taskbarlist.c b/dlls/explorerframe/tests/taskbarlist.c index ed1bc44a6ac..9b2de996000 100644 --- a/dlls/explorerframe/tests/taskbarlist.c +++ b/dlls/explorerframe/tests/taskbarlist.c @@ -55,7 +55,6 @@ static void test_ITaskbarList(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ITaskbarList_DeleteTab(taskbarlist, hwnd); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
/* Call ITaskbarList::HrInit() */ @@ -88,7 +87,6 @@ static void test_ITaskbarList(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ITaskbarList_DeleteTab(taskbarlist, hwnd); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
/* Test ITaskbarList::SetActiveAlt() */ @@ -116,7 +114,6 @@ static void test_ITaskbarList(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ITaskbarList_DeleteTab(taskbarlist, hwnd); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
/* Test ITaskbarList::ActivateTab() */ @@ -144,21 +141,17 @@ static void test_ITaskbarList(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ITaskbarList_DeleteTab(taskbarlist, hwnd); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
/* Test ITaskbarList::DeleteTab() */ /* Check invalid parameters */ hr = ITaskbarList_DeleteTab(taskbarlist, NULL); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ITaskbarList_DeleteTab(taskbarlist, (HWND)0xdeadbeef); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ITaskbarList_DeleteTab(taskbarlist, hwnd); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
/* Normal ITaskbarList::DeleteTab() */ @@ -167,7 +160,6 @@ static void test_ITaskbarList(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ITaskbarList_DeleteTab(taskbarlist, hwnd); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
ref_count = ITaskbarList_Release(taskbarlist); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index bcb0b8044bc..a9015f8f5b7 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -994,9 +994,9 @@ void update_net_wm_states( struct x11drv_win_data *data ) ex_style = GetWindowLongW( data->hwnd, GWL_EXSTYLE ); if (ex_style & WS_EX_TOPMOST) new_state |= (1 << NET_WM_STATE_ABOVE); - if (ex_style & (WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE)) + if (data->deleted_from_taskbar || (ex_style & (WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE))) new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR) | (1 << NET_WM_STATE_SKIP_PAGER); - if (!(ex_style & WS_EX_APPWINDOW) && GetWindow( data->hwnd, GW_OWNER )) + else if (!(ex_style & WS_EX_APPWINDOW) && GetWindow( data->hwnd, GW_OWNER )) new_state |= (1 << NET_WM_STATE_SKIP_TASKBAR);
if (!data->mapped) /* set the _NET_WM_STATE atom directly */ @@ -2970,3 +2970,21 @@ void CDECL X11DRV_FlashWindowEx( PFLASHWINFO pfinfo ) } release_win_data( data ); } + +/* Taskbar functions */ + +/* Delete a window from taskbar */ +void CDECL X11DRV_delete_tab( HWND hwnd ) +{ + struct x11drv_win_data *data; + + TRACE("hwnd %p\n", hwnd); + + data = get_win_data( hwnd ); + if (!data) + return; + + data->deleted_from_taskbar = TRUE; + update_net_wm_states( data ); + release_win_data( data ); +} diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 6e0ccfab4b0..898c3334062 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -7,6 +7,9 @@ # Desktop @ cdecl wine_create_desktop(long long) X11DRV_create_desktop
+# Taskbar +@ cdecl wine_taskbar_delete_tab(ptr) X11DRV_delete_tab + # System tray @ cdecl wine_notify_icon(long ptr)
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 4b4ee8daaeb..23f4144b7a4 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -619,6 +619,7 @@ struct x11drv_win_data BOOL shaped : 1; /* is window using a custom region shape? */ BOOL layered : 1; /* is window layered and with valid attributes? */ BOOL use_alpha : 1; /* does window use an alpha channel? */ + BOOL deleted_from_taskbar : 1; /* does window should be deleted from taskbar */ int wm_state; /* current value of the WM_STATE property */ DWORD net_wm_state; /* bit mask of active x11drv_net_wm_state values */ Window embedder; /* window id of embedder */