diff options
Diffstat (limited to 'xorg-server/hw/xwin/winmultiwindowwm.c')
-rw-r--r-- | xorg-server/hw/xwin/winmultiwindowwm.c | 333 |
1 files changed, 283 insertions, 50 deletions
diff --git a/xorg-server/hw/xwin/winmultiwindowwm.c b/xorg-server/hw/xwin/winmultiwindowwm.c index 5401ecdee..e766c42dc 100644 --- a/xorg-server/hw/xwin/winmultiwindowwm.c +++ b/xorg-server/hw/xwin/winmultiwindowwm.c @@ -1,5 +1,6 @@ /* *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + *Copyright (C) Colin Harrison 2005-2008 * *Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -26,6 +27,7 @@ *from the XFree86 Project. * * Authors: Kensuke Matsuzaki + * Colin Harrison */ /* X headers */ @@ -34,13 +36,18 @@ #endif #include <stdio.h> #include <stdlib.h> +#ifndef _MSC_VER #include <unistd.h> +#endif #ifdef __CYGWIN__ #include <sys/select.h> #endif #include <fcntl.h> #include <setjmp.h> #define HANDLE void * +#ifdef _MSC_VER +typedef int pid_t; +#endif #include <pthread.h> #undef HANDLE #include <X11/X.h> @@ -52,24 +59,22 @@ #include <X11/cursorfont.h> /* Windows headers */ -#ifdef __CYGWIN__ -/* Fixups to prevent collisions between Windows and X headers */ -#define ATOM DWORD - -#include <windows.h> -#else -#include <Xwindows.h> -#endif +#include <X11/Xwindows.h> /* Local headers */ #include "objbase.h" #include "ddraw.h" #include "winwindow.h" +#include "winprefs.h" +#include "window.h" +#include "windowstr.h" #ifdef XWIN_MULTIWINDOWEXTWM -#include "windowswmstr.h" +#include <X11/extensions/windowswmstr.h> #endif extern void winDebug(const char *format, ...); +extern void winReshapeMultiWindow(WindowPtr pWin); +extern void winUpdateRgnMultiWindow(WindowPtr pWin); #ifndef CYGDEBUG #define CYGDEBUG NO @@ -86,6 +91,7 @@ extern void winDebug(const char *format, ...); #endif #define WIN_JMP_OKAY 0 #define WIN_JMP_ERROR_IO 2 +#define AUTH_NAME "MIT-MAGIC-COOKIE-1" /* @@ -135,6 +141,10 @@ typedef struct _XMsgProcArgRec { extern char *display; extern void ErrorF (const char* /*f*/, ...); +#if defined(XCSECURITY) +extern unsigned int g_uiAuthDataLen; +extern char *g_pAuthData; +#endif /* @@ -151,7 +161,7 @@ static Bool InitQueue (WMMsgQueuePtr pQueue); static void -GetWindowName (Display * pDpy, Window iWin, char **ppName); +GetWindowName (Display * pDpy, Window iWin, wchar_t **ppName); static int SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData); @@ -191,6 +201,11 @@ PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction); static Bool CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen); +static void +winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle); + +void +winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle); /* * Local globals @@ -403,10 +418,12 @@ InitQueue (WMMsgQueuePtr pQueue) */ static void -GetWindowName (Display *pDisplay, Window iWin, char **ppName) +GetWindowName (Display *pDisplay, Window iWin, wchar_t **ppName) { int nResult, nNum; char **ppList; + char *pszReturnData; + int iLen, i; XTextProperty xtpName; #if CYGMULTIWINDOW_DEBUG @@ -425,38 +442,26 @@ GetWindowName (Display *pDisplay, Window iWin, char **ppName) #endif return; } - - /* */ - if (xtpName.encoding == XA_STRING) - { - /* */ - if (xtpName.value) - { - int size = xtpName.nitems * (xtpName.format >> 3); - *ppName = malloc(size + 1); - strncpy(*ppName, xtpName.value, size); - (*ppName)[size] = 0; - XFree (xtpName.value); - } -#if CYGMULTIWINDOW_DEBUG - ErrorF ("GetWindowName - XA_STRING %s\n", *ppName); -#endif - } - else - { - if (XmbTextPropertyToTextList (pDisplay, &xtpName, &ppList, &nNum) >= Success && nNum > 0 && *ppList) - { - *ppName = strdup (*ppList); - XFreeStringList (ppList); - } - XFree (xtpName.value); - -#if CYGMULTIWINDOW_DEBUG - ErrorF ("GetWindowName - %s %s\n", - XGetAtomName (pDisplay, xtpName.encoding), *ppName); -#endif - } + 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]); + } + 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); + if (ppList) XFreeStringList (ppList); + free (pszReturnData); #if CYGMULTIWINDOW_DEBUG ErrorF ("GetWindowName - Returning\n"); @@ -493,7 +498,7 @@ SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData) static void UpdateName (WMInfoPtr pWMInfo, Window iWindow) { - char *pszName; + wchar_t *pszName; Atom atmType; int fmtRet; unsigned long items, remain; @@ -537,7 +542,7 @@ UpdateName (WMInfoPtr pWMInfo, Window iWindow) &attr); if (!attr.override_redirect) { - SetWindowText (hWnd, pszName); + SetWindowTextW (hWnd, pszName); winUpdateIcon (iWindow); } @@ -705,10 +710,25 @@ winMultiWindowWMProc (void *pArg) 1); UpdateName (pWMInfo, pNode->msg.iWindow); winUpdateIcon (pNode->msg.iWindow); -#if 0 - /* Handles the case where there are AOT windows above it in W32 */ - PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV); + { + HWND zstyle = HWND_NOTOPMOST; + winApplyHints (pWMInfo->pDisplay, pNode->msg.iWindow, pNode->msg.hwndWindow, &zstyle); + winUpdateWindowPosition (pNode->msg.hwndWindow, TRUE, &zstyle); + } + break; + + case WM_WM_MAP2: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_MAP2\n"); #endif + XChangeProperty (pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmPrivMap, + XA_INTEGER,//pWMInfo->atmPrivMap, + 32, + PropModeReplace, + (unsigned char *) &(pNode->msg.hwndWindow), + 1); break; case WM_WM_UNMAP: @@ -803,6 +823,7 @@ winMultiWindowWMProc (void *pArg) #if CYGMULTIWINDOW_DEBUG ErrorF("-winMultiWindowWMProc ()\n"); #endif + return NULL; } @@ -1063,6 +1084,7 @@ winMultiWindowXMsgProc (void *pArg) XCloseDisplay (pProcArg->pDisplay); pthread_exit (NULL); + return NULL; } @@ -1226,6 +1248,14 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) /* Print the display connection string */ ErrorF ("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay); + +#if defined(XCSECURITY) + /* Use our generated cookie for authentication */ + XSetAuthorization (AUTH_NAME, + strlen (AUTH_NAME), + g_pAuthData, + g_uiAuthDataLen); +#endif /* Open the X display */ do @@ -1265,11 +1295,10 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) pWMInfo->atmWmDelete = XInternAtom (pWMInfo->pDisplay, "WM_DELETE_WINDOW", False); -#ifdef XWIN_MULTIWINDOWEXTWM + pWMInfo->atmPrivMap = XInternAtom (pWMInfo->pDisplay, - WINDOWSWM_NATIVE_HWND, + "_WINDOWSWM_NATIVE_HWND", False); -#endif if (1) { @@ -1364,7 +1393,9 @@ winMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr) pErr->error_code, pszErrorMsg, sizeof (pszErrorMsg)); +#if CYGMULTIWINDOW_DEBUG ErrorF ("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg); +#endif return 0; } @@ -1438,3 +1469,205 @@ winDeinitMultiWindowWM () ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n"); g_shutdown = TRUE; } + +/* Windows window styles */ +#define HINT_NOFRAME (1L<<0) +#define HINT_BORDER (1L<<1) +#define HINT_SIZEBOX (1L<<2) +#define HINT_CAPTION (1L<<3) +#define HINT_NOMAXIMIZE (1L<<4) +/* These two are used on their own */ +#define HINT_MAX (1L<<0) +#define HINT_MIN (1L<<1) + +static void +winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle) +{ + static Atom windowState, motif_wm_hints, windowType; + Atom type, *pAtom = NULL; + int format; + unsigned long hint = 0, maxmin = 0, rcStyle, nitems = 0 , left = 0; + WindowPtr pWin = GetProp (hWnd, WIN_WINDOW_PROP); + MwmHints *mwm_hint = NULL; + XSizeHints *normal_hint; + long supplied; + + if (!hWnd) return; + if (!IsWindow (hWnd)) return; + + if (windowState == None) windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False); + if (motif_wm_hints == None) motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False); + if (windowType == None) windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False); + + if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L, + 1L, False, XA_ATOM, &type, &format, + &nitems, &left, (unsigned char **)&pAtom) == Success) + { + if (pAtom && nitems == 1) + { + static Atom hiddenState, fullscreenState, belowState, aboveState; + if (hiddenState == None) hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False); + if (fullscreenState == None) fullscreenState = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False); + if (belowState == None) belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False); + if (aboveState == None) aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False); + if (*pAtom == hiddenState) maxmin |= HINT_MIN; + else if (*pAtom == fullscreenState) maxmin |= HINT_MAX; + if (*pAtom == belowState) *zstyle = HWND_BOTTOM; + else if (*pAtom == aboveState) *zstyle = HWND_TOPMOST; + } + if (pAtom) XFree(pAtom); + } + + nitems = left = 0; + if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L, + PropMwmHintsElements, False, motif_wm_hints, &type, &format, + &nitems, &left, (unsigned char **)&mwm_hint) == Success) + { + if (mwm_hint && nitems == PropMwmHintsElements && (mwm_hint->flags & MwmHintsDecorations)) + { + if (!mwm_hint->decorations) hint |= HINT_NOFRAME; + else if (!(mwm_hint->decorations & MwmDecorAll)) + { + if (mwm_hint->decorations & MwmDecorBorder) hint |= HINT_BORDER; + if (mwm_hint->decorations & MwmDecorHandle) hint |= HINT_SIZEBOX; + if (mwm_hint->decorations & MwmDecorTitle) hint |= HINT_CAPTION; + } + } + if (mwm_hint) XFree(mwm_hint); + } + + nitems = left = 0; + pAtom = NULL; + if (XGetWindowProperty(pDisplay, iWindow, windowType, 0L, + 1L, False, XA_ATOM, &type, &format, + &nitems, &left, (unsigned char **)&pAtom) == Success) + { + if (pAtom && nitems == 1) + { + static Atom dockWindow; + if (dockWindow == None) dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False); + if (*pAtom == dockWindow) + { + hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */ + *zstyle = HWND_TOPMOST; + } + } + if (pAtom) XFree(pAtom); + } + + normal_hint = XAllocSizeHints(); + if (normal_hint && (XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied) == Success)) + { + if (normal_hint->flags & PMaxSize) + { + /* Not maximizable if a maximum size is specified */ + hint |= HINT_NOMAXIMIZE; + + if (normal_hint->flags & PMinSize) + { + /* + If both minimum size and maximum size are specified and are the same, + don't bother with a resizing frame + */ + if ((normal_hint->min_width == normal_hint->max_width) + && (normal_hint->min_height == normal_hint->max_height)) + hint = (hint & ~HINT_SIZEBOX); + } + } + } + XFree(normal_hint); + + /* Apply Styles, overriding hint settings from above */ + rcStyle = winOverrideStyle((unsigned long)pWin); + if (rcStyle & STYLE_TOPMOST) *zstyle = HWND_TOPMOST; + else if (rcStyle & STYLE_MAXIMIZE) maxmin = (hint & ~HINT_MIN) | HINT_MAX; + else if (rcStyle & STYLE_MINIMIZE) maxmin = (hint & ~HINT_MAX) | HINT_MIN; + else if (rcStyle & STYLE_BOTTOM) *zstyle = HWND_BOTTOM; + + if (maxmin & HINT_MAX) SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + else if (maxmin & HINT_MIN) SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + + if (rcStyle & STYLE_NOTITLE) + hint = (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) | HINT_SIZEBOX; + else if (rcStyle & STYLE_OUTLINE) + hint = (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) | HINT_BORDER; + else if (rcStyle & STYLE_NOFRAME) + hint = (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) | HINT_NOFRAME; + + SetWindowLongPtr (hWnd, GWL_STYLE, GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION & ~WS_SIZEBOX); /* Just in case */ + if (!hint) /* All on */ + SetWindowLongPtr (hWnd, GWL_STYLE, GetWindowLongPtr(hWnd, GWL_STYLE) | WS_CAPTION | WS_SIZEBOX); + else if (hint & HINT_NOFRAME); /* All off, so do nothing */ + else SetWindowLongPtr (hWnd, GWL_STYLE, GetWindowLongPtr(hWnd, GWL_STYLE) | + ((hint & HINT_BORDER) ? WS_BORDER : 0) | + ((hint & HINT_SIZEBOX) ? WS_SIZEBOX : 0) | + ((hint & HINT_CAPTION) ? WS_CAPTION : 0)); + + if (hint & HINT_NOMAXIMIZE) + SetWindowLongPtr(hWnd, GWL_STYLE, GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX); +} + +void +winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle) +{ + int iX, iY, iWidth, iHeight; + int iDx, iDy; + RECT rcNew; + WindowPtr pWin = GetProp (hWnd, WIN_WINDOW_PROP); + DrawablePtr pDraw = NULL; + + if (!pWin) return; + pDraw = &pWin->drawable; + if (!pDraw) return; + + /* 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; + + /* Setup a rectangle with the X window position and size */ + SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight); + +#if 0 + ErrorF ("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, + rcNew.right, rcNew.bottom); +#endif + + AdjustWindowRectEx (&rcNew, GetWindowLongPtr (hWnd, GWL_STYLE), FALSE, WS_EX_APPWINDOW); + + /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */ + if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) + { + iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left; + rcNew.left += iDx; + rcNew.right += iDx; + } + + if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) + { + iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top; + rcNew.top += iDy; + rcNew.bottom += iDy; + } + +#if 0 + ErrorF ("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, + rcNew.right, rcNew.bottom); +#endif + + /* Position the Windows window */ + SetWindowPos (hWnd, *zstyle, rcNew.left, rcNew.top, + rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, + 0); + + if (reshape) + { + winReshapeMultiWindow(pWin); + winUpdateRgnMultiWindow(pWin); + } +} |