diff options
Diffstat (limited to 'xorg-server/hw/xwin')
26 files changed, 507 insertions, 104 deletions
diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c index 4bcd3a006..78ff74fc5 100644 --- a/xorg-server/hw/xwin/InitOutput.c +++ b/xorg-server/hw/xwin/InitOutput.c @@ -204,6 +204,9 @@ ddxGiveUp(enum ExitCode error) } #ifdef XWIN_MULTIWINDOW + /* Unload libraries for taskbar grouping */ + winPropertyStoreDestroy(); + /* Notify the worker threads we're exiting */ winDeinitMultiWindowWM(); #endif @@ -804,7 +807,7 @@ winUseMsg(void) ErrorF("-resize=none|scrollbars|randr" "\tIn windowed mode, [don't] allow resizing of the window. 'scrollbars'\n" "\tmode gives the window scrollbars as needed, 'randr' mode uses the RANR\n" - "\textension to resize the X screen.\n"); + "\textension to resize the X screen. 'randr' is the default.\n"); ErrorF("-rootless\n" "\tRun the server in rootless mode.\n"); @@ -837,7 +840,7 @@ winUseMsg(void) #ifdef XWIN_GLX_WINDOWS ErrorF("-[no]wgl\n" - "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n"); + "\tEnable the GLX extension to use the native Windows WGL interface for hardware-accelerated OpenGL\n"); #endif ErrorF("-[no]winkill\n" "\tAlt+F4 exits the X Server.\n"); @@ -951,6 +954,10 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) /* Detect supported engines */ winDetectSupportedEngines(); +#ifdef XWIN_MULTIWINDOW + /* Load libraries for taskbar grouping */ + winPropertyStoreInit(); +#endif /* Store the instance handle */ g_hInstance = GetModuleHandle(NULL); diff --git a/xorg-server/hw/xwin/Makefile.am b/xorg-server/hw/xwin/Makefile.am index 3fcaf9d0b..93ce57038 100644 --- a/xorg-server/hw/xwin/Makefile.am +++ b/xorg-server/hw/xwin/Makefile.am @@ -23,8 +23,11 @@ SRCS_MULTIWINDOW = \ winmultiwindowshape.c \ winmultiwindowwindow.c \ winmultiwindowwm.c \ - winmultiwindowwndproc.c + winmultiwindowwndproc.c \ + propertystore.h \ + winSetAppUserModelID.c DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW +MULTIWINDOW_LIBS = -lshlwapi -lole32 endif if XWIN_MULTIWINDOWEXTWM @@ -99,6 +102,7 @@ SRCS = InitInput.c \ winshaddd.c \ winshadddnl.c \ winshadgdi.c \ + wintaskbar.c \ wintrayicon.c \ winvalargs.c \ winwakeup.c \ @@ -150,7 +154,7 @@ INCLUDES = -I$(top_srcdir)/miext/rootless XWIN_SYS_LIBS += -ldxguid 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/xorg-server/hw/xwin/ddraw.h b/xorg-server/hw/xwin/ddraw.h index 9463049c8..1871d9551 100644 --- a/xorg-server/hw/xwin/ddraw.h +++ b/xorg-server/hw/xwin/ddraw.h @@ -1,3 +1,7 @@ +#ifdef __MINGW64_VERSION_MAJOR +#include_next <ddraw.h> +#define __XWIN_DDRAW_H +#endif #ifndef __XWIN_DDRAW_H #define __XWIN_DDRAW_H diff --git a/xorg-server/hw/xwin/glx/indirect.c b/xorg-server/hw/xwin/glx/indirect.c index c0069a20f..22c5abc14 100644 --- a/xorg-server/hw/xwin/glx/indirect.c +++ b/xorg-server/hw/xwin/glx/indirect.c @@ -86,6 +86,7 @@ #include <winpriv.h> #include <wgl_ext_api.h> +#include <winglobals.h> #define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1])) @@ -341,6 +342,10 @@ swap_method_name(int mthd) static void fbConfigsDump(unsigned int n, __GLXconfig * c) { + LogMessage(X_INFO, "%d fbConfigs\n", n); + + if (g_iLogVerbose < 3) + return; ErrorF("%d fbConfigs\n", n); ErrorF ("pxf vis fb render Ste aux accum MS drawable Group/\n"); @@ -595,11 +600,14 @@ glxWinScreenProbe(ScreenPtr pScreen) gl_renderer = (const char *) glGetStringWrapperNonstatic(GL_RENDERER); ErrorF("GL_RENDERER: %s\n", gl_renderer); gl_extensions = (const char *) glGetStringWrapperNonstatic(GL_EXTENSIONS); - glxLogExtensions("GL_EXTENSIONS: ", gl_extensions); wgl_extensions = wglGetExtensionsStringARBWrapper(hdc); if (!wgl_extensions) wgl_extensions = ""; - glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions); + + if (g_iLogVerbose >= 3) { + glxLogExtensions("GL_EXTENSIONS: ", gl_extensions); + glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions); + } if (strcasecmp(gl_renderer, "GDI Generic") == 0) { free(screen); @@ -1835,8 +1843,8 @@ glxWinCreateConfigs(HDC hdc, glxWinScreen * screen) // get the number of pixelformats numConfigs = DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL); - GLWIN_DEBUG_MSG("DescribePixelFormat says %d possible pixel formats", - numConfigs); + LogMessage(X_INFO, "%d pixel formats reported by DescribePixelFormat\n", + numConfigs); /* alloc */ result = malloc(sizeof(GLXWinConfig) * numConfigs); @@ -2083,9 +2091,9 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) return; } - GLWIN_DEBUG_MSG - ("wglGetPixelFormatAttribivARB says %d possible pixel formats", - numConfigs); + LogMessage(X_INFO, + "%d pixel formats reported by wglGetPixelFormatAttribivARB\n", + numConfigs); /* alloc */ result = malloc(sizeof(GLXWinConfig) * numConfigs); diff --git a/xorg-server/hw/xwin/man/XWin.man b/xorg-server/hw/xwin/man/XWin.man index dbadad6f5..18ee667d4 100644 --- a/xorg-server/hw/xwin/man/XWin.man +++ b/xorg-server/hw/xwin/man/XWin.man @@ -121,14 +121,16 @@ Alternative name for \fB\-resize=scrollbars\fP. .SH OPTIONS CONTROLLING RESIZE BEHAVIOUR .TP 8 .B \-resize[=none|scrollbars|randr] -Select the resize mode of an X screen. +Select the resize mode of an X screen. The default is randr. .RS .IP \fB\-resize=none\fP 8 -(default). The screen is not resizable. +The screen is not resizable. In windowed mode, if the window has decorations, a fixed frame is used. +Alternative name is \fB\-noresize\fP. + .IP \fB\-resize=scrollbars\fP 8 The screen window is resizeable, but the screen is not resizable. @@ -159,8 +161,8 @@ of the X screen using the RANDR extension is not permitted. The maximum dimensions of the screen are the dimensions of the \fIWindows\fP virtual desktop. -.IP \fB\--resize\fP 8 -on its own is equivalent to \fB\--resize=randr\fP +.IP \fB\-resize\fP 8 +on its own is equivalent to \fB\-resize=randr\fP .RE .SH OPTIONS CONTROLLING WINDOWS INTEGRATION @@ -211,7 +213,7 @@ is disabled by default. .TP 8 .B \-[no]wgl Enable [disable] the GLX extension to use the native Windows WGL interface -for hardware accelerated OpenGL (AIGLX). (Experimental) +for hardware accelerated OpenGL (AIGLX). The default is enabled. .TP 8 .B \-[no]winkill Enable or disable the \fIAlt-F4\fP key combination as a signal to exit the diff --git a/xorg-server/hw/xwin/propertystore.h b/xorg-server/hw/xwin/propertystore.h new file mode 100644 index 000000000..6afc6c954 --- /dev/null +++ b/xorg-server/hw/xwin/propertystore.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011 Tobias Häußler + * + * 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 (including the next + * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifndef PROPERTYSTORE_H +#define PROPERTYSTORE_H + +#include <windows.h> + +#ifdef __MINGW64_VERSION_MAJOR +/* If we are using headers from mingw-w64 project, it provides the PSDK headers this needs ... */ +#include <propkey.h> +#include <propsys.h> +#else /* !__MINGW64_VERSION_MAJOR */ +/* ... otherwise, we need to define all this stuff ourselves */ + +typedef struct _tagpropertykey { + GUID fmtid; + DWORD pid; +} PROPERTYKEY; + +#define REFPROPERTYKEY const PROPERTYKEY * +#define REFPROPVARIANT const PROPVARIANT * + +WINOLEAPI PropVariantClear(PROPVARIANT *pvar); + +#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); + +#endif /* !__MINGW64_VERSION_MAJOR */ + +typedef HRESULT(__stdcall * SHGETPROPERTYSTOREFORWINDOWPROC) (HWND, REFIID, + void **); + +#endif diff --git a/xorg-server/hw/xwin/win.h b/xorg-server/hw/xwin/win.h index 7b34e84d9..fa774bc00 100644 --- a/xorg-server/hw/xwin/win.h +++ b/xorg-server/hw/xwin/win.h @@ -133,6 +133,8 @@ #define WIN_MAX_KEYS_PER_KEY 4 +#define NONAMELESSUNION + #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> @@ -248,9 +250,6 @@ if (++PROFPT##point % thresh == 0)\ ErrorF (#point ": PROFILEPOINT hit %u times\n", PROFPT##point);\ } -/* We use xor this macro for detecting toggle key state changes */ -#define WIN_XOR(a,b) ((!(a) && (b)) || ((a) && !(b))) - #define DEFINE_ATOM_HELPER(func,atom_name) \ static Atom func (void) { \ static int generation; \ diff --git a/xorg-server/hw/xwin/winSetAppUserModelID.c b/xorg-server/hw/xwin/winSetAppUserModelID.c new file mode 100644 index 000000000..ce9da5e7d --- /dev/null +++ b/xorg-server/hw/xwin/winSetAppUserModelID.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2011 Tobias Häußler + * + * 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 (including the next + * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include <X11/Xlib.h> +#include <X11/Xproto.h> +#include <X11/Xwindows.h> +#include "winwindow.h" +#include "os.h" +#include "winmsg.h" + +#include <shlwapi.h> + +#define INITGUID +#include "initguid.h" +#include "propertystore.h" +#undef INITGUID + +static HMODULE g_hmodShell32Dll = NULL; +static SHGETPROPERTYSTOREFORWINDOWPROC g_pSHGetPropertyStoreForWindow = NULL; + +void +winPropertyStoreInit(void) +{ + /* + Load library and get function pointer to SHGetPropertyStoreForWindow() + + SHGetPropertyStoreForWindow is only supported since Windows 7. On previous + versions the pointer will be NULL and taskbar grouping is not supported. + winSetAppUserModelID() will do nothing in this case. + */ + g_hmodShell32Dll = LoadLibrary("shell32.dll"); + if (g_hmodShell32Dll == NULL) { + ErrorF("winPropertyStoreInit - Could not load shell32.dll\n"); + return; + } + + g_pSHGetPropertyStoreForWindow = + (SHGETPROPERTYSTOREFORWINDOWPROC) GetProcAddress(g_hmodShell32Dll, + "SHGetPropertyStoreForWindow"); + if (g_pSHGetPropertyStoreForWindow == NULL) { + ErrorF + ("winPropertyStoreInit - Could not get SHGetPropertyStoreForWindow address\n"); + return; + } +} + +void +winPropertyStoreDestroy(void) +{ + if (g_hmodShell32Dll != NULL) { + FreeLibrary(g_hmodShell32Dll); + g_hmodShell32Dll = NULL; + g_pSHGetPropertyStoreForWindow = NULL; + } +} + +void +winSetAppUserModelID(HWND hWnd, const char *AppID) +{ + PROPVARIANT pv; + IPropertyStore *pps = NULL; + HRESULT hr; + + if (g_pSHGetPropertyStoreForWindow == NULL) { + return; + } + + winDebug("winSetAppUserMOdelID - 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)) { + pps->lpVtbl->SetValue(pps, &PKEY_AppUserModel_ID, &pv); + PropVariantClear(&pv); + } + pps->lpVtbl->Release(pps); + } +} diff --git a/xorg-server/hw/xwin/winblock.c b/xorg-server/hw/xwin/winblock.c index 480e3bd48..a4ae8669f 100644 --- a/xorg-server/hw/xwin/winblock.c +++ b/xorg-server/hw/xwin/winblock.c @@ -86,4 +86,13 @@ winBlockHandler(ScreenPtr pScreen, DispatchMessage(&msg); } } + + /* + At least one X client has asked to suspend the screensaver, so + reset Windows' display idle timer + */ +#ifdef SCREENSAVER + if (screenSaverSuspended) + SetThreadExecutionState(ES_DISPLAY_REQUIRED); +#endif } diff --git a/xorg-server/hw/xwin/winclipboardthread.c b/xorg-server/hw/xwin/winclipboardthread.c index 891278279..c8508a9b8 100644 --- a/xorg-server/hw/xwin/winclipboardthread.c +++ b/xorg-server/hw/xwin/winclipboardthread.c @@ -36,6 +36,7 @@ #define HAS_WINSOCK 1 #endif #include <sys/types.h> +#include <signal.h> #include "winclipboard.h" #ifdef __CYGWIN__ #include <errno.h> @@ -431,7 +432,7 @@ winClipboardProc(void *pvNotUsed) else { ErrorF("winClipboardProc - Clipboard disabled - Exit from server \n"); /* clipboard thread has exited, stop server as well */ - kill(getpid(), SIGTERM); + raise(SIGTERM); } return NULL; diff --git a/xorg-server/hw/xwin/winclipboardxevents.c b/xorg-server/hw/xwin/winclipboardxevents.c index ce533c59f..5cae98caa 100644 --- a/xorg-server/hw/xwin/winclipboardxevents.c +++ b/xorg-server/hw/xwin/winclipboardxevents.c @@ -165,6 +165,24 @@ winClipboardFlushXEvents(HWND hwnd, break; } + /* Close clipboard if we have it open already */ + if (GetOpenClipboardWindow() == hwnd) { + CloseClipboard(); + } + + /* Access the clipboard */ + if (!OpenClipboard(hwnd)) { + ErrorF("winClipboardFlushXEvents - SelectionRequest - " + "OpenClipboard () failed: %08lx\n", GetLastError()); + + /* Abort */ + fAbort = TRUE; + goto winClipboardFlushXEvents_SelectionRequest_Done; + } + + /* Indicate that clipboard was opened */ + fCloseClipboard = TRUE; + /* Check that clipboard format is available */ if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) { static int count; /* Hack to stop acroread spamming the log */ @@ -192,24 +210,6 @@ winClipboardFlushXEvents(HWND hwnd, goto winClipboardFlushXEvents_SelectionRequest_Done; } - /* Close clipboard if we have it open already */ - if (GetOpenClipboardWindow() == hwnd) { - CloseClipboard(); - } - - /* Access the clipboard */ - if (!OpenClipboard(hwnd)) { - ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "OpenClipboard () failed: %08lx\n", GetLastError()); - - /* Abort */ - fAbort = TRUE; - goto winClipboardFlushXEvents_SelectionRequest_Done; - } - - /* Indicate that clipboard was opened */ - fCloseClipboard = TRUE; - /* Setup the string style */ if (event.xselectionrequest.target == XA_STRING) xiccesStyle = XStringStyle; diff --git a/xorg-server/hw/xwin/winengine.c b/xorg-server/hw/xwin/winengine.c index 67489598b..b2007d751 100644 --- a/xorg-server/hw/xwin/winengine.c +++ b/xorg-server/hw/xwin/winengine.c @@ -92,7 +92,7 @@ winDetectSupportedEngines(void) else { /* We have DirectDraw */ winErrorFVerb(2, - "winDetectSupportedEngines - DirectDraw installed\n"); + "winDetectSupportedEngines - DirectDraw installed, allowing ShadowDD\n"); g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD; #ifdef XWIN_PRIMARYFB @@ -100,7 +100,7 @@ winDetectSupportedEngines(void) if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { g_dwEnginesSupported |= WIN_SERVER_PRIMARY_DD; winErrorFVerb(2, - "winDetectSupportedEngines - Allowing PrimaryDD\n"); + "winDetectSupportedEngines - Windows NT, allowing PrimaryDD\n"); } #endif } @@ -112,7 +112,7 @@ winDetectSupportedEngines(void) if (SUCCEEDED(ddrval)) { /* We have DirectDraw4 */ winErrorFVerb(2, - "winDetectSupportedEngines - DirectDraw4 installed\n"); + "winDetectSupportedEngines - DirectDraw4 installed, allowing ShadowDDNL\n"); g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL; } diff --git a/xorg-server/hw/xwin/winerror.c b/xorg-server/hw/xwin/winerror.c index 6645469fc..1318b0f36 100644 --- a/xorg-server/hw/xwin/winerror.c +++ b/xorg-server/hw/xwin/winerror.c @@ -59,15 +59,16 @@ OsVendorVErrorF(const char *pszFormat, va_list va_args) #endif /* - * os/util.c/FatalError () calls our vendor ErrorF, so the message - * from a FatalError will be logged. Thus, the message for the - * fatal error is not passed to this function. + * os/log.c:FatalError () calls our vendor ErrorF, so the message + * from a FatalError will be logged. * * Attempt to do last-ditch, safe, important cleanup here. */ void OsVendorFatalError(const char *f, va_list args) { + char errormsg[1024] = ""; + /* Don't give duplicate warning if UseMsg was called */ if (g_fSilentFatalError) return; @@ -78,9 +79,28 @@ OsVendorFatalError(const char *f, va_list args) } LogClose(EXIT_ERR_ABORT); - winMessageBoxF("A fatal error has occurred and " PROJECT_NAME - " will now exit.\n" "Please open %s for more information.\n", - MB_ICONERROR, (g_pszLogFile ? g_pszLogFile : "the logfile")); + /* Format the error message */ + vsnprintf(errormsg, sizeof(errormsg), f, args); + + /* + Sometimes the error message needs a bit of cosmetic cleaning + up for use in a dialog box... + */ + { + char *s; + + while ((s = strstr(errormsg, "\n\t")) != NULL) { + s[0] = ' '; + s[1] = '\n'; + } + } + + winMessageBoxF("A fatal error has occurred and " PROJECT_NAME " will now exit.\n\n" + "%s\n\n" + "Please open %s for more information.\n", + MB_ICONERROR, + errormsg, + (g_pszLogFile ? g_pszLogFile : "the logfile")); } /* diff --git a/xorg-server/hw/xwin/winglobals.c b/xorg-server/hw/xwin/winglobals.c index 4953bd0cf..b34d1a751 100644 --- a/xorg-server/hw/xwin/winglobals.c +++ b/xorg-server/hw/xwin/winglobals.c @@ -77,7 +77,7 @@ Bool g_fKeyboardHookLL = FALSE; Bool g_fNoHelpMessageBox = FALSE; Bool g_fSoftwareCursor = FALSE; Bool g_fSilentDupError = FALSE; -Bool g_fNativeGl = FALSE; +Bool g_fNativeGl = TRUE; #ifdef XWIN_CLIPBOARD /* diff --git a/xorg-server/hw/xwin/winkeybd.c b/xorg-server/hw/xwin/winkeybd.c index 2ffb9a943..a70cdcd16 100644 --- a/xorg-server/hw/xwin/winkeybd.c +++ b/xorg-server/hw/xwin/winkeybd.c @@ -41,6 +41,9 @@ #include "xkbsrv.h" +/* C does not have a logical XOR operator, so we use a macro instead */ +#define LOGICAL_XOR(a,b) ((!(a) && (b)) || ((a) && !(b))) + static Bool g_winKeyState[NUM_KEYCODES]; /* @@ -259,36 +262,54 @@ winRestoreModeKeyStates(void) XkbStateFieldFromRec(&inputInfo.keyboard->key->xkbInfo->state); winDebug("winRestoreModeKeyStates: state %d\n", internalKeyStates); - /* - * NOTE: The C XOR operator, ^, will not work here because it is - * a bitwise operator, not a logical operator. C does not - * have a logical XOR operator, so we use a macro instead. - */ + /* Check if modifier keys are pressed, and if so, fake a press */ + { + BOOL ctrl = (GetAsyncKeyState(VK_CONTROL) < 0); + BOOL shift = (GetAsyncKeyState(VK_SHIFT) < 0); + BOOL alt = (GetAsyncKeyState(VK_LMENU) < 0); + BOOL altgr = (GetAsyncKeyState(VK_RMENU) < 0); + + if (ctrl && altgr) + ctrl = FALSE; + + if (LOGICAL_XOR(internalKeyStates & ControlMask, ctrl)) + winSendKeyEvent(KEY_LCtrl, ctrl); + + if (LOGICAL_XOR(internalKeyStates & ShiftMask, shift)) + winSendKeyEvent(KEY_ShiftL, shift); - /* Has the key state changed? */ + if (LOGICAL_XOR(internalKeyStates & Mod1Mask, alt)) + winSendKeyEvent(KEY_Alt, alt); + + if (LOGICAL_XOR(internalKeyStates & Mod5Mask, altgr)) + winSendKeyEvent(KEY_AltLang, altgr); + } + + /* + Check if latching modifier key states have changed, and if so, + fake a press and a release to toggle the modifier to the correct + state + */ dwKeyState = GetKeyState(VK_NUMLOCK) & 0x0001; - if (WIN_XOR(internalKeyStates & NumLockMask, dwKeyState)) { + if (LOGICAL_XOR(internalKeyStates & NumLockMask, dwKeyState)) { winSendKeyEvent(KEY_NumLock, TRUE); winSendKeyEvent(KEY_NumLock, FALSE); } - /* Has the key state changed? */ dwKeyState = GetKeyState(VK_CAPITAL) & 0x0001; - if (WIN_XOR(internalKeyStates & LockMask, dwKeyState)) { + if (LOGICAL_XOR(internalKeyStates & LockMask, dwKeyState)) { winSendKeyEvent(KEY_CapsLock, TRUE); winSendKeyEvent(KEY_CapsLock, FALSE); } - /* Has the key state changed? */ dwKeyState = GetKeyState(VK_SCROLL) & 0x0001; - if (WIN_XOR(internalKeyStates & ScrollLockMask, dwKeyState)) { + if (LOGICAL_XOR(internalKeyStates & ScrollLockMask, dwKeyState)) { winSendKeyEvent(KEY_ScrollLock, TRUE); winSendKeyEvent(KEY_ScrollLock, FALSE); } - /* Has the key state changed? */ dwKeyState = GetKeyState(VK_KANA) & 0x0001; - if (WIN_XOR(internalKeyStates & KanaMask, dwKeyState)) { + if (LOGICAL_XOR(internalKeyStates & KanaMask, dwKeyState)) { winSendKeyEvent(KEY_HKTG, TRUE); winSendKeyEvent(KEY_HKTG, FALSE); } diff --git a/xorg-server/hw/xwin/winms.h b/xorg-server/hw/xwin/winms.h index 5282fc982..32923e503 100644 --- a/xorg-server/hw/xwin/winms.h +++ b/xorg-server/hw/xwin/winms.h @@ -30,7 +30,6 @@ * Authors: Harold L Hunt II */ -#define NONAMELESSUNION #define DIRECTDRAW_VERSION 0x0300 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN diff --git a/xorg-server/hw/xwin/winmultiwindowwm.c b/xorg-server/hw/xwin/winmultiwindowwm.c index 42925e36d..773fc9767 100644 --- a/xorg-server/hw/xwin/winmultiwindowwm.c +++ b/xorg-server/hw/xwin/winmultiwindowwm.c @@ -1503,6 +1503,7 @@ winDeinitMultiWindowWM(void) #define HINT_NOMAXIMIZE (1L<<4) #define HINT_NOMINIMIZE (1L<<5) #define HINT_NOSYSMENU (1L<<6) +#define HINT_SKIPTASKBAR (1L<<7) /* These two are used on their own */ #define HINT_MAX (1L<<0) #define HINT_MIN (1L<<1) @@ -1511,12 +1512,14 @@ static void winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) { static Atom windowState, motif_wm_hints, windowType; - static Atom hiddenState, fullscreenState, belowState, aboveState; + static Atom hiddenState, fullscreenState, belowState, aboveState, + skiptaskbarState; static Atom dockWindow; static int generation; Atom type, *pAtom = NULL; int format; - unsigned long hint = 0, maxmin = 0, style, nitems = 0, left = 0; + unsigned long hint = 0, maxmin = 0, nitems = 0, left = 0; + unsigned long style, exStyle; MwmHints *mwm_hint = NULL; if (!hWnd) @@ -1535,6 +1538,8 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False); aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False); dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False); + skiptaskbarState = + XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", False); } if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L, @@ -1542,6 +1547,8 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) &nitems, &left, (unsigned char **) &pAtom) == Success) { if (pAtom && nitems == 1) { + if (*pAtom == skiptaskbarState) + hint |= HINT_SKIPTASKBAR; if (*pAtom == hiddenState) maxmin |= HINT_MIN; else if (*pAtom == fullscreenState) @@ -1630,10 +1637,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)) { XFetchName(pDisplay, iWindow, &window_name); @@ -1642,10 +1653,24 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) 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); + } + winSetAppUserModelID(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); } @@ -1682,13 +1707,15 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) HINT_NOFRAME; /* Now apply styles to window */ - style = GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */ + style = GetWindowLongPtr(hWnd, GWL_STYLE); if (!style) - return; + return; /* GetWindowLongPointer returns 0 on failure, we hope this isn't a valid style */ + + style &= ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */ - if (!hint) /* All on */ + if (!(hint & ~HINT_SKIPTASKBAR)) /* No hints, default */ style = style | WS_CAPTION | WS_SIZEBOX; - else if (hint & HINT_NOFRAME) /* All off */ + else if (hint & HINT_NOFRAME) /* No frame, no decorations */ style = style & ~WS_CAPTION & ~WS_SIZEBOX; else style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) | @@ -1704,7 +1731,21 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) if (hint & HINT_NOSYSMENU) style = style & ~WS_SYSMENU; + if (hint & HINT_SKIPTASKBAR) + style = style & ~WS_MINIMIZEBOX; /* window will become lost if minimized */ + SetWindowLongPtr(hWnd, GWL_STYLE, style); + + exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); + if (hint & HINT_SKIPTASKBAR) + exStyle = (exStyle & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW; + else + exStyle = (exStyle & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW; + SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle); + + winDebug + ("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n", + iWindow, hint, style, exStyle); } void diff --git a/xorg-server/hw/xwin/winmultiwindowwndproc.c b/xorg-server/hw/xwin/winmultiwindowwndproc.c index af917d6fc..4180a3aa3 100644 --- a/xorg-server/hw/xwin/winmultiwindowwndproc.c +++ b/xorg-server/hw/xwin/winmultiwindowwndproc.c @@ -825,6 +825,8 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_CLOSE: + /* Removep AppUserModelID property */ + winSetAppUserModelID(hwnd, NULL); /* Branch on if the window was killed in X already */ if (pWinPriv->fXKilled) { /* Window was killed, go ahead and destroy the window */ diff --git a/xorg-server/hw/xwin/winprocarg.c b/xorg-server/hw/xwin/winprocarg.c index 14056faf0..858be4a56 100644 --- a/xorg-server/hw/xwin/winprocarg.c +++ b/xorg-server/hw/xwin/winprocarg.c @@ -142,7 +142,7 @@ winInitializeScreenDefaults(void) #endif defaultScreenInfo.fMultipleMonitors = FALSE; defaultScreenInfo.fLessPointer = FALSE; - defaultScreenInfo.iResizeMode = notAllowed; + defaultScreenInfo.iResizeMode = resizeWithRandr; defaultScreenInfo.fNoTrayIcon = FALSE; defaultScreenInfo.iE3BTimeout = WIN_E3B_DEFAULT; defaultScreenInfo.fUseWinKillKey = WIN_DEFAULT_WIN_KILL; @@ -1161,6 +1161,8 @@ winLogVersionInfo(void) ErrorF("Vendor: %s\n", XVENDORNAME); ErrorF("Release: %d.%d.%d.%d\n", XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP); - ErrorF("%s\n\n", BUILDERSTRING); + if (strlen(BUILDERSTRING)) + ErrorF("%s\n", BUILDERSTRING); ErrorF("Contact: %s\n", BUILDERADDR); + ErrorF("\n"); } diff --git a/xorg-server/hw/xwin/winshaddd.c b/xorg-server/hw/xwin/winshaddd.c index 3afc57cd0..aad3a02a0 100644 --- a/xorg-server/hw/xwin/winshaddd.c +++ b/xorg-server/hw/xwin/winshaddd.c @@ -489,7 +489,7 @@ winShadowUpdateDD(ScreenPtr pScreen, shadowBufPtr pBuf) POINT ptOrigin; DWORD dwBox = RegionNumRects(damage); BoxPtr pBox = RegionRects(damage); - HRGN hrgnTemp = NULL, hrgnCombined = NULL; + HRGN hrgnCombined = NULL; /* * Return immediately if the app is not active @@ -551,15 +551,9 @@ winShadowUpdateDD(ScreenPtr pScreen, shadowBufPtr pBuf) BoxPtr pBoxExtents = RegionExtents(damage); /* Compute a GDI region from the damaged region */ - hrgnCombined = CreateRectRgn(pBox->x1, pBox->y1, pBox->x2, pBox->y2); - dwBox--; - pBox++; - while (dwBox--) { - hrgnTemp = CreateRectRgn(pBox->x1, pBox->y1, pBox->x2, pBox->y2); - CombineRgn(hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); - DeleteObject(hrgnTemp); - pBox++; - } + hrgnCombined = + CreateRectRgn(pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2, + pBoxExtents->y2); /* Install the GDI region as a clipping region */ SelectClipRgn(pScreenPriv->hdcScreen, hrgnCombined); diff --git a/xorg-server/hw/xwin/winshadddnl.c b/xorg-server/hw/xwin/winshadddnl.c index e7306151e..7668bd1c0 100644 --- a/xorg-server/hw/xwin/winshadddnl.c +++ b/xorg-server/hw/xwin/winshadddnl.c @@ -523,7 +523,7 @@ winShadowUpdateDDNL(ScreenPtr pScreen, shadowBufPtr pBuf) POINT ptOrigin; DWORD dwBox = RegionNumRects(damage); BoxPtr pBox = RegionRects(damage); - HRGN hrgnTemp = NULL, hrgnCombined = NULL; + HRGN hrgnCombined = NULL; /* * Return immediately if the app is not active @@ -595,15 +595,9 @@ winShadowUpdateDDNL(ScreenPtr pScreen, shadowBufPtr pBuf) BoxPtr pBoxExtents = RegionExtents(damage); /* Compute a GDI region from the damaged region */ - hrgnCombined = CreateRectRgn(pBox->x1, pBox->y1, pBox->x2, pBox->y2); - dwBox--; - pBox++; - while (dwBox--) { - hrgnTemp = CreateRectRgn(pBox->x1, pBox->y1, pBox->x2, pBox->y2); - CombineRgn(hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); - DeleteObject(hrgnTemp); - pBox++; - } + hrgnCombined = + CreateRectRgn(pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2, + pBoxExtents->y2); /* Install the GDI region as a clipping region */ SelectClipRgn(pScreenPriv->hdcScreen, hrgnCombined); diff --git a/xorg-server/hw/xwin/winshadgdi.c b/xorg-server/hw/xwin/winshadgdi.c index cdbb46bf2..912f7e41f 100644 --- a/xorg-server/hw/xwin/winshadgdi.c +++ b/xorg-server/hw/xwin/winshadgdi.c @@ -439,7 +439,7 @@ winShadowUpdateGDI(ScreenPtr pScreen, shadowBufPtr pBuf) DWORD dwBox = RegionNumRects(damage); BoxPtr pBox = RegionRects(damage); int x, y, w, h; - HRGN hrgnTemp = NULL, hrgnCombined = NULL; + HRGN hrgnCombined = NULL; #ifdef XWIN_UPDATESTATS static DWORD s_dwNonUnitRegions = 0; @@ -500,16 +500,11 @@ winShadowUpdateGDI(ScreenPtr pScreen, shadowBufPtr pBuf) } } else if (!pScreenInfo->fMultiWindow) { + /* Compute a GDI region from the damaged region */ - hrgnCombined = CreateRectRgn(pBox->x1, pBox->y1, pBox->x2, pBox->y2); - dwBox--; - pBox++; - while (dwBox--) { - hrgnTemp = CreateRectRgn(pBox->x1, pBox->y1, pBox->x2, pBox->y2); - CombineRgn(hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); - DeleteObject(hrgnTemp); - pBox++; - } + hrgnCombined = + CreateRectRgn(pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2, + pBoxExtents->y2); /* Install the GDI region as a clipping region */ SelectClipRgn(pScreenPriv->hdcScreen, hrgnCombined); diff --git a/xorg-server/hw/xwin/wintaskbar.c b/xorg-server/hw/xwin/wintaskbar.c new file mode 100644 index 000000000..7dd4ec30b --- /dev/null +++ b/xorg-server/hw/xwin/wintaskbar.c @@ -0,0 +1,92 @@ +/* + 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 (including the next + paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. +*/ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include "win.h" +#include "winwindow.h" + +const GUID CLSID_TaskbarList = {0x56fdf344,0xfd6d,0x11d0,{0x95,0x8a,0x0,0x60,0x97,0xc9,0xa0,0x90}}; +const GUID IID_ITaskbarList = {0x56fdf342,0xfd6d,0x11d0,{0x95,0x8a,0x0,0x60,0x97,0xc9,0xa0,0x90}}; + +#ifdef INTERFACE +#undef INTERFACE +#endif + +#define INTERFACE ITaskbarList +DECLARE_INTERFACE_(ITaskbarList, IUnknown) +{ + /* IUnknown methods */ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + + /* ITaskbarList methods */ + STDMETHOD(HrInit) (THIS) PURE; + STDMETHOD(AddTab) (THIS_ HWND hWnd) PURE; + STDMETHOD(DeleteTab) (THIS_ HWND hWnd) PURE; + STDMETHOD(ActivateTab) (THIS_ HWND hWnd) PURE; + STDMETHOD(SetActiveAlt) (THIS_ HWND hWnd) PURE; +}; +#undef INTERFACE + +/* + The stuff above needs to be in win32api headers, not defined here, + or at least generated from the MIDL :-) +*/ + +/* + This is unnecessarily heavyweight, we could just call CoInitialize() once at + startup and CoUninitialize() once at shutdown +*/ + +/* + The documentation for ITaskbarList::AddTab says that we are responsible for + deleting the tab ourselves when the window is deleted, but that doesn't actually + seem to be the case +*/ + +void winShowWindowOnTaskbar(HWND hWnd, BOOL show) +{ + ITaskbarList* pTaskbarList = NULL; + + if (SUCCEEDED(CoInitialize(NULL))) + { + if (SUCCEEDED(CoCreateInstance((const CLSID *)&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, (const IID *)&IID_ITaskbarList, (void**)&pTaskbarList))) + { + if (SUCCEEDED(pTaskbarList->lpVtbl->HrInit(pTaskbarList))) + { + if (show) + { + pTaskbarList->lpVtbl->AddTab(pTaskbarList,hWnd); + } + else + { + pTaskbarList->lpVtbl->DeleteTab(pTaskbarList,hWnd); + } + } + pTaskbarList->lpVtbl->Release(pTaskbarList); + } + CoUninitialize(); + } +} diff --git a/xorg-server/hw/xwin/winwin32rootless.c b/xorg-server/hw/xwin/winwin32rootless.c index 5bf710209..974309248 100644 --- a/xorg-server/hw/xwin/winwin32rootless.c +++ b/xorg-server/hw/xwin/winwin32rootless.c @@ -263,7 +263,7 @@ winMWExtWMCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, strcat(pszClass, pszWindowID); #if CYGMULTIWINDOW_DEBUG - winDebug("winCreateWindowsWindow - Creating class: %s\n", pszClass); + winDebug("winMWExtWMCreateFrame - Creating class: %s\n", pszClass); #endif /* Setup our window class */ diff --git a/xorg-server/hw/xwin/winwindow.h b/xorg-server/hw/xwin/winwindow.h index 49a720a67..37b975224 100644 --- a/xorg-server/hw/xwin/winwindow.h +++ b/xorg-server/hw/xwin/winwindow.h @@ -148,5 +148,17 @@ void void winMinimizeWindow(Window id); +void + winPropertyStoreInit(void); + +void + winPropertyStoreDestroy(void); + +void + winSetAppUserModelID(HWND hWnd, const char *AppID); + +void + winShowWindowOnTaskbar(HWND hWnd, BOOL show); + #endif /* XWIN_MULTIWINDOW */ #endif diff --git a/xorg-server/hw/xwin/winwndproc.c b/xorg-server/hw/xwin/winwndproc.c index fe662b9ba..7ba028042 100644 --- a/xorg-server/hw/xwin/winwndproc.c +++ b/xorg-server/hw/xwin/winwndproc.c @@ -930,6 +930,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WIN_POLLING_MOUSE_TIMER_ID: { + static POINT last_point; POINT point; WPARAM wL, wM, wR, wShift, wCtrl; LPARAM lPos; @@ -941,8 +942,12 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) point.x -= GetSystemMetrics(SM_XVIRTUALSCREEN); point.y -= GetSystemMetrics(SM_YVIRTUALSCREEN); - /* Deliver absolute cursor position to X Server */ - winEnqueueMotion(point.x, point.y); + /* If the mouse pointer has moved, deliver absolute cursor position to X Server */ + if (last_point.x != point.x || last_point.y != point.y) { + winEnqueueMotion(point.x, point.y); + last_point.x = point.x; + last_point.y = point.y; + } /* Check if a button was released but we didn't see it */ GetCursorPos(&point); |