diff options
author | Tobias Häußler <tobias.haeussler@gmx.de> | 2011-07-18 14:48:23 +0100 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2011-10-05 17:08:43 +0100 |
commit | d054d486d9022369b949d0c983a9406ec2194836 (patch) | |
tree | df8169d9ab6b96161d67c21785fa1d9e8f62677a /hw | |
parent | 2fe1f55edce755907ef10288d468d3cccb58a2cb (diff) |
Add correct taskbar grouping of X windows on Windows 7
I created a small patch for XWin that adds correct grouping of taskbar
icons when 'Always combine, hide labels' is set in the taskbar
properties. It uses the new taskbar APIs introduced in Windows 7 to set
an application id for each window. The id is based on the X11 class hints.
Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xwin/InitOutput.c | 8 | ||||
-rw-r--r-- | hw/xwin/Makefile.am | 3 | ||||
-rw-r--r-- | hw/xwin/taskbar.h | 72 | ||||
-rw-r--r-- | hw/xwin/winmultiwindowwm.c | 127 | ||||
-rw-r--r-- | hw/xwin/winmultiwindowwndproc.c | 3 | ||||
-rw-r--r-- | hw/xwin/winwindow.h | 8 |
6 files changed, 219 insertions, 2 deletions
diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index 80cfc3151..1695ab8eb 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -220,6 +220,9 @@ ddxGiveUp (enum ExitCode error) } #ifdef XWIN_MULTIWINDOW + /* Unload libraries for taskbar grouping */ + winTaskbarDestroy (); + /* Notify the worker threads we're exiting */ winDeinitMultiWindowWM (); #endif @@ -1029,6 +1032,11 @@ InitOutput (ScreenInfo *screenInfo, int argc, char *argv[]) /* Detect supported engines */ winDetectSupportedEngines (); +#ifdef XWIN_MULTIWINDOW + /* Load libraries for taskbar grouping */ + winTaskbarInit (); +#endif + /* Store the instance handle */ g_hInstance = GetModuleHandle (NULL); diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am index c24cf2a9c..105163677 100644 --- a/hw/xwin/Makefile.am +++ b/hw/xwin/Makefile.am @@ -26,6 +26,7 @@ SRCS_MULTIWINDOW = \ winmultiwindowwm.c \ winmultiwindowwndproc.c DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW +MULTIWINDOW_LIBS = -lshlwapi endif if XWIN_MULTIWINDOWEXTWM @@ -149,7 +150,7 @@ XWin_SOURCES = $(SRCS) INCLUDES = -I$(top_srcdir)/miext/rootless XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) -XWin_LDADD = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) +XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) XWin_LDFLAGS = -mwindows -static .rc.o: diff --git a/hw/xwin/taskbar.h b/hw/xwin/taskbar.h new file mode 100644 index 000000000..bfe301d12 --- /dev/null +++ b/hw/xwin/taskbar.h @@ -0,0 +1,72 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + */ + +#ifndef _TASKBAR_H +#define _TASKBAR_H + +#include <windows.h> + +typedef struct _tagpropertykey { + GUID fmtid; + DWORD pid; +} PROPERTYKEY; +#define REFPROPERTYKEY const PROPERTYKEY * +#define REFPROPVARIANT const PROPVARIANT * + +#ifdef INTERFACE +#undef INTERFACE +#endif + +#define INTERFACE IPropertyStore +DECLARE_INTERFACE_(IPropertyStore,IUnknown) { + STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + STDMETHOD(GetCount)(THIS_ DWORD) PURE; + STDMETHOD(GetAt)(THIS_ DWORD,PROPERTYKEY) PURE; + STDMETHOD(GetValue)(THIS_ REFPROPERTYKEY,PROPVARIANT) PURE; + STDMETHOD(SetValue)(THIS_ REFPROPERTYKEY,REFPROPVARIANT) PURE; + STDMETHOD(Commit)(THIS) PURE; +}; +#undef INTERFACE +typedef IPropertyStore *LPPROPERTYSTORE; + +DEFINE_GUID(IID_IPropertyStore,0x886d8eeb, 0x8cf2, 0x4446, 0x8d,0x02, 0xcd,0xba,0x1d,0xbd,0xcf,0x99); + +#ifdef INITGUID +#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) GUID_EXT const PROPERTYKEY DECLSPEC_SELECTANY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid } +#else +#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) GUID_EXT const PROPERTYKEY name +#endif + +DEFINE_PROPERTYKEY(PKEY_AppUserModel_ID, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 5); + +typedef HRESULT (__stdcall *SHGETPROPERTYSTOREFORWINDOWPROC)(HWND,REFIID,void**); +typedef HRESULT (__stdcall *PROPVARIANTCLEARPROC)(PROPVARIANT*); + +#endif diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 0121da7dc..69de2e417 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -62,6 +62,13 @@ #include "pixmapstr.h" #include "windowstr.h" +#include <shlwapi.h> + +#define INITGUID +#include "initguid.h" +#include "taskbar.h" +#undef INITGUID + #ifdef XWIN_MULTIWINDOWEXTWM #include <X11/extensions/windowswmstr.h> #else @@ -213,6 +220,10 @@ static pthread_t g_winMultiWindowXMsgProcThread; static Bool g_shutdown = FALSE; static Bool redirectError = FALSE; static Bool g_fAnotherWMRunning = FALSE; +static HMODULE g_hmodShell32Dll = NULL; +static HMODULE g_hmodOle32Dll = NULL; +static SHGETPROPERTYSTOREFORWINDOWPROC g_pSHGetPropertyStoreForWindow = NULL; +static PROPVARIANTCLEARPROC g_pPropVariantClear = NULL; /* * PushMessage - Push a message onto the queue @@ -1671,10 +1682,14 @@ winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle) XFree(normal_hint); } - /* Override hint settings from above with settings from config file */ + /* + Override hint settings from above with settings from config file and set + application id for grouping. + */ { XClassHint class_hint = {0,0}; char *window_name = 0; + char *application_id = 0; if (XGetClassHint(pDisplay, iWindow, &class_hint)) { @@ -1682,8 +1697,21 @@ winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle) style = winOverrideStyle(class_hint.res_name, class_hint.res_class, window_name); +#define APPLICATION_ID_FORMAT "%s.xwin.%s" +#define APPLICATION_ID_UNKNOWN "unknown" + if (class_hint.res_class) + { + asprintf (&application_id, APPLICATION_ID_FORMAT, XVENDORNAME, class_hint.res_class); + } + else + { + asprintf (&application_id, APPLICATION_ID_FORMAT, XVENDORNAME, APPLICATION_ID_UNKNOWN); + } + winSetAppID (hWnd, application_id); + if (class_hint.res_name) XFree(class_hint.res_name); if (class_hint.res_class) XFree(class_hint.res_class); + if (application_id) free(application_id); if (window_name) XFree(window_name); } else @@ -1789,3 +1817,100 @@ winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle) winUpdateRgnMultiWindow(pWin); } } + +void +winTaskbarInit (void) +{ + /* + Load libraries and get function pointers to SHGetPropertyStoreForWindow + and PropVariantClear for winSetAppID() + */ + + /* + SHGetPropertyStoreForWindow is only supported since Windows 7. On previous + versions the pointer will be NULL and taskbar grouping is not supported. + winSetAppID() will do nothing in this case. + */ + g_hmodShell32Dll = LoadLibrary ("shell32.dll"); + if (g_hmodShell32Dll == NULL) + { + ErrorF ("winTaskbarInit - Could not load shell32.dll\n"); + return; + } + + g_pSHGetPropertyStoreForWindow = (SHGETPROPERTYSTOREFORWINDOWPROC) GetProcAddress (g_hmodShell32Dll, "SHGetPropertyStoreForWindow"); + if (g_pSHGetPropertyStoreForWindow == NULL) + { + ErrorF ("winTaskbarInit - Could not get SHGetPropertyStoreForWindow address\n"); + return; + } + + /* + PropVariantClear is supported since NT4, but we have no propidl.h to + provide a prototype for it + */ + g_hmodOle32Dll = LoadLibrary ("ole32.dll"); + if (g_hmodOle32Dll == NULL) + { + ErrorF ("winTaskbarInit - Could not load ole32.dll\n"); + return; + } + + g_pPropVariantClear = (PROPVARIANTCLEARPROC) GetProcAddress (g_hmodOle32Dll, "PropVariantClear"); + if (g_pPropVariantClear == NULL) + { + ErrorF ("winTaskbarInit - Could not get g_pPropVariantClear address\n"); + return; + } +} + +void +winTaskbarDestroy (void) +{ + if (g_hmodOle32Dll != NULL) + { + FreeLibrary (g_hmodOle32Dll); + g_hmodOle32Dll = NULL; + g_pPropVariantClear = NULL; + } + if (g_hmodShell32Dll != NULL) + { + FreeLibrary (g_hmodShell32Dll); + g_hmodShell32Dll = NULL; + g_pSHGetPropertyStoreForWindow = NULL; + } +} + +void +winSetAppID (HWND hWnd, const char* AppID) +{ + PROPVARIANT pv; + IPropertyStore *pps = NULL; + HRESULT hr; + + if (g_pSHGetPropertyStoreForWindow == NULL || + g_pPropVariantClear == NULL) + { + return; + } + + winDebug ("winSetAppID - hwnd 0x%08x appid '%s'\n", hWnd, AppID); + + hr = g_pSHGetPropertyStoreForWindow (hWnd, &IID_IPropertyStore, (void**)&pps); + if(SUCCEEDED(hr) && pps) + { + memset(&pv, 0, sizeof(PROPVARIANT)); + if(AppID) + { + pv.vt = VT_LPWSTR; + hr = SHStrDupA(AppID, &pv.pwszVal); + } + + if(SUCCEEDED(hr)) + { + hr = pps->lpVtbl->SetValue(pps, &PKEY_AppUserModel_ID, &pv); + g_pPropVariantClear(&pv); + } + pps->lpVtbl->Release(pps); + } +} diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index f1fdf42f3..34f9d21a6 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -832,6 +832,9 @@ winTopLevelWindowProc (HWND hwnd, UINT message, break; case WM_CLOSE: + /* Remove property AppUserModelID */ + winSetAppID (hwnd, NULL); + /* Branch on if the window was killed in X already */ if (pWinPriv->fXKilled) { diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index 7783e190e..d1143cd2d 100644 --- a/hw/xwin/winwindow.h +++ b/hw/xwin/winwindow.h @@ -158,6 +158,14 @@ winDeinitMultiWindowWM (void); void winMinimizeWindow (Window id); +void +winTaskbarInit (void); + +void +winTaskbarDestroy (void); + +void +winSetAppID (HWND hWnd, const char* AppID); /* * winmultiwindowicons.c |