From: Colin Harrison <[email protected]>

Improve internal WM to:
Remove frames from 'dock' windows and make them topmost in -multiwindow mode.
Remove frames from windows with MOTIF_WM_HINTS of no decorations in 
-multiwindow mode.
Apply some _NET_WM_STATE hints in -multiwindow mode.
Improve handling of overrideRedirect windows: minimal window decoration and 
force in front of topmost window
only if it is also an X window

XXX: Is GetWindowLongPtr(GWLP_USERDATA) == XMING_SIGNATURE doing the same thing 
as GetProp(WIN_WID_PROP) != NULL

Signed-off-by: Jon TURNEY <[email protected]>
---
 hw/xwin/winmultiwindowwm.c      |  103 +++++++++++++++++++++++++++++++++++++++
 hw/xwin/winmultiwindowwndproc.c |   74 +++++++++++++++++-----------
 hw/xwin/winwindow.h             |   15 ++++++
 3 files changed, 164 insertions(+), 28 deletions(-)

diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index ea9dfca..b996a04 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/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 */
@@ -186,6 +188,8 @@ PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT 
direction);
 static Bool
 CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen);
 
+static void
+ApplyHints (Display *pDisplay, Window iWindow, HWND hWnd);
 
 /*
  * Local globals
@@ -689,6 +693,7 @@ winMultiWindowWMProc (void *pArg)
 #if CYGMULTIWINDOW_DEBUG
          ErrorF ("\tWM_WM_MAP\n");
 #endif
+         ApplyHints (pWMInfo->pDisplay, pNode->msg.iWindow, 
pNode->msg.hwndWindow);
          /* Put a note as to the HWND associated with this Window */
          XChangeProperty (pWMInfo->pDisplay,
                           pNode->msg.iWindow,
@@ -706,6 +711,17 @@ winMultiWindowWMProc (void *pArg)
 #endif
          break;
 
+       case WM_WM_MAP2:
+         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:
 #if CYGMULTIWINDOW_DEBUG
          ErrorF ("\tWM_WM_UNMAP\n");
@@ -1433,3 +1449,90 @@ winDeinitMultiWindowWM (void)
   ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n");
   g_shutdown = TRUE;
 }
+
+static void
+ApplyHints (Display *pDisplay, Window iWindow, HWND hWnd)
+{
+  Atom                 type;
+  static Atom  windowType, windowState, motif_wm_hints;
+  int          format;
+  unsigned long nitems = 0, left = 0;
+  unsigned char *data = 0;
+
+  if (!hWnd) return;
+  if (!IsWindow (hWnd)) return;
+
+  if (windowType == None) windowType = XInternAtom(pDisplay, 
"_NET_WM_WINDOW_TYPE", False);
+  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 (XGetWindowProperty(pDisplay, iWindow, windowType, 0L,
+                        1L, False, XA_ATOM, &type, &format,
+                        &nitems, &left, &data) == Success)
+  {
+    if (data != None)
+    {
+      Atom a;
+      static Atom dockWindow, dialogWindow;
+      if (dockWindow == None) dockWindow = XInternAtom(pDisplay, 
"_NET_WM_WINDOW_TYPE_DOCK", False);
+      if (dialogWindow == None) dialogWindow = XInternAtom(pDisplay, 
"_NET_WM_WINDOW_TYPE_DIALOG", False);
+      memcpy (&a, data, sizeof (Atom));
+      XFree(data);
+      if (a == dockWindow)
+      {
+       SetWindowLongPtr (hWnd, GWL_STYLE, (GetWindowLongPtr(hWnd, GWL_STYLE) & 
~WS_OVERLAPPEDWINDOW) | WS_SIZEBOX);
+       SetWindowPos (hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 
SWP_FRAMECHANGED | SWP_NOACTIVATE);
+       return;
+      }
+      else if (a == dialogWindow)
+      {
+       SetForegroundWindow (hWnd);
+       return;
+      }
+    }
+  }
+
+  if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L,
+                        1L, False, XA_ATOM, &type, &format,
+                        &nitems, &left, &data) == Success)
+  {
+    if (data != None)
+    {
+      Atom a;
+      static Atom hiddenState, fullscreenState, aboveState;
+      if (hiddenState == None) hiddenState = XInternAtom(pDisplay, 
"_NET_WM_STATE_HIDDEN", False);
+      if (fullscreenState == None) fullscreenState = XInternAtom(pDisplay, 
"_NET_WM_STATE_FULLSCREEN", False);
+      if (aboveState == None) aboveState = XInternAtom(pDisplay, 
"_NET_WM_STATE_ABOVE", False);
+      memcpy (&a, data, sizeof (Atom));
+      XFree(data);
+      if (a == hiddenState)
+       PostMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+      else if (a == fullscreenState)
+       PostMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+      else if (a == aboveState)
+       SetWindowPos (hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | 
SWP_NOACTIVATE);
+    }
+  }
+
+  nitems = left = 0;
+  data = 0;
+  if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L,
+                        5L, False, motif_wm_hints, &type, &format,
+                        &nitems, &left, &data) == Success)
+  {
+    if (data != None)
+    {
+      struct MwmHints hintsdata;
+      struct MwmHints *hints = &hintsdata;
+      memcpy (hints, data, sizeof (MwmHints));
+      XFree(data);
+      if ((hints->flags & MWM_HINTS_DECORATIONS) && (hints->decorations == 0))
+      {
+       SetWindowLongPtr (hWnd, GWL_STYLE, GetWindowLongPtr(hWnd, GWL_STYLE) & 
~WS_OVERLAPPEDWINDOW);
+       SetWindowPos (hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
+       return;
+      }
+    }
+  }
+  SetForegroundWindow (hWnd);
+}
diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index 5477bd7..b0ad6da 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -407,6 +407,8 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
       SetWindowRgn (hwnd, hRgnWindow, TRUE);
       DeleteObject(hRgnWindow);
 
+      SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)XMING_SIGNATURE);
+
       return 0;
 
     case WM_INIT_SYS_MENU:
@@ -844,27 +846,41 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
       if (!wParam)
        return 0;
 
-      /* Tell X to map the window */
-      MapWindow (pWin, wClient(pWin));
-
       /* */
       if (!pWin->overrideRedirect)
        {
-         DWORD         dwExStyle;
-         DWORD         dwStyle;
-         RECT          rcNew;
-         int           iDx, iDy;
-             
          /* Flag that this window needs to be made active when clicked */
          SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
 
-         /* Get the standard and extended window style information */
-         dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE);
-         dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE);
-
-         /* */
-         if (dwExStyle != WS_EX_APPWINDOW)
+         if (!(GetWindowLongPtr (hwnd, GWL_EXSTYLE) & WS_EX_APPWINDOW))
            {
+             RECT              rcNew;
+             int               iDx, iDy;
+             unsigned long     rcStyle;
+
+             /* Set the window extended style flags */
+             SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
+
+             /* Set the transient style flags */
+             if (GetParent(hwnd)) SetWindowLongPtr (hwnd, GWL_STYLE,
+                  WS_POPUP | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | 
WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+             /* Set the window standard style flags */
+             else SetWindowLongPtr (hwnd, GWL_STYLE,
+                  WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | 
WS_CLIPSIBLINGS);
+
+             rcStyle = winOverrideStyle((unsigned long)pWin);
+             if (rcStyle & STYLE_TOPMOST)
+               SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | 
SWP_NOSIZE | SWP_NOACTIVATE);
+             else if (rcStyle & STYLE_MAXIMIZE)
+               PostMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+             else if (rcStyle & STYLE_MINIMIZE)
+               PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+
+             if (rcStyle & STYLE_NOTITLE)
+               SetWindowLongPtr (hwnd, GWL_STYLE, (GetWindowLongPtr(hwnd, 
GWL_STYLE) & ~WS_OVERLAPPEDWINDOW) | WS_SIZEBOX);
+             else if (rcStyle & STYLE_NOFRAME)
+               SetWindowLongPtr (hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, 
GWL_STYLE) & ~WS_OVERLAPPEDWINDOW);
+
              /* Setup a rectangle with the X window position and size */
              SetRect (&rcNew,
                       pDraw->x,
@@ -880,7 +896,7 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
 
              /* */
              AdjustWindowRectEx (&rcNew,
-                                 WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW,
+                                 GetWindowLongPtr (hwnd, GWL_STYLE),
                                  FALSE,
                                  WS_EX_APPWINDOW);
 
@@ -900,35 +916,37 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
                      rcNew.right, rcNew.bottom);
 #endif
 
-             /* Set the window extended style flags */
-             SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
-
-             /* Set the window standard style flags */
-             SetWindowLongPtr (hwnd, GWL_STYLE,
-                               WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW);
-
              /* Position the Windows window */
-             SetWindowPos (hwnd, HWND_TOP,
+             SetWindowPos (hwnd, NULL,
                            rcNew.left, rcNew.top,
                            rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
-                           SWP_NOMOVE | SWP_FRAMECHANGED
-                           | SWP_SHOWWINDOW | SWP_NOACTIVATE);
+                           SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
 
              /* Bring the Windows window to the foreground */
              SetForegroundWindow (hwnd);
            }
+         wmMsg.msg = WM_WM_MAP;
        }
       else /* It is an overridden window so make it top of Z stack */
        {
 #if CYGWINDOWING_DEBUG
          ErrorF ("overridden window is shown\n");
 #endif
-         SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
-                       SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+         HWND forHwnd = GetForegroundWindow();
+         if (forHwnd != NULL)
+         {
+           if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & 
(LONG_PTR)XMING_SIGNATURE)
+           {
+             if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
+               SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | 
SWP_NOSIZE | SWP_NOACTIVATE);
+             else
+               SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | 
SWP_NOSIZE | SWP_NOACTIVATE);
+           }
+         }
+         wmMsg.msg = WM_WM_MAP2;
        }
          
       /* Setup the Window Manager message */
-      wmMsg.msg = WM_WM_MAP;
       wmMsg.iWidth = pDraw->width;
       wmMsg.iHeight = pDraw->height;
 
diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h
index 38db55f..9b33c49 100644
--- a/hw/xwin/winwindow.h
+++ b/hw/xwin/winwindow.h
@@ -2,6 +2,7 @@
 #define _WINWINDOW_H_
 /*
  *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
@@ -28,6 +29,7 @@
  *from the XFree86 Project.
  *
  * Authors:    Kensuke Matsuzaki
+ *              Colin Harrison
  */
 
 #ifndef NO
@@ -60,6 +62,8 @@
 #define CYGWINDOWING_DEBUG     NO
 #endif
 
+#define XMING_SIGNATURE                0x12345678L
+
 typedef struct _winPrivScreenRec *winPrivScreenPtr;
 
 
@@ -111,9 +115,20 @@ typedef struct _winWMMessageRec{
 #define                WM_WM_NAME_EVENT        (WM_USER + 9)
 #define                WM_WM_HINTS_EVENT       (WM_USER + 10)
 #define                WM_WM_CHANGE_STATE      (WM_USER + 11)
+#define                WM_WM_MAP2              (WM_USER + 12)
 #define                WM_MANAGE               (WM_USER + 100)
 #define                WM_UNMANAGE             (WM_USER + 102)
 
+#define                MWM_HINTS_DECORATIONS   (1L << 1)
+
+typedef struct MwmHints {
+  unsigned long                flags;
+  unsigned long        functions;
+  unsigned long        decorations;
+  long                 input_mode;
+  unsigned long                status;
+} MwmHints;
+
 void
 winSendMessageToWM (void *pWMInfo, winWMMessagePtr msg);
 
-- 
1.6.1.2

_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to