[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