diff options
Diffstat (limited to 'hw/xwin')
34 files changed, 1498 insertions, 379 deletions
diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index 4a601b222..6e5c366aa 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -35,12 +35,10 @@ from The Open Group. #include "winmsg.h" #include "winconfig.h" #include "winprefs.h" -#ifdef XWIN_CLIPBOARD -#include "X11/Xlocale.h" -#endif #ifdef DPMSExtension #include "dpmsproc.h" #endif +#include <locale.h> #ifdef __CYGWIN__ #include <mntent.h> #endif @@ -57,6 +55,7 @@ typedef WINAPI HRESULT (*SHGETFOLDERPATHPROC)( LPTSTR pszPath ); #endif +#include "ddxhooks.h" /* * References to external symbols @@ -84,8 +83,6 @@ void OsVendorVErrorF (const char *pszFormat, va_list va_args); #endif -static Bool -winCheckDisplayNumber (void); void winLogCommandLine (int argc, char *argv[]); @@ -101,6 +98,8 @@ const char * winGetBaseDir(void); #endif +static void winCheckMount(void); + /* * For the depth 24 pixmap we default to 32 bits per pixel, but * we change this pixmap format later if we detect that the display @@ -165,13 +164,12 @@ ddxPushProviders(void) #endif } -#if defined(DDXBEFORERESET) /* * Called right before KillAllClients when the server is going to reset, * allows us to shutdown our seperate threads cleanly. */ -void +static void ddxBeforeReset (void) { winDebug ("ddxBeforeReset - Hello\n"); @@ -180,8 +178,31 @@ ddxBeforeReset (void) winClipboardShutdown (); #endif } -#endif +void +ddxMain(void) +{ + int iReturn; + + /* Initialize DDX-specific hooks */ + ddxHooks.ddxBeforeReset = ddxBeforeReset; + ddxHooks.ddxPushProviders = ddxPushProviders; + + /* Create & acquire the termination mutex */ + iReturn = pthread_mutex_init (&g_pmTerminating, NULL); + if (iReturn != 0) + { + ErrorF ("ddxMain - pthread_mutex_init () failed: %d\n", iReturn); + } + + iReturn = pthread_mutex_lock (&g_pmTerminating); + if (iReturn != 0) + { + ErrorF ("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn); + } + + winCheckMount(); +} /* See Porting Layer Definition - p. 57 */ void @@ -202,6 +223,9 @@ ddxGiveUp (enum ExitCode error) } #ifdef XWIN_MULTIWINDOW + /* Unload libraries for taskbar grouping */ + winTaskbarDestroy (); + /* Notify the worker threads we're exiting */ winDeinitMultiWindowWM (); #endif @@ -239,8 +263,19 @@ ddxGiveUp (enum ExitCode error) /* Tell Windows that we want to end the app */ PostQuitMessage (0); -} + { + winDebug ("ddxGiveUp - Releasing termination mutex\n"); + + int iReturn = pthread_mutex_unlock (&g_pmTerminating); + if (iReturn != 0) + { + ErrorF ("winMsgWindowProc - pthread_mutex_unlock () failed: %d\n", iReturn); + } + } + + winDebug ("ddxGiveUp - End\n"); +} /* See Porting Layer Definition - p. 57 */ void @@ -253,6 +288,8 @@ AbortDDX (enum ExitCode error) } #ifdef __CYGWIN__ +extern Bool nolock; + /* hasmntopt is currently not implemented for cygwin */ static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt) { @@ -274,6 +311,9 @@ static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt) return NULL; } +/* + Check mounts and issue warnings/activate workarounds as needed + */ static void winCheckMount(void) { @@ -283,6 +323,7 @@ winCheckMount(void) enum { none = 0, sys_root, user_root, sys_tmp, user_tmp } level = none, curlevel; BOOL binary = TRUE; + BOOL fat = TRUE; mnt = setmntent("/etc/mtab", "r"); if (mnt == NULL) @@ -325,20 +366,31 @@ winCheckMount(void) binary = FALSE; else binary = TRUE; + + if (strcmp(ent->mnt_type, "vfat") == 0) + fat = TRUE; + else + fat = FALSE; } - + if (endmntent(mnt) != 1) { ErrorF("endmntent failed"); return; } - - if (!binary) + + if (!binary) winMsg(X_WARNING, "/tmp mounted in textmode\n"); + + if (fat) + { + winMsg(X_WARNING, "/tmp mounted on FAT filesystem, activating -nolock\n"); + nolock = TRUE; + } } #else static void -winCheckMount(void) +winCheckMount(void) { } #endif @@ -762,6 +814,9 @@ winUseMsg (void) ErrorF ("-fullscreen\n" "\tRun the server in fullscreen mode.\n"); + ErrorF ("-hostintitle\n" + "\tIn multiwindow mode, add remote host names to window titles.\n"); + ErrorF ("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n"); @@ -825,7 +880,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"); @@ -859,7 +914,8 @@ 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\n" + "\tfor hardware-accelerated OpenGL (AIGLX). Enabled by default.\n"); #endif ErrorF ("-[no]winkill\n" @@ -933,15 +989,6 @@ InitOutput (ScreenInfo *screenInfo, int argc, char *argv[]) "Exiting.\n"); } - /* Check for duplicate invocation on same display number.*/ - if (serverGeneration == 1 && !winCheckDisplayNumber ()) - { - if (g_fSilentDupError) - g_fSilentFatalError = TRUE; - FatalError ("InitOutput - Duplicate invocation on display " - "number: %s. Exiting.\n", display); - } - #ifdef XWIN_XF86CONFIG /* Try to read the xorg.conf-style configuration file */ if (!winReadConfigfile ()) @@ -975,9 +1022,18 @@ 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); + /* Create the messaging window */ + if (serverGeneration == 1) + winCreateMsgWindowThread(); + /* Initialize each screen */ for (i = 0; i < g_iNumScreens; ++i) { @@ -997,11 +1053,27 @@ InitOutput (ScreenInfo *screenInfo, int argc, char *argv[]) /* Perform some one time initialization */ if (1 == serverGeneration) { + /* Allow multiple threads to access Xlib */ + if (XInitThreads () == 0) + { + ErrorF ("XInitThreads failed.\n"); + } + /* * setlocale applies to all threads in the current process. * Apply locale specified in LANG environment variable. */ - setlocale (LC_ALL, ""); + if (!setlocale (LC_ALL, "")) + { + ErrorF ("setlocale failed.\n"); + } + + /* See if X supports the current locale */ + if (XSupportsLocale () == FALSE) + { + ErrorF ("Warning: Locale not supported by X, falling back to 'C' locale.\n"); + setlocale(LC_ALL, "C"); + } } #endif @@ -1009,78 +1081,3 @@ InitOutput (ScreenInfo *screenInfo, int argc, char *argv[]) winDebug ("InitOutput - Returning.\n"); #endif } - - -/* - * winCheckDisplayNumber - Check if another instance of Cygwin/X is - * already running on the same display number. If no one exists, - * make a mutex to prevent new instances from running on the same display. - * - * return FALSE if the display number is already used. - */ - -static Bool -winCheckDisplayNumber (void) -{ - int nDisp; - HANDLE mutex; - char name[MAX_PATH]; - char * pszPrefix = '\0'; - OSVERSIONINFO osvi = {0}; - - /* Check display range */ - nDisp = atoi (display); - if (nDisp < 0 || nDisp > 65535) - { - ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp); - return FALSE; - } - - /* Set first character of mutex name to null */ - name[0] = '\0'; - - /* Get operating system version information */ - osvi.dwOSVersionInfoSize = sizeof (osvi); - GetVersionEx (&osvi); - - /* Want a mutex shared among all terminals on NT > 4.0 */ - if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT - && osvi.dwMajorVersion >= 5) - { - pszPrefix = "Global\\"; - } - - /* Setup Cygwin/X specific part of name */ - snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp); - - /* Windows automatically releases the mutex when this process exits */ - mutex = CreateMutex (NULL, FALSE, name); - if (!mutex) - { - LPVOID lpMsgBuf; - - /* Display a fancy error message */ - FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError (), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL); - ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n", - (LPSTR)lpMsgBuf); - LocalFree (lpMsgBuf); - - return FALSE; - } - if (GetLastError () == ERROR_ALREADY_EXISTS) - { - ErrorF ("winCheckDisplayNumber - " - PROJECT_NAME " is already running on display %d\n", - nDisp); - return FALSE; - } - - return TRUE; -} diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am index c49016398..17a4adbb9 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 @@ -90,6 +91,7 @@ SRCS = InitInput.c \ winmonitors.c \ winmouse.c \ winmsg.c \ + winmsgwindow.c \ winmultiwindowclass.c \ winmultiwindowicons.c \ winprefs.c \ @@ -120,6 +122,7 @@ SRCS = InitInput.c \ winprefs.h \ winresource.h \ winwindow.h \ + windisplay.c \ XWin.rc \ $(top_srcdir)/Xext/dpmsstubs.c \ $(top_srcdir)/Xi/stubs.c \ @@ -147,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/glx/gen_gl_wrappers.py b/hw/xwin/glx/gen_gl_wrappers.py index e2d960ec6..79fbeefe8 100755 --- a/hw/xwin/glx/gen_gl_wrappers.py +++ b/hw/xwin/glx/gen_gl_wrappers.py @@ -67,7 +67,7 @@ if dispatchheader : fh = open(dispatchheader) dispatchh = fh.readlines() - dispatch_regex = re.compile(r'#define\sSET_(\S*)\(') + dispatch_regex = re.compile(r'(?:#define|static\sinline\svoid)\sSET_(\S*)\(') for line in dispatchh : line = line.strip() @@ -308,12 +308,20 @@ for w in sorted(wrappers.keys()) : if dispatchheader : print 'void glWinSetupDispatchTable(void)' print '{' - print ' struct _glapi_table *disp = _glapi_get_dispatch();' + print ' static struct _glapi_table *disp = NULL;' + print '' + print ' if (!disp)' + print ' {' + print ' disp = calloc(sizeof(void *), _glapi_get_dispatch_table_size());' + print ' assert(disp);' for d in sorted(dispatch.keys()) : if wrappers.has_key(d) : - print ' SET_'+ d + '(disp, (void *)' + prefix + d + 'Wrapper);' + print ' SET_'+ d + '(disp, (void *)' + prefix + d + 'Wrapper);' else : print '#warning No wrapper for ' + prefix + d + ' !' + print ' }' + print '' + print ' _glapi_set_dispatch(disp);' print '}' diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c index 86fef55d1..0873c5e4a 100644 --- a/hw/xwin/glx/indirect.c +++ b/hw/xwin/glx/indirect.c @@ -469,7 +469,7 @@ static void glxLogExtensions(const char *prefix, const char *extensions) { int length = 0; - char *strl; + const char *strl; char *str = strdup(extensions); if (str == NULL) @@ -479,6 +479,7 @@ glxLogExtensions(const char *prefix, const char *extensions) } strl = strtok(str, " "); + if (strl == NULL) strl = ""; ErrorF("%s%s", prefix, strl); length = strlen(prefix) + strlen(strl); @@ -514,6 +515,7 @@ glxWinScreenProbe(ScreenPtr pScreen) { glxWinScreen *screen; const char *gl_extensions; + const char *gl_renderer; const char *wgl_extensions; HWND hwnd; HDC hdc; @@ -537,14 +539,6 @@ glxWinScreenProbe(ScreenPtr pScreen) if (NULL == screen) return NULL; - /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */ - screen->RealizeWindow = pScreen->RealizeWindow; - pScreen->RealizeWindow = glxWinRealizeWindow; - screen->UnrealizeWindow = pScreen->UnrealizeWindow; - pScreen->UnrealizeWindow = glxWinUnrealizeWindow; - screen->CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = glxWinCopyWindow; - /* Dump out some useful information about the native renderer */ // create window class @@ -591,13 +585,21 @@ glxWinScreenProbe(ScreenPtr pScreen) ErrorF("GL_VERSION: %s\n", glGetStringWrapperNonstatic(GL_VERSION)); ErrorF("GL_VENDOR: %s\n", glGetStringWrapperNonstatic(GL_VENDOR)); - ErrorF("GL_RENDERER: %s\n", glGetStringWrapperNonstatic(GL_RENDERER)); + 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 (strcasecmp(gl_renderer, "GDI Generic") == 0) + { + free(screen); + LogMessage(X_ERROR,"AIGLX: Won't use generic native renderer as it is not accelerated\n"); + return NULL; + } + // Can you see the problem here? The extensions string is DC specific // Different DCs for windows on a multimonitor system driven by multiple cards // might have completely different capabilities. Of course, good luck getting @@ -715,9 +717,6 @@ glxWinScreenProbe(ScreenPtr pScreen) __glXScreenInit(&screen->base, pScreen); - // dump out fbConfigs now fbConfigIds and visualIDs have been assigned - fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs); - // Override the GL extensions string set by __glXScreenInit() screen->base.GLextensions = strdup(gl_extensions); @@ -761,6 +760,17 @@ glxWinScreenProbe(ScreenPtr pScreen) ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); + // dump out fbConfigs now fbConfigIds and visualIDs have been assigned + fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs); + + /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */ + screen->RealizeWindow = pScreen->RealizeWindow; + pScreen->RealizeWindow = glxWinRealizeWindow; + screen->UnrealizeWindow = pScreen->UnrealizeWindow; + pScreen->UnrealizeWindow = glxWinUnrealizeWindow; + screen->CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = glxWinCopyWindow; + return &screen->base; } diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c index 460973730..72d65bc14 100644 --- a/hw/xwin/glx/winpriv.c +++ b/hw/xwin/glx/winpriv.c @@ -13,6 +13,40 @@ void winCreateWindowsWindow (WindowPtr pWin); + +static +void +winCreateWindowsWindowHierarchy(WindowPtr pWin) +{ + winWindowPriv(pWin); + + winDebug("winCreateWindowsWindowHierarchy - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); + + /* recursively ensure parent window exists if it's not the root window */ + if (pWin->parent) + { + if (pWin->parent != pWin->drawable.pScreen->root) + winCreateWindowsWindowHierarchy(pWin->parent); + } + + /* ensure this window exists */ + if (pWinPriv->hWnd == NULL) + { + winCreateWindowsWindow(pWin); + + /* ... and if it's already been mapped, make sure it's visible */ + if (pWin->mapped) + { + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + /* Send first paint message */ + UpdateWindow (pWinPriv->hWnd); + } + } +} + /** * Return size and handles of a window. * If pWin is NULL, then the information for the root window is requested. @@ -53,8 +87,8 @@ HWND winGetWindowInfo(WindowPtr pWin) if (pWinPriv->hWnd == NULL) { - winCreateWindowsWindow(pWin); - ErrorF("winGetWindowInfo: forcing window to exist...\n"); + ErrorF("winGetWindowInfo: forcing window to exist\n"); + winCreateWindowsWindowHierarchy(pWin); } if (pWinPriv->hWnd != NULL) diff --git a/hw/xwin/man/XWin.man b/hw/xwin/man/XWin.man index d03a36521..67219e3f7 100644 --- a/hw/xwin/man/XWin.man +++ b/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,10 +161,16 @@ 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 FOR MULTIWINDOW MODE +.TP 8 +.B \-hostintitle +Add the host name to the window title for X applications which are running +on remote hosts, when that information is available and it's useful to do so. + .SH OPTIONS CONTROLLING WINDOWS INTEGRATION .TP 8 .B \-[no]clipboard @@ -211,7 +219,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/hw/xwin/system.XWinrc b/hw/xwin/system.XWinrc index f0771c610..5ff3abad6 100644 --- a/hw/xwin/system.XWinrc +++ b/hw/xwin/system.XWinrc @@ -89,9 +89,17 @@ menu apps { } menu root { + "Applications" menu apps // Comments fit here, too... + + SEPARATOR + FAQ EXEC "cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html" + "User's Guide" EXEC "cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html" + SEPARATOR + "View logfile" EXEC "xterm -e less +F $XWINLOGFILE" + SEPARATOR + "Reload .XWinrc" RELOAD - "Applications" menu apps SEParATOR } 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/win.h b/hw/xwin/win.h index 583906442..a0631b3af 100644 --- a/hw/xwin/win.h +++ b/hw/xwin/win.h @@ -400,6 +400,8 @@ typedef struct DWORD dwScreen; int iMonitor; + HMONITOR hMonitor; + DWORD dwUserWidth; DWORD dwUserHeight; DWORD dwWidth; @@ -1317,6 +1319,9 @@ winAdjustXWindow (WindowPtr pWin, HWND hwnd); LRESULT CALLBACK winTopLevelWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK +winChildWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); #endif @@ -1482,6 +1487,18 @@ winDoRandRScreenSetSize (ScreenPtr pScreen, CARD16 height, CARD32 mmWidth, CARD32 mmHeight); +/* + * windisplay.c + */ + +void +winGetDisplayName(char *szDisplay, unsigned int screen); + +/* + * winmsgwindow.c + */ +Bool +winCreateMsgWindowThread(void); /* * END DDX and DIX Function Prototypes diff --git a/hw/xwin/winblock.c b/hw/xwin/winblock.c index e165d5488..b3bbc3dc8 100644 --- a/hw/xwin/winblock.c +++ b/hw/xwin/winblock.c @@ -44,7 +44,7 @@ winBlockHandler (int nScreen, #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) winScreenPriv((ScreenPtr)pBlockData); #endif - MSG msg; + #ifndef HAS_DEVWINDOWS struct timeval **tvp = pTimeout; if (*tvp != NULL) @@ -52,6 +52,24 @@ winBlockHandler (int nScreen, (*tvp)->tv_sec = 0; (*tvp)->tv_usec = 100; } +#else + /* + Sometimes, we have work to do on the Windows message queue, + but /dev/windows doesn't appear to be ready. At the moment, + I don't understand how that happens. + + As a workaround, make sure select() just polls rather than + blocking if there are still messages to process... + */ + if (GetQueueStatus(QS_ALLINPUT | QS_ALLPOSTMESSAGE) != 0) + { + struct timeval **tvp = pTimeout; + if (*tvp != NULL) + { + (*tvp)->tv_sec = 0; + (*tvp)->tv_usec = 0; + } + } #endif #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) @@ -59,8 +77,8 @@ winBlockHandler (int nScreen, if (pScreenPriv != NULL && !pScreenPriv->fServerStarted) { int iReturn; - - winDebug ("winBlockHandler - Releasing pmServerStarted\n"); + + ErrorF ("winBlockHandler - pthread_mutex_unlock()\n"); /* Flag that modules are to be started */ pScreenPriv->fServerStarted = TRUE; @@ -71,26 +89,18 @@ winBlockHandler (int nScreen, { ErrorF ("winBlockHandler - pthread_mutex_unlock () failed: %d\n", iReturn); - goto winBlockHandler_ProcessMessages; } - - winDebug ("winBlockHandler - pthread_mutex_unlock () returned\n"); - } - -winBlockHandler_ProcessMessages: -#endif - - /* Process all messages on our queue */ - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) - { - if ((g_hDlgDepthChange == 0 - || !IsDialogMessage (g_hDlgDepthChange, &msg)) - && (g_hDlgExit == 0 - || !IsDialogMessage (g_hDlgExit, &msg)) - && (g_hDlgAbout == 0 - || !IsDialogMessage (g_hDlgAbout, &msg))) + else { - DispatchMessage (&msg); + winDebug ("winBlockHandler - pthread_mutex_unlock () returned\n"); } } +#endif + + /* + At least one X client has asked to suspend the screensaver, so + reset Windows' display idle timer + */ + if (screenSaverSuspended) + SetThreadExecutionState(ES_DISPLAY_REQUIRED); } diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h index b655f1623..bdec33f53 100644 --- a/hw/xwin/winclipboard.h +++ b/hw/xwin/winclipboard.h @@ -49,7 +49,6 @@ #include <X11/Xatom.h> #include <X11/Xproto.h> #include <X11/Xutil.h> -#include <X11/Xlocale.h> /* Windows headers */ #include <X11/Xwindows.h> diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c index d74cd03e2..1cbc27a2b 100644 --- a/hw/xwin/winclipboardinit.c +++ b/hw/xwin/winclipboardinit.c @@ -61,7 +61,7 @@ extern HWND g_hwndClipboard; Bool winInitClipboard (void) { - ErrorF ("winInitClipboard ()\n"); + winDebug ("winInitClipboard ()\n"); /* Wrap some internal server functions */ if (ProcVector[X_SetSelectionOwner] != winProcSetSelectionOwner) diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c index bc4bc3059..de6803436 100644 --- a/hw/xwin/winclipboardthread.c +++ b/hw/xwin/winclipboardthread.c @@ -80,6 +80,9 @@ winClipboardErrorHandler (Display *pDisplay, XErrorEvent *pErr); static int winClipboardIOErrorHandler (Display *pDisplay); +static void +winClipboardThreadExit(void *arg); + /* * Main thread function */ @@ -105,7 +108,9 @@ winClipboardProc (void *pvNotUsed) char szDisplay[512]; int iSelectError; - ErrorF ("winClipboardProc - Hello\n"); + pthread_cleanup_push(&winClipboardThreadExit, NULL); + + winDebug ("winClipboardProc - Hello\n"); ++clipboardRestarts; /* Do we have Unicode support? */ @@ -117,19 +122,6 @@ winClipboardProc (void *pvNotUsed) /* Save the Unicode support flag in a global */ g_fUseUnicode = fUseUnicode; - /* Allow multiple threads to access Xlib */ - if (XInitThreads () == 0) - { - ErrorF ("winClipboardProc - XInitThreads failed.\n"); - goto winClipboardProc_Exit; - } - - /* See if X supports the current locale */ - if (XSupportsLocale () == False) - { - ErrorF ("winClipboardProc - Warning: Locale not supported by X.\n"); - } - /* Set error handler */ XSetErrorHandler (winClipboardErrorHandler); g_winClipboardProcThread = pthread_self(); @@ -149,9 +141,9 @@ winClipboardProc (void *pvNotUsed) } else if (iReturn == WIN_JMP_ERROR_IO) { - /* TODO: Cleanup the Win32 window and free any allocated memory */ - ErrorF ("winClipboardProc - setjmp returned for IO Error Handler.\n"); - pthread_exit (NULL); + /* TODO: cleanup and free any allocated memory */ + ErrorF("winClipboardProc - setjmp returned for IO Error Handler\n"); + goto winClipboardProc_Done; } /* Use our generated cookie for authentication */ @@ -168,10 +160,7 @@ winClipboardProc (void *pvNotUsed) * for all screens on the display. That is why there is only * one clipboard client thread. */ - snprintf (szDisplay, - 512, - "127.0.0.1:%s.0", - display); + winGetDisplayName(szDisplay, 0); /* Print the display connection string */ ErrorF ("winClipboardProc - DISPLAY=%s\n", szDisplay); @@ -201,7 +190,7 @@ winClipboardProc (void *pvNotUsed) goto winClipboardProc_Done; } - /* Save the display in the screen privates */ + /* Save the display in a global used by the wndproc */ g_pClipboardDisplay = pDisplay; ErrorF ("winClipboardProc - XOpenDisplay () returned and " @@ -298,7 +287,10 @@ winClipboardProc (void *pvNotUsed) /* Pre-flush Windows messages */ if (!winClipboardFlushWindowsMessageQueue (hwnd)) - return 0; + { + ErrorF ("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n"); + pthread_exit (NULL); + } /* Signal that the clipboard client has started */ g_fClipboardStarted = TRUE; @@ -478,6 +470,8 @@ winClipboardProc_Done: kill(getpid(), SIGTERM); } + pthread_cleanup_pop(0); + return NULL; } @@ -525,3 +519,14 @@ winClipboardIOErrorHandler (Display *pDisplay) return 0; } + +/* + * winClipboardThreadExit - Thread exit handler + */ + +static void +winClipboardThreadExit(void *arg) +{ + /* clipboard thread has exited, stop server as well */ + kill(getpid(), SIGTERM); +} diff --git a/hw/xwin/winclipboardwrappers.c b/hw/xwin/winclipboardwrappers.c index ec6e95a8a..7ffb6fc3d 100644 --- a/hw/xwin/winclipboardwrappers.c +++ b/hw/xwin/winclipboardwrappers.c @@ -92,7 +92,7 @@ winProcEstablishConnection (ClientPtr client) static int s_iCallCount = 0; static unsigned long s_ulServerGeneration = 0; - if (s_iCallCount == 0) ErrorF ("winProcEstablishConnection - Hello\n"); + if (s_iCallCount == 0) winDebug ("winProcEstablishConnection - Hello\n"); /* Do nothing if clipboard is not enabled */ if (!g_fClipboard) diff --git a/hw/xwin/wincreatewnd.c b/hw/xwin/wincreatewnd.c index 755373965..882725f54 100644 --- a/hw/xwin/wincreatewnd.c +++ b/hw/xwin/wincreatewnd.c @@ -34,10 +34,6 @@ #include "win.h" #include "shellapi.h" -#ifndef ABS_AUTOHIDE -#define ABS_AUTOHIDE 1 -#endif - /* * Local function prototypes */ @@ -46,7 +42,7 @@ static Bool winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo); static Bool -winAdjustForAutoHide (RECT *prcWorkArea); +winAdjustForAutoHide (RECT *prcWorkArea, winScreenInfo *pScreenInfo); /* @@ -219,7 +215,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) winGetWorkArea (&rcWorkArea, pScreenInfo); /* Adjust for auto-hide taskbars */ - winAdjustForAutoHide (&rcWorkArea); + winAdjustForAutoHide (&rcWorkArea, pScreenInfo); /* Did the user specify a position? */ if (pScreenInfo->fUserGavePosition) @@ -523,14 +519,33 @@ winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo) int iLeft, iTop; int iPrimaryNonWorkAreaWidth, iPrimaryNonWorkAreaHeight; + /* Use GetMonitorInfo to get work area for monitor */ + if (!pScreenInfo->fMultipleMonitors) + { + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + if (GetMonitorInfo(pScreenInfo->hMonitor, &mi)) + { + *prcWorkArea = mi.rcWork; + + winDebug ("winGetWorkArea - Monitor %d WorkArea: %d %d %d %d\n", + pScreenInfo->iMonitor, + (int) prcWorkArea->top, (int) prcWorkArea->left, + (int) prcWorkArea->bottom, (int) prcWorkArea->right); + } + else + { + ErrorF ("winGetWorkArea - GetMonitorInfo() failed for monitor %d\n", pScreenInfo->iMonitor); + } + + /* Bail out here if we aren't using multiple monitors */ + return TRUE; + } + /* SPI_GETWORKAREA only gets the work area of the primary screen. */ SystemParametersInfo (SPI_GETWORKAREA, 0, prcWorkArea, 0); - /* Bail out here if we aren't using multiple monitors */ - if (!pScreenInfo->fMultipleMonitors) - return TRUE; - - winDebug ("winGetWorkArea - Original WorkArea: %d %d %d %d\n", + winDebug ("winGetWorkArea - Primary Monitor WorkArea: %d %d %d %d\n", (int) prcWorkArea->top, (int) prcWorkArea->left, (int) prcWorkArea->bottom, (int) prcWorkArea->right); @@ -581,6 +596,28 @@ winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo) return TRUE; } +static Bool +winTaskbarOnScreenEdge(unsigned int uEdge, winScreenInfo *pScreenInfo) +{ + APPBARDATA abd; + HWND hwndAutoHide; + + ZeroMemory (&abd, sizeof (abd)); + abd.cbSize = sizeof (abd); + abd.uEdge = uEdge; + + hwndAutoHide = (HWND) SHAppBarMessage (ABM_GETAUTOHIDEBAR, &abd); + if (hwndAutoHide != NULL) + { + /* + Found an autohide taskbar on that edge, but is it on the + same monitor as the screen window? + */ + if (pScreenInfo->fMultipleMonitors || (MonitorFromWindow(hwndAutoHide, MONITOR_DEFAULTTONULL) == pScreenInfo->hMonitor)) + return TRUE; + } + return FALSE; +} /* * Adjust the client area so that any auto-hide toolbars @@ -588,10 +625,9 @@ winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo) */ static Bool -winAdjustForAutoHide (RECT *prcWorkArea) +winAdjustForAutoHide (RECT *prcWorkArea, winScreenInfo *pScreenInfo) { APPBARDATA abd; - HWND hwndAutoHide; winDebug ("winAdjustForAutoHide - Original WorkArea: %d %d %d %d\n", (int) prcWorkArea->top, (int) prcWorkArea->left, @@ -603,37 +639,34 @@ winAdjustForAutoHide (RECT *prcWorkArea) if (SHAppBarMessage (ABM_GETSTATE, &abd) & ABS_AUTOHIDE) winDebug ("winAdjustForAutoHide - Taskbar is auto hide\n"); + /* + Despite the forgoing, we are checking for any AppBar + hiding along a monitor edge, not just the Windows TaskBar. + */ + /* Look for a TOP auto-hide taskbar */ - abd.uEdge = ABE_TOP; - hwndAutoHide = (HWND) SHAppBarMessage (ABM_GETAUTOHIDEBAR, &abd); - if (hwndAutoHide != NULL) + if (winTaskbarOnScreenEdge(ABE_TOP, pScreenInfo)) { winDebug ("winAdjustForAutoHide - Found TOP auto-hide taskbar\n"); prcWorkArea->top += 1; } /* Look for a LEFT auto-hide taskbar */ - abd.uEdge = ABE_LEFT; - hwndAutoHide = (HWND) SHAppBarMessage (ABM_GETAUTOHIDEBAR, &abd); - if (hwndAutoHide != NULL) + if (winTaskbarOnScreenEdge(ABE_LEFT, pScreenInfo)) { winDebug ("winAdjustForAutoHide - Found LEFT auto-hide taskbar\n"); prcWorkArea->left += 1; } /* Look for a BOTTOM auto-hide taskbar */ - abd.uEdge = ABE_BOTTOM; - hwndAutoHide = (HWND) SHAppBarMessage (ABM_GETAUTOHIDEBAR, &abd); - if (hwndAutoHide != NULL) + if (winTaskbarOnScreenEdge(ABE_BOTTOM, pScreenInfo)) { winDebug ("winAdjustForAutoHide - Found BOTTOM auto-hide taskbar\n"); prcWorkArea->bottom -= 1; } /* Look for a RIGHT auto-hide taskbar */ - abd.uEdge = ABE_RIGHT; - hwndAutoHide = (HWND) SHAppBarMessage (ABM_GETAUTOHIDEBAR, &abd); - if (hwndAutoHide != NULL) + if (winTaskbarOnScreenEdge(ABE_RIGHT, pScreenInfo)) { winDebug ("winAdjustForAutoHide - Found RIGHT auto-hide taskbar\n"); prcWorkArea->right -= 1; @@ -642,15 +675,6 @@ winAdjustForAutoHide (RECT *prcWorkArea) winDebug ("winAdjustForAutoHide - Adjusted WorkArea: %d %d %d %d\n", (int) prcWorkArea->top, (int) prcWorkArea->left, (int) prcWorkArea->bottom, (int) prcWorkArea->right); - -#if 0 - /* Obtain the task bar window dimensions */ - abd.hWnd = hwndAutoHide; - hwndAutoHide = (HWND) SHAppBarMessage (ABM_GETTASKBARPOS, &abd); - winDebug ("hwndAutoHide %08x abd.hWnd %08x %d %d %d %d\n", - hwndAutoHide, abd.hWnd, - abd.rc.top, abd.rc.left, abd.rc.bottom, abd.rc.right); -#endif return TRUE; } diff --git a/hw/xwin/windisplay.c b/hw/xwin/windisplay.c new file mode 100644 index 000000000..10ac8f220 --- /dev/null +++ b/hw/xwin/windisplay.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) Jon TURNEY 2009 + * + * 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. + * + */ + +#include <opaque.h> // for display +#include "win.h" + +/* + Generate a display name string referring to the display of this server, + using a transport we know is enabled +*/ + +void +winGetDisplayName(char *szDisplay, unsigned int screen) +{ + if (TransIsListening("local")) + { + snprintf(szDisplay, 512, ":%s.%d", display, screen); + } + else if (TransIsListening("inet")) + { + snprintf(szDisplay, 512, "127.0.0.1:%s.%d", display, screen); + } + else if (TransIsListening("inet6")) + { + snprintf(szDisplay, 512, "::1:%s.%d", display, screen); + } + else + { + // this can't happen! + ErrorF ("winGetDisplay: Don't know what to use for DISPLAY\n"); + snprintf(szDisplay, 512, "localhost:%s.%d", display, screen); + } + + winDebug("winGetDisplay: DISPLAY=%s\n", szDisplay); +} diff --git a/hw/xwin/winengine.c b/hw/xwin/winengine.c index bf5187bcd..5f706a6ed 100644 --- a/hw/xwin/winengine.c +++ b/hw/xwin/winengine.c @@ -96,7 +96,7 @@ winDetectSupportedEngines (void) else { /* We have DirectDraw */ - winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw installed\n"); + winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw installed, allowing ShadowDD\n"); g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD; #ifdef XWIN_PRIMARYFB @@ -104,11 +104,11 @@ winDetectSupportedEngines (void) if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { g_dwEnginesSupported |= WIN_SERVER_PRIMARY_DD; - winErrorFVerb (2, "winDetectSupportedEngines - Allowing PrimaryDD\n"); + winErrorFVerb (2, "winDetectSupportedEngines - Windows NT, allowing PrimaryDD\n"); } #endif } - + /* Try to query for DirectDraw4 interface */ ddrval = IDirectDraw_QueryInterface (lpdd, &IID_IDirectDraw4, @@ -116,7 +116,7 @@ winDetectSupportedEngines (void) if (SUCCEEDED (ddrval)) { /* We have DirectDraw4 */ - winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw4 installed\n"); + winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw4 installed, allowing ShadowDDNL\n"); g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL; } diff --git a/hw/xwin/winerror.c b/hw/xwin/winerror.c index 0440d13ff..ec3c2868f 100644 --- a/hw/xwin/winerror.c +++ b/hw/xwin/winerror.c @@ -35,6 +35,9 @@ #include <../xfree86/common/xorgVersion.h> #include "win.h" +/* Last error reported */ +static char lastError[1024] = ""; + #ifdef DDXOSVERRORF /* Prototype */ void @@ -52,6 +55,32 @@ OsVendorVErrorF (const char *pszFormat, va_list va_args) pthread_mutex_lock (&s_pmPrinting); #endif + /* If we want to silence it, + * detect if we are going to abort due to duplication error */ + if (g_fSilentDupError) + { + if ((strcmp(pszFormat, + "InitOutput - Duplicate invocation on display " + "number: %s. Exiting.\n") == 0) + || (strcmp(pszFormat, + "Server is already active for display %s\n%s %s\n%s\n") == 0) + || (strcmp(pszFormat, + "MakeAllCOTSServerListeners: server already running\n") == 0)) + { + g_fSilentFatalError = TRUE; + } + } + + /* Record the error, in case it's a fatal one... */ + if ((strcmp(pszFormat,"\n") != 0) && + (strcmp(pszFormat,"Server terminated %s (%d). Closing log file.\n") != 0)) + { + va_list va_args_copy; + va_copy(va_args_copy, va_args); + vsnprintf(lastError, sizeof(lastError), pszFormat, va_args_copy); + va_end(va_args_copy); + } + /* Print the error message to a log file, could be stderr */ LogVWrite (0, pszFormat, va_args); @@ -64,9 +93,12 @@ OsVendorVErrorF (const char *pszFormat, va_list va_args) /* - * 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. + * + * But the message for the fatal error is not passed to this + * function, so we stash the log string in lastError so we can + * also report it here * * Attempt to do last-ditch, safe, important cleanup here. */ @@ -83,10 +115,25 @@ OsVendorFatalError (void) } 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")); + /* + Sometimes the error message we capture in lastError + needs some cosmetic cleaning up for use in a dialog box... + */ + { + char *s; + while ((s = strstr(lastError, "\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, + lastError, + (g_pszLogFile ? g_pszLogFile : "the logfile")); } @@ -114,7 +161,7 @@ winMessageBoxF (const char *pszError, UINT uType, ...) #define MESSAGEBOXF \ "%s\n" \ "Vendor: %s\n" \ - "Release: %d.%d.%d.%d (%d)\n" \ + "Release: %d.%d.%d.%d\n" \ "Contact: %s\n" \ "%s\n\n" \ "XWin was started with the following command-line:\n\n" \ @@ -123,7 +170,7 @@ winMessageBoxF (const char *pszError, UINT uType, ...) size = asprintf (&pszMsgBox, MESSAGEBOXF, pszErrorF, XVENDORNAME, XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, - XORG_VERSION_SNAP, XORG_VERSION_CURRENT, + XORG_VERSION_SNAP, BUILDERADDR, BUILDERSTRING, g_pszCommandLine); diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c index 655cdb131..71cb283f3 100644 --- a/hw/xwin/winglobals.c +++ b/hw/xwin/winglobals.c @@ -76,8 +76,9 @@ Bool g_fKeyboardHookLL = FALSE; Bool g_fNoHelpMessageBox = FALSE; Bool g_fSoftwareCursor = FALSE; Bool g_fSilentDupError = FALSE; -Bool g_fNativeGl = FALSE; - +Bool g_fNativeGl = TRUE; +Bool g_fHostInTitle = FALSE; +pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER; #ifdef XWIN_CLIPBOARD /* diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h index 89926796c..fe647f70b 100644 --- a/hw/xwin/winglobals.h +++ b/hw/xwin/winglobals.h @@ -47,6 +47,7 @@ extern Bool g_fXdmcpEnabled; extern Bool g_fNoHelpMessageBox; extern Bool g_fSilentDupError; extern Bool g_fNativeGl; +extern Bool g_fHostInTitle; extern HWND g_hDlgDepthChange; extern HWND g_hDlgExit; @@ -85,4 +86,6 @@ extern Bool g_fButton[3]; extern Bool g_fNoConfigureWindow; #endif +extern pthread_mutex_t g_pmTerminating; + #endif /* WINGLOBALS_H */ diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c index 0496c40ab..f1add8912 100644 --- a/hw/xwin/winkeybd.c +++ b/hw/xwin/winkeybd.c @@ -41,6 +41,7 @@ #include "winmsg.h" #include "xkbsrv.h" +#include "dixgrabs.h" static Bool g_winKeyState[NUM_KEYCODES]; @@ -282,6 +283,29 @@ winRestoreModeKeyStates (void) * have a logical XOR operator, so we use a macro instead. */ + { + /* consider modifer keys */ + + 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 (WIN_XOR (internalKeyStates & ControlMask, ctrl)) + winSendKeyEvent (KEY_LCtrl, ctrl); + + if (WIN_XOR (internalKeyStates & ShiftMask, shift)) + winSendKeyEvent (KEY_ShiftL, shift); + + if (WIN_XOR (internalKeyStates & Mod1Mask, alt)) + winSendKeyEvent (KEY_Alt, alt); + + if (WIN_XOR (internalKeyStates & Mod5Mask, altgr)) + winSendKeyEvent (KEY_AltLang, altgr); + } + /* Has the key state changed? */ dwKeyState = GetKeyState (VK_NUMLOCK) & 0x0001; if (WIN_XOR (internalKeyStates & NumLockMask, dwKeyState)) @@ -539,3 +563,34 @@ void winFixShiftKeys (int iScanCode) if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL]) winSendKeyEvent (KEY_ShiftL, FALSE); } + +/* + */ +int +XkbDDXPrivate(DeviceIntPtr dev,KeyCode key,XkbAction *act) +{ + XkbAnyAction *xf86act = &(act->any); + char msgbuf[XkbAnyActionDataSize+1]; + + if (xf86act->type == XkbSA_XFree86Private) + { + memcpy(msgbuf, xf86act->data, XkbAnyActionDataSize); + msgbuf[XkbAnyActionDataSize]= '\0'; + if (strcasecmp(msgbuf, "prgrbs")==0) { + DeviceIntPtr tmp; + winMsg(X_INFO, "Printing all currently active device grabs:\n"); + for (tmp = inputInfo.devices; tmp; tmp = tmp->next) + if (tmp->deviceGrab.grab) + PrintDeviceGrabInfo(tmp); + winMsg(X_INFO, "End list of active device grabs\n"); + } + else if (strcasecmp(msgbuf, "ungrab")==0) + UngrabAllDevices(FALSE); + else if (strcasecmp(msgbuf, "clsgrb")==0) + UngrabAllDevices(TRUE); + else if (strcasecmp(msgbuf, "prwins")==0) + PrintWindowTree(); + } + + return 0; +} diff --git a/hw/xwin/winmonitors.c b/hw/xwin/winmonitors.c index 967ae6d35..5484209a9 100644 --- a/hw/xwin/winmonitors.c +++ b/hw/xwin/winmonitors.c @@ -48,6 +48,7 @@ wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _d data->monitorOffsetY = rect->top; data->monitorHeight = rect->bottom - rect->top; data->monitorWidth = rect->right - rect->left; + data->monitorHandle = hMonitor; return FALSE; } return TRUE; diff --git a/hw/xwin/winmonitors.h b/hw/xwin/winmonitors.h index 180566b00..9445e90b2 100644 --- a/hw/xwin/winmonitors.h +++ b/hw/xwin/winmonitors.h @@ -1,3 +1,31 @@ +/* + +Copyright 1993, 1998 The Open Group +Copyright (C) Colin Harrison 2005-2008 + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 OPEN GROUP 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 Open Group 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 Open Group. + +*/ /* data returned for monitor information */ struct GetMonitorInfoData { @@ -9,6 +37,7 @@ struct GetMonitorInfoData { int monitorOffsetY; int monitorHeight; int monitorWidth; + HMONITOR monitorHandle; }; Bool QueryMonitor(int index, struct GetMonitorInfoData *data); diff --git a/hw/xwin/winmsgwindow.c b/hw/xwin/winmsgwindow.c new file mode 100644 index 000000000..d8af1b5ff --- /dev/null +++ b/hw/xwin/winmsgwindow.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) Jon TURNEY 2011 + * + * 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. + * + */ + +#include "win.h" + +/* + * This is the messaging window, a hidden top-level window. We never do anything + * with it, but other programs may send messages to it. + */ + +/* + * winMsgWindowProc - Window procedure for msg window + */ + +static +LRESULT CALLBACK +winMsgWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ +#if CYGDEBUG + winDebugWin32Message("winMsgWindowProc", hwnd, message, wParam, lParam); +#endif + + switch (message) + { + case WM_ENDSESSION: + if (!wParam) + return 0; /* shutdown is being cancelled */ + + /* + Send a WM_GIVEUP message to the X server thread so it wakes up if + blocked in select(), performs GiveUp(), and then notices that GiveUp() + has set the DE_TERMINATE flag so exits the msg dispatch loop. + */ + { + ScreenPtr pScreen = screenInfo.screens[0]; + winScreenPriv(pScreen); + PostMessage(pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0); + } + + /* + This process will be terminated by the system almost immediately + after the last thread with a message queue returns from processing + WM_ENDSESSION, so we cannot rely on any code executing after this + message is processed and need to wait here until ddxGiveUp() is called + and releases the termination mutex to guarantee that the lock file and + unix domain sockets have been removed + + ofc, Microsoft doesn't document this under WM_ENDSESSION, you are supposed + to read the source of CRSS to find out how it works :-) + + http://blogs.msdn.com/b/michen/archive/2008/04/04/application-termination-when-user-logs-off.aspx + */ + { + int iReturn = pthread_mutex_lock (&g_pmTerminating); + if (iReturn != 0) + { + ErrorF ("winMsgWindowProc - pthread_mutex_lock () failed: %d\n", iReturn); + } + winDebug ("winMsgWindowProc - WM_ENDSESSION termination lock acquired\n"); + } + + return 0; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + +static HWND +winCreateMsgWindow(void) +{ + HWND hwndMsg; + wATOM winClass; + + // register window class + { + WNDCLASSEX wcx ; + wcx.cbSize=sizeof(WNDCLASSEX); + wcx.style = CS_HREDRAW | CS_VREDRAW; + wcx.lpfnWndProc = winMsgWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = g_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X_MSG; + wcx.hIconSm = NULL; + winClass = RegisterClassEx(&wcx); + } + + // Create the msg window. + hwndMsg = CreateWindowEx( + 0, // no extended styles + WINDOW_CLASS_X_MSG, // class name + "XWin Msg Window", // window name + WS_OVERLAPPEDWINDOW, // overlapped window + CW_USEDEFAULT, // default horizontal position + CW_USEDEFAULT, // default vertical position + CW_USEDEFAULT, // default width + CW_USEDEFAULT, // default height + (HWND) NULL, // no parent or owner window + (HMENU) NULL, // class menu used + GetModuleHandle (NULL), // instance handle + NULL); // no window creation data + + if (!hwndMsg) + { + ErrorF("winCreateMsgWindow - Create msg window failed\n"); + return NULL; + } + + winDebug("winCreateMsgWindow - Created msg window hwnd 0x%x\n", hwndMsg); + + return hwndMsg; +} + +static void * +winMsgWindowThreadProc(void *arg) +{ + HWND hwndMsg; + + winDebug ("winMsgWindowThreadProc - Hello\n"); + + hwndMsg = winCreateMsgWindow(); + if (hwndMsg) + { + MSG msg; + + /* Pump the msg window message queue */ + while (GetMessage (&msg, hwndMsg, 0, 0) > 0) + { +#if CYGDEBUG + winDebugWin32Message("winMsgWindowThread", msg.hwnd, msg.message, msg.wParam, msg.lParam); +#endif + DispatchMessage (&msg); + } + } + + winDebug ("winMsgWindowThreadProc - Exit\n"); + + return NULL; +} + +Bool +winCreateMsgWindowThread(void) +{ + pthread_t ptMsgWindowThreadProc; + + /* Spawn a thread for the msg window */ + if (pthread_create (&ptMsgWindowThreadProc, + NULL, + winMsgWindowThreadProc, + NULL)) + { + /* Bail if thread creation failed */ + ErrorF ("winCreateMsgWindow - pthread_create failed.\n"); + return FALSE; + } + + return TRUE; +} diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index aabde6b4a..3635931b2 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -55,10 +55,27 @@ winUpdateWindowsWindow (WindowPtr pWin); static void winFindWindow (pointer value, XID id, pointer cdata); +static Bool +isToplevelWindow(WindowPtr pWin) +{ + assert(pWin->parent); /* root window isn't expected here */ + + /* If the immediate parent is the root window, this is a top-level window */ + if ((pWin->parent) && (pWin->parent->parent == NULL)) + { + assert(pWin->parent == pWin->drawable.pScreen->root); + return TRUE; + } + + /* otherwise, a child window */ + return FALSE; +} + static void winInitMultiWindowClass(void) { static wATOM atomXWinClass=0; + static wATOM atomXWinChildClass = 0; WNDCLASSEX wcx; if (atomXWinClass==0) @@ -78,11 +95,34 @@ void winInitMultiWindowClass(void) wcx.hIconSm = g_hSmallIconX; #if CYGMULTIWINDOW_DEBUG - ErrorF ("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X); + ErrorF ("winInitMultiWindowClass - Creating class: %s\n", WINDOW_CLASS_X); #endif atomXWinClass = RegisterClassEx (&wcx); } + + if (atomXWinChildClass==0) + { + /* Setup our window class */ + wcx.cbSize=sizeof(WNDCLASSEX); + wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0); + wcx.lpfnWndProc = winChildWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = g_hInstance; + wcx.hIcon = g_hIconX; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X_CHILD; + wcx.hIconSm = g_hSmallIconX; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winInitMultiWindowClass - Creating class: %s\n", WINDOW_CLASS_X_CHILD); +#endif + + atomXWinChildClass = RegisterClassEx (&wcx); + } } /* @@ -197,6 +237,30 @@ winPositionWindowMultiWindow (WindowPtr pWin, int x, int y) return fResult; } + if (!isToplevelWindow(pWin)) + { + POINT parentOrigin; + + /* Get the X and Y location of the X window */ + iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN); + iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN); + + /* Get the height and width of the X window */ + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* Convert screen coordinates into client area co-ordinates of the parent */ + parentOrigin.x = 0; + parentOrigin.y = 0; + ClientToScreen(GetParent(hWnd), &parentOrigin); + + MoveWindow (hWnd, + iX - parentOrigin.x, iY - parentOrigin.y, iWidth, iHeight, + TRUE); + + return fResult; + } + /* Get the Windows window style and extended style */ dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE); dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE); @@ -476,13 +540,8 @@ winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib) #endif } - -/* - * winCreateWindowsWindow - Create a Windows window associated with an X window - */ - -void -winCreateWindowsWindow (WindowPtr pWin) +static void +winCreateWindowsTopLevelWindow (WindowPtr pWin) { int iX, iY; int iWidth; @@ -519,7 +578,7 @@ winCreateWindowsWindow (WindowPtr pWin) iY = CW_USEDEFAULT; } - winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); if (winMultiWindowGetTransientFor (pWin, &pDaddy)) { @@ -542,7 +601,10 @@ winCreateWindowsWindow (WindowPtr pWin) } } - /* Make it WS_OVERLAPPED in create call since WS_POPUP doesn't support */ + winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + + /* Create the window */ + /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */ /* CW_USEDEFAULT, change back to popup after creation */ dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; dwExStyle = WS_EX_TOOLWINDOW; @@ -578,11 +640,13 @@ winCreateWindowsWindow (WindowPtr pWin) pWin); /* ScreenPrivates */ if (hWnd == NULL) { - ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", + ErrorF ("winCreateWindowsTopLevelWindow - CreateWindowExA () failed: %d\n", (int) GetLastError ()); } pWinPriv->hWnd = hWnd; + winDebug("winCreateWindowsTopLevelWindow - hwnd 0x%08x\n", hWnd); + /* Set application or .XWinrc defined Icons */ winSelectIcons(pWin, &hIcon, &hIconSmall); if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); @@ -611,6 +675,104 @@ winCreateWindowsWindow (WindowPtr pWin) (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin); } +static void +winCreateWindowsChildWindow(WindowPtr pWin) +{ + int iX, iY, iWidth, iHeight; + HWND hWnd; + WindowPtr pParent = pWin->parent; + DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED; + DWORD dwExStyle = WS_EX_TRANSPARENT; + /* + WS_DISABLED means child window never gains the input focus, so only the + top-level window needs deal with passing input to the X server + + WS_EX_TRANSPARENT ensures that the contents of the top-level + Windows window (which will contain all non-OpenGL drawing for the hierarchy) + can be seen through any intermediate child windows which have nothing + drawn to them + */ + winPrivWinPtr pParentPriv, pWinPriv; + + winDebug("winCreateWindowsChildWindow - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); + + winInitMultiWindowClass(); + + assert(pParent); + + pParentPriv = winGetWindowPriv(pParent); + pWinPriv = winGetWindowPriv(pWin); + + iX = pWin->drawable.x - pParent->drawable.x; + iY = pWin->drawable.y - pParent->drawable.y; + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + winDebug("winCreateWindowsChildWindow - parent pWin:%08x XID:0x%08x hWnd:0x%08x\n", pParent, pParent->drawable.id, pParentPriv->hWnd); + winDebug("winCreateWindowsChildWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + + /* Create the window */ + hWnd = CreateWindowExA (dwExStyle, /* Extended styles */ + WINDOW_CLASS_X_CHILD, /* Class name */ + WINDOW_TITLE_X, /* Window name */ + dwStyle, /* Styles */ + iX, /* Horizontal position */ + iY, /* Vertical position */ + iWidth, /* Right edge */ + iHeight, /* Bottom edge */ + pParentPriv->hWnd, /* parent window */ + (HMENU) NULL, /* No menu */ + GetModuleHandle(NULL),/* Instance handle */ + pWin); /* ScreenPrivates */ + if (hWnd == NULL) + { + ErrorF ("winCreateWindowsChildWindow - CreateWindowExA () failed: %d\n", + (int) GetLastError ()); + } + winDebug("winCreateWindowsChildWindow - hwnd 0x%08x\n", hWnd); + pWinPriv->hWnd = hWnd; + + SetProp(hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin)); +} + +/* + * winCreateWindowsWindow - Create a Windows window associated with an X window + */ + +void +winCreateWindowsWindow (WindowPtr pWin) +{ + winDebug("winCreateWindowsWindow - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); + + if (isToplevelWindow(pWin)) + { + winCreateWindowsTopLevelWindow(pWin); + } + else + { + winCreateWindowsChildWindow(pWin); + } +} + +static int +winDestroyChildWindowsWindow(WindowPtr pWin, pointer data) +{ + winWindowPriv(pWin); + + winDebug("winDestroyChildWindowsWindow - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); + + SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, NULL); + + /* Null our handle to the Window so referencing it will cause an error */ + pWinPriv->hWnd = NULL; + +#ifdef XWIN_GLX_WINDOWS + /* No longer note WGL used on this window */ + pWinPriv->fWglUsed = FALSE; +#endif + + return WT_WALKCHILDREN; /* continue enumeration */ +} Bool winInDestroyWindowsWindow = FALSE; /* @@ -625,6 +787,7 @@ winDestroyWindowsWindow (WindowPtr pWin) BOOL oldstate = winInDestroyWindowsWindow; HICON hIcon; HICON hIconSm; + HWND hWnd; winDebug("winDestroyWindowsWindow - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); @@ -638,21 +801,20 @@ winDestroyWindowsWindow (WindowPtr pWin) hIcon = (HICON)SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_BIG, 0); hIconSm = (HICON)SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0); - /* Destroy the Windows window */ - DestroyWindow (pWinPriv->hWnd); + hWnd = pWinPriv->hWnd; - /* Null our handle to the Window so referencing it will cause an error */ - pWinPriv->hWnd = NULL; + /* DestroyWindow() implicitly destroys all child windows, + so first walk over the child tree of this window, clearing + any hWnds */ + TraverseTree(pWin, winDestroyChildWindowsWindow, 0); + + /* Destroy the Windows window */ + DestroyWindow (hWnd); /* Destroy any icons we created for this window */ winDestroyIcon(hIcon); winDestroyIcon(hIconSm); -#ifdef XWIN_GLX_WINDOWS - /* No longer note WGL used on this window */ - pWinPriv->fWglUsed = FALSE; -#endif - /* Process all messages on our queue */ while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { @@ -677,36 +839,64 @@ static void winUpdateWindowsWindow (WindowPtr pWin) { winWindowPriv(pWin); - HWND hWnd = pWinPriv->hWnd; #if CYGMULTIWINDOW_DEBUG ErrorF ("winUpdateWindowsWindow\n"); #endif - /* Check if the Windows window's parents have been destroyed */ - if (pWin->parent != NULL - && pWin->parent->parent == NULL - && pWin->mapped) - { - /* Create the Windows window if it has been destroyed */ - if (hWnd == NULL) - { - winCreateWindowsWindow (pWin); - assert (pWinPriv->hWnd != NULL); - } - /* Display the window without activating it */ - if (pWin->drawable.class != InputOnly) - ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + /* Ignore the root window */ + if (pWin->parent == NULL) + return; - /* Send first paint message */ - UpdateWindow (pWinPriv->hWnd); + /* If it's mapped */ + if (pWin->mapped) + { + /* If it's a top-level window */ + if (isToplevelWindow(pWin)) + { + /* Create the Windows window if needed */ + if (pWinPriv->hWnd == NULL) + { + winCreateWindowsWindow (pWin); + assert (pWinPriv->hWnd != NULL); + } + + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + } + /* It's not a top-level window, but we created a window for GLX */ + else if (pWinPriv->hWnd) + { + winPrivWinPtr pParentPriv = winGetWindowPriv(pWin->parent); + + /* XXX: This really belongs in winReparentWindow ??? */ + /* XXX: this assumes parent window has been made to exist */ + assert(pParentPriv->hWnd); + + /* Ensure we have the correct parent and position if reparented */ + SetParent(pWinPriv->hWnd, pParentPriv->hWnd); + SetWindowPos(pWinPriv->hWnd, NULL, pWin->drawable.x - pWin->parent->drawable.x, pWin->drawable.y - pWin->parent->drawable.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); + } + + /* If it's top level, or a GLX window which has already been created getting mapped, show it */ + if (pWinPriv->hWnd != NULL) + { + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + /* Send first paint message */ + UpdateWindow (pWinPriv->hWnd); + } } - else if (hWnd != NULL) + else if (pWinPriv->hWnd != NULL) { - /* Destroy the Windows window if its parents are destroyed */ + /* If it's been reparented to an unmapped window when previously mapped, destroy the Windows window */ winDestroyWindowsWindow (pWin); - assert (pWinPriv->hWnd == NULL); + assert(pWinPriv->hWnd == NULL); } #if CYGMULTIWINDOW_DEBUG @@ -954,6 +1144,14 @@ winAdjustXWindow (WindowPtr pWin, HWND hwnd) ErrorF ("winAdjustXWindow\n"); #endif + if (!isToplevelWindow(pWin)) + { +#if 1 + ErrorF ("winAdjustXWindow - immediately return because not a top-level window\n"); +#endif + return 0; + } + if (IsIconic (hwnd)) { #if CYGWINDOWING_DEBUG diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 70f53854c..abe35efb5 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -48,7 +48,6 @@ #include <X11/X.h> #include <X11/Xatom.h> #include <X11/Xlib.h> -#include <X11/Xlocale.h> #include <X11/Xproto.h> #include <X11/Xutil.h> #include <X11/cursorfont.h> @@ -62,6 +61,14 @@ #include "window.h" #include "pixmapstr.h" #include "windowstr.h" +#include "winglobals.h" + +#include <shlwapi.h> + +#define INITGUID +#include "initguid.h" +#include "taskbar.h" +#undef INITGUID #ifdef XWIN_MULTIWINDOWEXTWM #include <X11/extensions/windowswmstr.h> @@ -136,7 +143,6 @@ typedef struct _XMsgProcArgRec { * References to external symbols */ -extern char *display; extern void ErrorF (const char* /*f*/, ...); /* @@ -153,7 +159,7 @@ static Bool InitQueue (WMMsgQueuePtr pQueue); static void -GetWindowName (Display * pDpy, Window iWin, wchar_t **ppName); +GetWindowName (Display * pDpy, Window iWin, char **ppWindowName); static int SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData); @@ -179,6 +185,9 @@ winMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr); static int winMultiWindowXMsgProcIOErrorHandler (Display *pDisplay); +static void +winMultiWindowThreadExit(void *arg); + static int winRedirectErrorHandler (Display *pDisplay, XErrorEvent *pErr); @@ -212,6 +221,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 @@ -395,49 +408,78 @@ InitQueue (WMMsgQueuePtr pQueue) pQueue->nQueueSize = 0; #if CYGMULTIWINDOW_DEBUG - ErrorF ("InitQueue - Queue Size %d %d\n", pQueue->nQueueSize, - QueueSize(pQueue)); + winDebug ("InitQueue - Queue Size %d %d\n", pQueue->nQueueSize, QueueSize(pQueue)); #endif - ErrorF ("InitQueue - Calling pthread_mutex_init\n"); + winDebug ("InitQueue - Calling pthread_mutex_init\n"); /* Create synchronization objects */ pthread_mutex_init (&pQueue->pmMutex, NULL); - ErrorF ("InitQueue - pthread_mutex_init returned\n"); - ErrorF ("InitQueue - Calling pthread_cond_init\n"); + winDebug ("InitQueue - pthread_mutex_init returned\n"); + winDebug ("InitQueue - Calling pthread_cond_init\n"); pthread_cond_init (&pQueue->pcNotEmpty, NULL); - ErrorF ("InitQueue - pthread_cond_init returned\n"); + winDebug ("InitQueue - pthread_cond_init returned\n"); return TRUE; } +static +char *Xutf8TextPropertyToString(Display *pDisplay, XTextProperty *xtp) +{ + int nNum; + char **ppList; + char *pszReturnData; + + if (Xutf8TextPropertyToTextList (pDisplay, xtp, &ppList, &nNum) >= Success && nNum > 0 && *ppList) + { + int i; + int iLen = 0; + + for (i = 0; i < nNum; i++) + iLen += strlen(ppList[i]); + pszReturnData = (char *) malloc (iLen + 1); + pszReturnData[0] = '\0'; + for (i = 0; i < nNum; i++) + strcat (pszReturnData, ppList[i]); + if (ppList) + XFreeStringList (ppList); + } + else + { + pszReturnData = (char *) malloc (1); + pszReturnData[0] = '\0'; + } + + return pszReturnData; +} /* * GetWindowName - Retrieve the title of an X Window */ static void -GetWindowName (Display *pDisplay, Window iWin, wchar_t **ppName) +GetWindowName (Display *pDisplay, Window iWin, char **ppWindowName) { - int nResult, nNum; - char **ppList; - char *pszReturnData; - int iLen, i; - XTextProperty xtpName; - + int nResult; + XTextProperty xtpWindowName; + XTextProperty xtpClientMachine; + char *pszWindowName; + char *pszClientMachine; + char hostname[HOST_NAME_MAX + 1]; + #if CYGMULTIWINDOW_DEBUG ErrorF ("GetWindowName\n"); #endif - /* Intialize ppName to NULL */ - *ppName = NULL; + /* Intialize ppWindowName to NULL */ + *ppWindowName = NULL; - /* Try to get --- */ - nResult = XGetWMName (pDisplay, iWin, &xtpName); - if (!nResult || !xtpName.value || !xtpName.nitems) + /* Try to get window name */ + nResult = XGetWMName (pDisplay, iWin, &xtpWindowName); + if (!nResult || !xtpWindowName.value || !xtpWindowName.nitems) { #if CYGMULTIWINDOW_DEBUG ErrorF ("GetWindowName - XGetWMName failed. No name.\n"); @@ -445,29 +487,43 @@ GetWindowName (Display *pDisplay, Window iWin, wchar_t **ppName) return; } - if (Xutf8TextPropertyToTextList (pDisplay, &xtpName, &ppList, &nNum) >= Success && nNum > 0 && *ppList) - { - iLen = 0; - for (i = 0; i < nNum; i++) iLen += strlen(ppList[i]); - pszReturnData = (char *) malloc (iLen + 1); - pszReturnData[0] = '\0'; - for (i = 0; i < nNum; i++) strcat (pszReturnData, ppList[i]); - if (ppList) XFreeStringList (ppList); - } - else - { - pszReturnData = (char *) malloc (1); - pszReturnData[0] = '\0'; - } - iLen = MultiByteToWideChar (CP_UTF8, 0, pszReturnData, -1, NULL, 0); - *ppName = (wchar_t*)malloc(sizeof(wchar_t)*(iLen + 1)); - MultiByteToWideChar (CP_UTF8, 0, pszReturnData, -1, *ppName, iLen); - XFree (xtpName.value); - free (pszReturnData); + pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName); + XFree(xtpWindowName.value); -#if CYGMULTIWINDOW_DEBUG - ErrorF ("GetWindowName - Returning\n"); -#endif + if (g_fHostInTitle) + { + /* Try to get client machine name */ + nResult = XGetWMClientMachine(pDisplay, iWin, &xtpClientMachine); + if (nResult && xtpClientMachine.value && xtpClientMachine.nitems) + { + pszClientMachine = Xutf8TextPropertyToString(pDisplay, &xtpClientMachine); + XFree(xtpClientMachine.value); + + /* + If we have a client machine name + and it's not the local host name... + */ + if (strlen(pszClientMachine) && + !gethostname(hostname, HOST_NAME_MAX + 1) && + strcmp (hostname, pszClientMachine)) + { + /* ... add ' (on <clientmachine>)' to end of window name */ + *ppWindowName = malloc(strlen(pszWindowName) + strlen(pszClientMachine) + 7); + strcpy(*ppWindowName, pszWindowName); + strcat(*ppWindowName, " (on "); + strcat(*ppWindowName, pszClientMachine); + strcat(*ppWindowName, ")"); + + free(pszWindowName); + free(pszClientMachine); + + return; + } + } + } + + /* otherwise just return the window name */ + *ppWindowName = pszWindowName; } @@ -500,7 +556,6 @@ SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData) static void UpdateName (WMInfoPtr pWMInfo, Window iWindow) { - wchar_t *pszName; Atom atmType; int fmtRet; unsigned long items, remain; @@ -529,26 +584,33 @@ UpdateName (WMInfoPtr pWMInfo, Window iWindow) XFree (retHwnd); } } - + /* Some sanity checks */ if (!hWnd) return; if (!IsWindow (hWnd)) return; - /* Set the Windows window name */ - GetWindowName (pWMInfo->pDisplay, iWindow, &pszName); - if (pszName) + /* If window isn't override-redirect */ + XGetWindowAttributes (pWMInfo->pDisplay, iWindow, &attr); + if (!attr.override_redirect) { - /* Get the window attributes */ - XGetWindowAttributes (pWMInfo->pDisplay, - iWindow, - &attr); - if (!attr.override_redirect) - { - SetWindowTextW (hWnd, pszName); - winUpdateIcon (iWindow); - } + char *pszWindowName; + /* Get the X windows window name */ + GetWindowName (pWMInfo->pDisplay, iWindow, &pszWindowName); + + if (pszWindowName) + { + /* Convert from UTF-8 to wide char */ + int iLen = MultiByteToWideChar (CP_UTF8, 0, pszWindowName, -1, NULL, 0); + wchar_t *pwszWideWindowName = (wchar_t*)malloc(sizeof(wchar_t)*(iLen + 1)); + MultiByteToWideChar (CP_UTF8, 0, pszWindowName, -1, pwszWideWindowName, iLen); - free (pszName); + /* Set the Windows window name */ + SetWindowTextW (hWnd, pwszWideWindowName); + winUpdateIcon (iWindow); + + free (pwszWideWindowName); + free (pszWindowName); + } } } @@ -630,6 +692,8 @@ winMultiWindowWMProc (void *pArg) { WMProcArgPtr pProcArg = (WMProcArgPtr)pArg; WMInfoPtr pWMInfo = pProcArg->pWMInfo; + + pthread_cleanup_push(&winMultiWindowThreadExit, NULL); /* Initialize the Window Manager */ winInitMultiWindowWM (pWMInfo, pProcArg); @@ -842,6 +906,9 @@ winMultiWindowWMProc (void *pArg) #if CYGMULTIWINDOW_DEBUG ErrorF("-winMultiWindowWMProc ()\n"); #endif + + pthread_cleanup_pop(0); + return NULL; } @@ -864,7 +931,9 @@ winMultiWindowXMsgProc (void *pArg) int iReturn; XIconSize *xis; - ErrorF ("winMultiWindowXMsgProc - Hello\n"); + pthread_cleanup_push(&winMultiWindowThreadExit, NULL); + + winDebug ("winMultiWindowXMsgProc - Hello\n"); /* Check that argument pointer is not invalid */ if (pProcArg == NULL) @@ -887,19 +956,6 @@ winMultiWindowXMsgProc (void *pArg) ErrorF ("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n"); - /* Allow multiple threads to access Xlib */ - if (XInitThreads () == 0) - { - ErrorF ("winMultiWindowXMsgProc - XInitThreads () failed. Exiting.\n"); - pthread_exit (NULL); - } - - /* See if X supports the current locale */ - if (XSupportsLocale () == False) - { - ErrorF ("winMultiWindowXMsgProc - Warning: locale not supported by X\n"); - } - /* Release the server started mutex */ pthread_mutex_unlock (pProcArg->ppmServerStarted); @@ -929,8 +985,7 @@ winMultiWindowXMsgProc (void *pArg) } /* Setup the display connection string x */ - snprintf (pszDisplay, - 512, "127.0.0.1:%s.%d", display, (int)pProcArg->dwScreen); + winGetDisplayName(pszDisplay, (int)pProcArg->dwScreen); /* Print the display connection string */ ErrorF ("winMultiWindowXMsgProc - DISPLAY=%s\n", pszDisplay); @@ -1181,7 +1236,7 @@ winMultiWindowXMsgProc (void *pArg) } XCloseDisplay (pProcArg->pDisplay); - pthread_exit (NULL); + pthread_cleanup_pop(0); return NULL; } @@ -1274,7 +1329,7 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) char pszDisplay[512]; int iReturn; - ErrorF ("winInitMultiWindowWM - Hello\n"); + winDebug ("winInitMultiWindowWM - Hello\n"); /* Check that argument pointer is not invalid */ if (pProcArg == NULL) @@ -1297,19 +1352,6 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () returned.\n"); - /* Allow multiple threads to access Xlib */ - if (XInitThreads () == 0) - { - ErrorF ("winInitMultiWindowWM - XInitThreads () failed. Exiting.\n"); - pthread_exit (NULL); - } - - /* See if X supports the current locale */ - if (XSupportsLocale () == False) - { - ErrorF ("winInitMultiWindowWM - Warning: Locale not supported by X.\n"); - } - /* Release the server started mutex */ pthread_mutex_unlock (pProcArg->ppmServerStarted); @@ -1339,11 +1381,7 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) } /* Setup the display connection string x */ - snprintf (pszDisplay, - 512, - "127.0.0.1:%s.%d", - display, - (int) pProcArg->dwScreen); + winGetDisplayName(pszDisplay, (int)pProcArg->dwScreen); /* Print the display connection string */ ErrorF ("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay); @@ -1522,6 +1560,16 @@ winMultiWindowXMsgProcIOErrorHandler (Display *pDisplay) return 0; } +/* + * winMultiWindowThreadExit - Thread exit handler + */ + +static void +winMultiWindowThreadExit(void *arg) +{ + /* multiwindow client thread has exited, stop server as well */ + kill(getpid(), SIGTERM); +} /* * Catch RedirectError to detect other window manager running @@ -1699,10 +1747,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)) { @@ -1710,8 +1762,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 @@ -1823,3 +1888,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 19dad579c..3c0fc34cc 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -321,6 +321,7 @@ winTopLevelWindowProc (HWND hwnd, UINT message, static Bool s_fTracking = FALSE; Bool needRestack = FALSE; LRESULT ret; + static Bool hasEnteredSizeMove = FALSE; #if CYGDEBUG winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam, lParam); @@ -834,6 +835,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) { @@ -870,7 +874,8 @@ winTopLevelWindowProc (HWND hwnd, UINT message, case WM_MOVE: /* Adjust the X Window to the moved Windows window */ - winAdjustXWindow (pWin, hwnd); + if (!hasEnteredSizeMove) winAdjustXWindow (pWin, hwnd); + /* else: Wait for WM_EXITSIZEMOVE */ return 0; case WM_SHOWWINDOW: @@ -1011,6 +1016,16 @@ winTopLevelWindowProc (HWND hwnd, UINT message, */ break; + case WM_ENTERSIZEMOVE: + hasEnteredSizeMove = TRUE; + return 0; + + case WM_EXITSIZEMOVE: + /* Adjust the X Window to the moved Windows window */ + hasEnteredSizeMove = FALSE; + winAdjustXWindow (pWin, hwnd); + return 0; + case WM_SIZE: /* see dix/window.c */ #if CYGWINDOWING_DEBUG @@ -1035,8 +1050,13 @@ winTopLevelWindowProc (HWND hwnd, UINT message, (int)(GetTickCount ())); } #endif - /* Adjust the X Window to the moved Windows window */ - winAdjustXWindow (pWin, hwnd); + if (!hasEnteredSizeMove) + { + /* Adjust the X Window to the moved Windows window */ + winAdjustXWindow (pWin, hwnd); + if (wParam == SIZE_MINIMIZED) winReorderWindowsMultiWindow(); + } + /* else: wait for WM_EXITSIZEMOVE */ return 0; /* end of WM_SIZE handler */ case WM_STYLECHANGING: @@ -1133,3 +1153,42 @@ winTopLevelWindowProc (HWND hwnd, UINT message, winReorderWindowsMultiWindow(); return ret; } + +/* + * winChildWindowProc - Window procedure for all top-level Windows windows. + */ + +LRESULT CALLBACK +winChildWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ +#if CYGDEBUG + winDebugWin32Message("winChildWindowProc", hwnd, message, wParam, lParam); +#endif + + switch (message) + { + case WM_ERASEBKGND: + return TRUE; + + case WM_PAINT: + /* + We don't have the bits to draw into the window, they went straight into the OpenGL + surface + + XXX: For now, just leave it alone, but ideally we want to send an expose event to + the window so it really redraws the affected region... + */ + { + PAINTSTRUCT ps; + HDC hdcUpdate; + hdcUpdate = BeginPaint(hwnd, &ps); + ValidateRect(hwnd, &(ps.rcPaint)); + EndPaint(hwnd, &ps); + return 0; + } + /* XXX: this is exactly what DefWindowProc does? */ + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c index 76c30e9e3..7750e7c94 100644 --- a/hw/xwin/winprefs.c +++ b/hw/xwin/winprefs.c @@ -58,10 +58,6 @@ extern int parse_file (FILE *fp); /* Currently in use command ID, incremented each new menu item created */ static int g_cmdid = STARTMENUID; - -/* Defined in DIX */ -extern char *display; - /* Local function to handle comma-ified icon names */ static HICON LoadImageComma (char *fname, int sx, int sy, int flags); @@ -726,6 +722,10 @@ winPrefsLoadPreferences (char *path) "MENU rmenu {\n" " \"How to customize this menu\" EXEC \"xterm +tb -e man XWinrc\"\n" " \"Launch xterm\" EXEC xterm\n" + " SEPARATOR\n" + " FAQ EXEC \"cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html\"\n" + " \"User's Guide\" EXEC \"cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html\"\n" + " SEPARATOR\n" " \"Load .XWinrc\" RELOAD\n" " SEPARATOR\n" "}\n" @@ -809,16 +809,18 @@ LoadPreferences (void) /* Setup a DISPLAY environment variable, need to allocate on heap */ /* because putenv doesn't copy the argument... */ - snprintf (szDisplay, 512, "DISPLAY=127.0.0.1:%s.0", display); - szEnvDisplay = (char *)(malloc (strlen(szDisplay)+1)); + winGetDisplayName(szDisplay, 0); + szEnvDisplay = (char *)(malloc(strlen(szDisplay)+strlen("DISPLAY=")+1)); if (szEnvDisplay) { - strcpy (szEnvDisplay, szDisplay); + snprintf(szEnvDisplay, 512, "DISPLAY=%s", szDisplay); putenv (szEnvDisplay); } + /* Setup XWINLOGFILE environment variable */ + setenv("XWINLOGFILE", g_pszLogFile, TRUE); + /* Replace any "%display%" in menu commands with display string */ - snprintf (szDisplay, 512, "127.0.0.1:%s.0", display); for (i=0; i<pref.menuItems; i++) { for (j=0; j<pref.menu[i].menuItems; j++) diff --git a/hw/xwin/winprocarg.c b/hw/xwin/winprocarg.c index 9bec84141..674aa03db 100644 --- a/hw/xwin/winprocarg.c +++ b/hw/xwin/winprocarg.c @@ -111,6 +111,7 @@ winInitializeScreenDefaults(void) } defaultScreenInfo.iMonitor = 1; + defaultScreenInfo.hMonitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); defaultScreenInfo.dwWidth = dwWidth; defaultScreenInfo.dwHeight = dwHeight; defaultScreenInfo.dwUserWidth = dwWidth; @@ -139,7 +140,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; @@ -154,7 +155,7 @@ winInitializeScreenDefaults(void) static void winInitializeScreen(int i) { - winErrorFVerb (2, "winInitializeScreen - %d\n",i); + winErrorFVerb (3, "winInitializeScreen - %d\n",i); /* Initialize default screen values, if needed */ winInitializeScreenDefaults(); @@ -170,7 +171,7 @@ void winInitializeScreens(int maxscreens) { int i; - winErrorFVerb (2, "winInitializeScreens - %i\n", maxscreens); + winErrorFVerb (3, "winInitializeScreens - %i\n", maxscreens); if (maxscreens > g_iNumScreens) { @@ -334,6 +335,7 @@ ddxProcessArgument (int argc, char *argv[], int i) g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE; g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE; g_ScreenInfo[nScreenNum].iMonitor = iMonitor; + g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle; g_ScreenInfo[nScreenNum].dwWidth = data.monitorWidth; g_ScreenInfo[nScreenNum].dwHeight = data.monitorHeight; g_ScreenInfo[nScreenNum].dwUserWidth = data.monitorWidth; @@ -386,6 +388,7 @@ ddxProcessArgument (int argc, char *argv[], int i) } else if (data.bMonitorSpecifiedExists == TRUE) { g_ScreenInfo[nScreenNum].iMonitor = iMonitor; + g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle; g_ScreenInfo[nScreenNum].dwInitialX += data.monitorOffsetX; g_ScreenInfo[nScreenNum].dwInitialY += data.monitorOffsetY; } @@ -415,6 +418,7 @@ ddxProcessArgument (int argc, char *argv[], int i) winErrorFVerb (2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor); g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE; g_ScreenInfo[nScreenNum].iMonitor = iMonitor; + g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle; g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX; g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY; } @@ -1143,6 +1147,12 @@ ddxProcessArgument (int argc, char *argv[], int i) return 1; } + if (IS_OPTION("-hostintitle")) + { + g_fHostInTitle = TRUE; + return 1; + } + return 0; } @@ -1218,6 +1228,107 @@ winLogCommandLine (int argc, char *argv[]) "%s\n\n", g_pszCommandLine); } +/* + * Detect the OS + */ + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +static void +winOS(void) +{ + OSVERSIONINFOEX osvi = {0}; + char *windowstype = "Unknown"; + char *prodName = "Unknown"; + char *isWow = "Unknown"; + LPFN_ISWOW64PROCESS fnIsWow64Process; + + /* Get operating system version information */ + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx((LPOSVERSIONINFO)&osvi); + + /* Branch on platform ID */ + switch (osvi.dwPlatformId) + { + case VER_PLATFORM_WIN32_NT: + windowstype = "Windows NT"; + + if (osvi.dwMajorVersion <= 4) + prodName = "Windows NT"; + else if (osvi.dwMajorVersion == 6) + { + if (osvi.dwMinorVersion == 2) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 8"; + else + prodName = "Windows Server 2012"; + } + else if (osvi.dwMinorVersion == 1) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 7"; + else + prodName = "Windows Server 2008 R2"; + } + else if (osvi.dwMinorVersion == 0) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows Vista"; + else + prodName = "Windows Server 2008"; + } + } else if (osvi.dwMajorVersion == 5) + { + if (osvi.dwMinorVersion == 2) + { + if (GetSystemMetrics(SM_SERVERR2)) + prodName = "Windows Server 2003 R2"; + else + prodName = "Windows Server 2003"; + } + else if (osvi.dwMinorVersion == 1) + prodName = "Windows XP"; + else if (osvi.dwMinorVersion == 0) + { + prodName = "Windows 2000"; + break; + } + } + + break; + + case VER_PLATFORM_WIN32_WINDOWS: + windowstype = "Windows"; + break; + } + + /* Check if we are running under WoW64 */ + fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"),"IsWow64Process"); + if (NULL != fnIsWow64Process) + { + wBOOL bIsWow64 = FALSE; + if (fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) + { + isWow = bIsWow64 ? " (WoW64)" : " (Win32)"; + } + else + { + /* IsWow64Process() failed */ + isWow = " (WoWUnknown)"; + } + } + else + { + /* OS doesn't support IsWow64Process() */ + isWow = ""; + } + + ErrorF("OS: %s %s [%s %ld.%ld build %ld]%s\n", + prodName, osvi.szCSDVersion, + windowstype, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, + isWow); +} /* * winLogVersionInfo - Log version information @@ -1234,7 +1345,8 @@ winLogVersionInfo (void) ErrorF ("Welcome to the XWin X Server\n"); ErrorF ("Vendor: %s\n", XVENDORNAME); - ErrorF ("Release: %d.%d.%d.%d (%d)\n", XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP, XORG_VERSION_CURRENT); - ErrorF ("%s\n\n", BUILDERSTRING); - ErrorF ("Contact: %s\n", BUILDERADDR); + ErrorF ("Release: %d.%d.%d.%d\n", XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP); + winOS(); + if (strlen(BUILDERSTRING)) ErrorF ("%s\n", BUILDERSTRING); + ErrorF("\n"); } diff --git a/hw/xwin/winscrinit.c b/hw/xwin/winscrinit.c index 983ff5730..fa6838a78 100644 --- a/hw/xwin/winscrinit.c +++ b/hw/xwin/winscrinit.c @@ -467,7 +467,7 @@ winFinishScreenInitFB (int index, if (pScreen->a) { \ pScreenPriv->a = pScreen->a; \ } else { \ - ErrorF("null screen fn " #a "\n"); \ + winDebug("winScreenInit - null screen fn " #a "\n"); \ pScreenPriv->a = NULL; \ } @@ -503,7 +503,7 @@ winFinishScreenInitFB (int index, if (pScreen->a) { \ pScreenPriv->a = pScreen->a; \ } else { \ - ErrorF("null screen fn " #a "\n"); \ + winDebug("null screen fn " #a "\n"); \ pScreenPriv->a = NULL; \ } diff --git a/hw/xwin/winwakeup.c b/hw/xwin/winwakeup.c index b512b29e8..031a510f9 100644 --- a/hw/xwin/winwakeup.c +++ b/hw/xwin/winwakeup.c @@ -45,8 +45,8 @@ winWakeupHandler (int nScreen, { MSG msg; - /* Process all messages on our queue */ - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + /* Process one message from our queue */ + if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { if ((g_hDlgDepthChange == 0 || !IsDialogMessage (g_hDlgDepthChange, &msg)) diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c index 91399c248..734ac87d7 100644 --- a/hw/xwin/winwin32rootless.c +++ b/hw/xwin/winwin32rootless.c @@ -283,7 +283,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/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index 229696ae4..769b890e8 100644 --- a/hw/xwin/winwindow.h +++ b/hw/xwin/winwindow.h @@ -49,6 +49,8 @@ #define WINDOW_TITLE_XDMCP "%s:%s.%d" #define WIN_SCR_PROP "cyg_screen_prop rl" #define WINDOW_CLASS_X "cygwin/x X rl" +#define WINDOW_CLASS_X_CHILD "cygwin/x X child" +#define WINDOW_CLASS_X_MSG "cygwin/x X msg" #define WINDOW_TITLE_X PROJECT_NAME " X" #define WIN_WINDOW_PROP "cyg_window_prop_rl" #ifdef HAS_DEVWINDOWS @@ -160,6 +162,14 @@ winDeinitMultiWindowWM (void); void winMinimizeWindow (Window id); +void +winTaskbarInit (void); + +void +winTaskbarDestroy (void); + +void +winSetAppID (HWND hWnd, const char* AppID); /* * winmultiwindowicons.c diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c index 88b506891..e99697de8 100644 --- a/hw/xwin/winwndproc.c +++ b/hw/xwin/winwndproc.c @@ -438,6 +438,12 @@ winWindowProc (HWND hwnd, UINT message, } return 0; + case WM_SYSCOMMAND: + if (s_pScreenInfo->iResizeMode == resizeWithRandr && + ((wParam & 0xfff0) == SC_MAXIMIZE || (wParam & 0xfff0) == SC_RESTORE)) + PostMessage(hwnd, WM_EXITSIZEMOVE, 0, 0); + break; + case WM_ENTERSIZEMOVE: ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n"); break; @@ -1257,7 +1263,6 @@ winWindowProc (HWND hwnd, UINT message, } break; - case WM_ENDSESSION: case WM_GIVEUP: /* Tell X that we are giving up */ #ifdef XWIN_MULTIWINDOW |