[PATCH 06/12] Xming: Apply window style hints in -multiwindow mode

Jon TURNEY jon.turney at dronecode.org.uk
Wed May 20 04:52:24 PDT 2009


From: Colin Harrison <colin.harrison at virgin.net>

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 <jon.turney at dronecode.org.uk>
---
 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



More information about the xorg-devel mailing list