aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwin/winmultiwindowwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwin/winmultiwindowwm.c')
-rw-r--r--xorg-server/hw/xwin/winmultiwindowwm.c264
1 files changed, 246 insertions, 18 deletions
diff --git a/xorg-server/hw/xwin/winmultiwindowwm.c b/xorg-server/hw/xwin/winmultiwindowwm.c
index 5401ecdee..18d9aedc2 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-2009
*
*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 */
@@ -50,26 +52,28 @@
#include <X11/Xproto.h>
#include <X11/Xutil.h>
#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 "pixmapstr.h"
+#include "windowstr.h"
+
#ifdef XWIN_MULTIWINDOWEXTWM
-#include "windowswmstr.h"
+#include <X11/extensions/windowswmstr.h>
+#else
+/* We need the native HWND atom for intWM, so for consistency use the
+ same name as extWM would if we were building with enabled... */
+#define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND"
#endif
extern void winDebug(const char *format, ...);
+extern void winReshapeMultiWindow(WindowPtr pWin);
+extern void winUpdateRgnMultiWindow(WindowPtr pWin);
#ifndef CYGDEBUG
#define CYGDEBUG NO
@@ -191,6 +195,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
@@ -245,6 +254,12 @@ PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode)
case WM_WM_MAP:
ErrorF ("\tWM_WM_MAP\n");
break;
+ case WM_WM_MAP2:
+ ErrorF ("\tWM_WM_MAP2\n");
+ break;
+ case WM_WM_MAP3:
+ ErrorF ("\tWM_WM_MAP3\n");
+ break;
case WM_WM_UNMAP:
ErrorF ("\tWM_WM_UNMAP\n");
break;
@@ -705,10 +720,42 @@ 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);
+ 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_MAP3:
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("\tWM_WM_MAP3\n");
+#endif
+ /* Put a note as to the HWND associated with this Window */
+ XChangeProperty (pWMInfo->pDisplay,
+ pNode->msg.iWindow,
+ pWMInfo->atmPrivMap,
+ XA_INTEGER,//pWMInfo->atmPrivMap,
+ 32,
+ PropModeReplace,
+ (unsigned char *) &(pNode->msg.hwndWindow),
+ 1);
+ UpdateName (pWMInfo, pNode->msg.iWindow);
+ winUpdateIcon (pNode->msg.iWindow);
+ {
+ HWND zstyle = HWND_NOTOPMOST;
+ winApplyHints (pWMInfo->pDisplay, pNode->msg.iWindow, pNode->msg.hwndWindow, &zstyle);
+ winUpdateWindowPosition (pNode->msg.hwndWindow, TRUE, &zstyle);
+ }
break;
case WM_WM_UNMAP:
@@ -803,6 +850,7 @@ winMultiWindowWMProc (void *pArg)
#if CYGMULTIWINDOW_DEBUG
ErrorF("-winMultiWindowWMProc ()\n");
#endif
+ return NULL;
}
@@ -1063,7 +1111,7 @@ winMultiWindowXMsgProc (void *pArg)
XCloseDisplay (pProcArg->pDisplay);
pthread_exit (NULL);
-
+ return NULL;
}
@@ -1265,11 +1313,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,
False);
-#endif
if (1) {
@@ -1364,7 +1411,9 @@ winMultiWindowXMsgProcErrorHandler (Display *pDisplay, XErrorEvent *pErr)
pErr->error_code,
pszErrorMsg,
sizeof (pszErrorMsg));
+#if CYGMULTIWINDOW_DEBUG
ErrorF ("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg);
+#endif
return 0;
}
@@ -1433,8 +1482,187 @@ CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen)
*/
void
-winDeinitMultiWindowWM ()
+winDeinitMultiWindowWM (void)
{
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)
+/* 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;
+ static Atom hiddenState, fullscreenState, belowState, aboveState;
+ static Atom dockWindow;
+ static int generation;
+ Atom type, *pAtom = NULL;
+ int format;
+ unsigned long hint = 0, maxmin = 0, style, nitems = 0 , left = 0;
+ WindowPtr pWin = GetProp (hWnd, WIN_WINDOW_PROP);
+
+ if (!hWnd) return;
+ if (!IsWindow (hWnd)) return;
+
+ if (generation != serverGeneration) {
+ generation = serverGeneration;
+ windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False);
+ motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False);
+ windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False);
+ hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False);
+ fullscreenState = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False);
+ belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False);
+ aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False);
+ dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False);
+ }
+
+ if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L,
+ 1L, False, XA_ATOM, &type, &format,
+ &nitems, &left, (unsigned char **)&pAtom) == Success)
+ {
+ if (pAtom && nitems == 1)
+ {
+ 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;
+ MwmHints *mwm_hint = NULL;
+ 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)
+ {
+ if (*pAtom == dockWindow)
+ {
+ hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */
+ *zstyle = HWND_TOPMOST;
+ }
+ }
+ if (pAtom) XFree(pAtom);
+ }
+
+ /* Apply Styles, overriding hint settings from above */
+ style = winOverrideStyle((unsigned long)pWin);
+ if (style & STYLE_TOPMOST) *zstyle = HWND_TOPMOST;
+ else if (style & STYLE_MAXIMIZE) maxmin = (hint & ~HINT_MIN) | HINT_MAX;
+ else if (style & STYLE_MINIMIZE) maxmin = (hint & ~HINT_MAX) | HINT_MIN;
+ else if (style & 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 (style & STYLE_NOTITLE)
+ hint = (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) | HINT_SIZEBOX;
+ else if (style & STYLE_OUTLINE)
+ hint = (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) | HINT_BORDER;
+ else if (style & STYLE_NOFRAME)
+ hint = (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) | HINT_NOFRAME;
+
+ style = GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */
+ if (!style) return;
+ if (!hint) /* All on, but no resize of children is allowed */
+ style = style | WS_CAPTION | (GetParent(hWnd) ? 0 : WS_SIZEBOX);
+ else if (hint & HINT_NOFRAME); /* All off, so do nothing */
+ else style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) |
+ ((hint & HINT_SIZEBOX) ? (GetParent(hWnd) ? 0 : WS_SIZEBOX) : 0) |
+ ((hint & HINT_CAPTION) ? WS_CAPTION : 0);
+ SetWindowLongPtr (hWnd, GWL_STYLE, style);
+}
+
+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);
+ }
+}