diff -uNr src/xserver-cygwin-1.10.1-1/hw/xwin/InitOutput.c src/xserver-cygwin-1.10.1-1/hw/xwin/InitOutput.c --- src/xserver-cygwin-1.10.1-1/hw/xwin/InitOutput.c 2011-04-22 18:03:27.000000000 +0200 +++ src/xserver-cygwin-1.10.1-1/hw/xwin/InitOutput.c 2011-07-01 20:11:55.028448200 +0200 @@ -219,6 +219,9 @@ } #ifdef XWIN_MULTIWINDOW + /* Unload libraries for taskbar grouping */ + winTaskbarDestroy (); + /* Notify the worker threads we're exiting */ winDeinitMultiWindowWM (); #endif @@ -984,6 +987,11 @@ /* Detect supported engines */ winDetectSupportedEngines (); +#ifdef XWIN_MULTIWINDOW + /* Load libraries for taskbar grouping */ + winTaskbarInit (); +#endif + /* Store the instance handle */ g_hInstance = GetModuleHandle (NULL); diff -uNr src/xserver-cygwin-1.10.1-1/hw/xwin/Makefile.am src/xserver-cygwin-1.10.1-1/hw/xwin/Makefile.am --- src/xserver-cygwin-1.10.1-1/hw/xwin/Makefile.am 2011-04-22 18:03:27.000000000 +0200 +++ src/xserver-cygwin-1.10.1-1/hw/xwin/Makefile.am 2011-07-01 21:27:18.840399400 +0200 @@ -26,6 +26,7 @@ winmultiwindowwm.c \ winmultiwindowwndproc.c DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW +MULTIWINDOW_LIBS = -lshlwapi endif if XWIN_MULTIWINDOWEXTWM @@ -149,7 +150,7 @@ 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 -uNr src/xserver-cygwin-1.10.1-1/hw/xwin/taskbar.h src/xserver-cygwin-1.10.1-1/hw/xwin/taskbar.h --- src/xserver-cygwin-1.10.1-1/hw/xwin/taskbar.h 1970-01-01 01:00:00.000000000 +0100 +++ src/xserver-cygwin-1.10.1-1/hw/xwin/taskbar.h 2011-07-01 21:10:40.698151400 +0200 @@ -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 + +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 -uNr src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwm.c src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwm.c --- src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwm.c 2011-04-22 18:03:27.000000000 +0200 +++ src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwm.c 2011-07-01 22:05:50.932997900 +0200 @@ -62,6 +62,13 @@ #include "pixmapstr.h" #include "windowstr.h" +#include + +#define INITGUID +#include "initguid.h" +#include "taskbar.h" +#undef INITGUID + #ifdef XWIN_MULTIWINDOWEXTWM #include #else @@ -213,6 +220,10 @@ 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,19 +1682,36 @@ 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)) { XFetchName(pDisplay, iWindow, &window_name); 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 @@ -1691,7 +1719,7 @@ style = STYLE_NONE; } } - + if (style & STYLE_TOPMOST) *zstyle = HWND_TOPMOST; else if (style & STYLE_MAXIMIZE) maxmin = (hint & ~HINT_MIN) | HINT_MAX; else if (style & STYLE_MINIMIZE) maxmin = (hint & ~HINT_MAX) | HINT_MIN; @@ -1789,3 +1817,97 @@ 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; + } + + + 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; + } + + 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 -uNr src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwndproc.c src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwndproc.c --- src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwndproc.c 2011-04-22 18:03:27.000000000 +0200 +++ src/xserver-cygwin-1.10.1-1/hw/xwin/winmultiwindowwndproc.c 2011-07-01 19:23:06.977633000 +0200 @@ -832,6 +832,9 @@ break; case WM_CLOSE: + /* Remove property AppUserModelID */ + winSetAppID (hwnd, NULL); + /* Branch on if the window was killed in X already */ if (pWinPriv->fXKilled) { diff -uNr src/xserver-cygwin-1.10.1-1/hw/xwin/winwindow.h src/xserver-cygwin-1.10.1-1/hw/xwin/winwindow.h --- src/xserver-cygwin-1.10.1-1/hw/xwin/winwindow.h 2011-04-22 18:03:27.000000000 +0200 +++ src/xserver-cygwin-1.10.1-1/hw/xwin/winwindow.h 2011-07-01 20:15:07.290362400 +0200 @@ -159,6 +159,14 @@ void winMinimizeWindow (Window id); +void +winTaskbarInit (void); + +void +winTaskbarDestroy (void); + +void +winSetAppID (HWND hWnd, const char* AppID); /* * winmultiwindowicons.c