[PATCH 2/3] explorerframe: Implement taskbar_list_DeleteTab() for x11 driver.

Zhiyi Zhang zzhang at codeweavers.com
Fri Nov 12 01:00:12 CST 2021


Fix Excel 2007 and 2010 showing an extra taskbar icon when opening multiple documents in one instance.

Signed-off-by: Zhiyi Zhang <zzhang at 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 */
-- 
2.32.0




More information about the wine-devel mailing list