This is the mail archive of the cygwin-xfree@cygwin.com mailing list for the Cygwin XFree86 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch for multiple monitors


Hi,

I attach a patch for multiple monitors, diffed against
xwin-20021107-0015. I have added a command-line flag -multiplemonitors
which activates the extra code.

This works on my machine in both windowed and rootless modes for engines
1, 2 and 4. It does not work in fullscreen mode because the defaults for
the fullscreen dimensions are calculated before the command line
parameters are parsed (as far as I could figure out).

It should be possible to make this behaviour the default (SM_CXSCREEN ==
SM_CXVIRTUALSCREEN etc. if there is only one monitor), which would
remove many of the if {} else {} blocks, and also might make fullscreen
mode work

My machine is running Windows 2000. Both my graphics cards are set at
1600x1200 32bit colour. It's great - I'm running KDE in rootless mode,
and I get the kicker across the bottom of both monitors, and I can drag
X windows from one monitor to the other ...

Comments?

Nick

diff -uw ./InitOutput.c
../../x-devel/build/opt/programs/Xserver/hw/xwin/InitOutput.c
--- ./InitOutput.c	2002-11-07 05:21:18.000000000 +0000
+++ ../../x-devel/build/opt/programs/Xserver/hw/xwin/InitOutput.c
2003-01-09 16:51:10.000000000 +0000
@@ -114,7 +114,8 @@
   /* Zero the memory used for storing the screen info */
   ZeroMemory (g_ScreenInfo, MAXSCREENS * sizeof (winScreenInfo));
 
-  /* Get default width and height */
+  /* Get default width and height. These will just be for the primary
+     monitor in the case that we have multiple monitors. */
   dwWidth = GetSystemMetrics (SM_CXSCREEN);
   dwHeight = GetSystemMetrics (SM_CYSCREEN);
 
@@ -139,6 +140,7 @@
       g_ScreenInfo[i].fFullScreen = FALSE;
       g_ScreenInfo[i].fDecoration = TRUE;
       g_ScreenInfo[i].fRootless = FALSE;
+      g_ScreenInfo[i].fMultiplemonitors = FALSE;
       g_ScreenInfo[i].fLessPointer = FALSE;
       g_ScreenInfo[i].fScrollbars = FALSE;
       g_ScreenInfo[i].iE3BTimeout = WIN_E3B_OFF;
@@ -303,6 +305,10 @@
   ErrorF ("-rootless\n"
 	  "\tEXPERIMENTAL: Run the server in pseudo-rootless mode.\n");
 
+  ErrorF ("-multiplemonitors\n"
+	  "\tEXPERIMENTAL: Use the entire virtual screen if multiple\n"
+	  "\tmonitors are present.\n");
+
   ErrorF ("-scrollbars\n"
 	  "\tIn windowed mode, allow screens bigger than the Windows
desktop.\n"
 	  "\tMoreover, if the window has decorations, one can now
resize\n"
@@ -653,6 +659,32 @@
     }
 
   /*
+   * Look for the '-multiplemonitors' argument
+   */
+  if (strcmp (argv[i], "-multiplemonitors") == 0)
+    {
+      /* Is this parameter attached to a screen or is it global? */
+      if (-1 == g_iLastScreen)
+	{
+	  int			j;
+
+	  /* Parameter is for all screens */
+	  for (j = 0; j < MAXSCREENS; j++)
+	    {
+	      g_ScreenInfo[j].fMultiplemonitors = TRUE;
+	    }
+	}
+      else
+	{
+	  /* Parameter is for a single screen */
+	  g_ScreenInfo[g_iLastScreen].fMultiplemonitors = TRUE;
+	}
+
+      /* Indicate that we have processed this argument */
+      return 1;
+    }
+
+  /*
    * Look for the '-scrollbars' argument
    */
   if (strcmp (argv[i], "-scrollbars") == 0)
diff -uw ./win.h ../../x-devel/build/opt/programs/Xserver/hw/xwin/win.h
--- ./win.h	2002-11-07 05:33:17.000000000 +0000
+++ ../../x-devel/build/opt/programs/Xserver/hw/xwin/win.h
2003-01-09 16:51:38.000000000 +0000
@@ -390,6 +390,7 @@
   Bool			fFullScreen;
   Bool			fDecoration;
   Bool			fRootless;
+  Bool                  fMultiplemonitors;
   Bool			fLessPointer;
   Bool			fScrollbars;
   int			iE3BTimeout;
diff -uw ./wincreatewnd.c
../../x-devel/build/opt/programs/Xserver/hw/xwin/wincreatewnd.c
--- ./wincreatewnd.c	2002-10-19 04:56:52.000000000 +0100
+++ ../../x-devel/build/opt/programs/Xserver/hw/xwin/wincreatewnd.c
2003-01-10 15:11:26.000000000 +0000
@@ -31,16 +31,17 @@
 
 #include "win.h"
 #include "shellapi.h"
 
 /*
  * Local function prototypes
  */
 
 static Bool
+winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo);
+static Bool
 winAdjustForAutoHide (RECT *prcWorkArea);
 
-
 /*
  * Create a full screen window
  */
@@ -155,7 +156,7 @@
   RegisterClass (&wc);
 
   /* Get size of work area */
-  SystemParametersInfo (SPI_GETWORKAREA, 0, &rcWorkArea, 0);
+  winGetWorkArea (&rcWorkArea, pScreenInfo);
 
   /* Adjust for auto-hide taskbars */
   winAdjustForAutoHide (&rcWorkArea);
@@ -206,10 +207,18 @@
 	   * In this case we have to ignore the requested width and
height
 	   * and instead use the largest possible window that we can.
 	   */
+	  if (pScreenInfo->fMultiplemonitors)
+	    {
+	      iWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+	      iHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+	    }
+	  else
+	    {
 	  iWidth = GetSystemMetrics (SM_CXSCREEN);
 	  iHeight = GetSystemMetrics (SM_CYSCREEN);
 	}
     }
+    }
   else
     {
       /* By default, we are creating a window that is as large as
possible */
@@ -217,6 +226,12 @@
       ErrorF ("winCreateBoundingWindowWindowed - User did not give "
 	      "height and width\n");
 #endif
+      /* Defaults are wrong if we have multiple monitors */
+      if (pScreenInfo->fMultiplemonitors)
+	{
+	  iWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+	  iHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+	}
     }
 
   /* Clean up the scrollbars flag, if necessary */
@@ -368,6 +383,59 @@
 
 
 /*
+ * Find the work area of all attached monitors
+ */
+static Bool
+winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo)
+{
+  /* SPI_GETWORKAREA only gets the work area of the primary screen. */
+  SystemParametersInfo (SPI_GETWORKAREA, 0, prcWorkArea, 0);
+  if (pScreenInfo->fMultiplemonitors)
+    {
+      int iPrimaryWidth, iPrimaryHeight, iWidth, iHeight;
+      int iLeft, iTop, iPrimaryNonWorkAreaWidth,
iPrimaryNonWorkAreaHeight;
+      
+      ErrorF ("winGetWorkArea - Original WorkArea: %d %d %d %d\n",
+	      prcWorkArea->top, prcWorkArea->left,
+	      prcWorkArea->bottom, prcWorkArea->right);
+      /* Get info on full virtual screen */
+      iWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+      iHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+      ErrorF("winGetWorkArea - Virtual screen is %d x %d\n", iWidth,
iHeight);
+      iLeft = GetSystemMetrics (SM_XVIRTUALSCREEN);
+      iTop = GetSystemMetrics (SM_YVIRTUALSCREEN);
+      ErrorF("winGetWorkArea - Virtual screen origin is %d, %d\n",
iLeft, iTop);
+
+      /* Get info on primary screen */
+      iPrimaryWidth = GetSystemMetrics (SM_CXSCREEN);
+      iPrimaryHeight = GetSystemMetrics (SM_CYSCREEN);
+      ErrorF("winGetWorkArea - Primary screen is %d x %d\n",
iPrimaryWidth, iPrimaryHeight);
+
+      /* Work out how much of the primary screen we aren't using */
+      iPrimaryNonWorkAreaWidth = iPrimaryWidth - (prcWorkArea->right -
prcWorkArea->left);
+      iPrimaryNonWorkAreaHeight = iPrimaryHeight - (prcWorkArea->bottom
- prcWorkArea->top);
+
+      /* Update the rectangle to include all monitors */
+      if (iLeft < 0) 
+	{
+	  prcWorkArea->left = iLeft;
+	}
+      if (iTop < 0) 
+	{
+	  prcWorkArea->top = iTop;
+	}
+      prcWorkArea->right = prcWorkArea->left + iWidth -
iPrimaryNonWorkAreaWidth;
+      prcWorkArea->bottom = prcWorkArea->top + iHeight -
iPrimaryNonWorkAreaHeight;
+	
+      ErrorF ("winGetWorkArea - Adjusted WorkArea for multiple
monitors: %d %d %d %d\n",
+	      prcWorkArea->top, prcWorkArea->left,
+	      prcWorkArea->bottom, prcWorkArea->right);
+    }
+  return TRUE;
+}
+
+
+/*
  * Adjust the client area so that any auto-hide toolbars
  * will work correctly.
  */
diff -uw ./winscrinit.c
../../x-devel/build/opt/programs/Xserver/hw/xwin/winscrinit.c
--- ./winscrinit.c	2002-11-07 05:21:18.000000000 +0000
+++ ../../x-devel/build/opt/programs/Xserver/hw/xwin/winscrinit.c
2003-01-10 09:27:45.000000000 +0000
@@ -113,6 +113,16 @@
 #endif
     }
 
+  /* Check all monitors have the same display depth if we are using
+     multiple monitors */
+  if (pScreenInfo->fMultiplemonitors 
+      && ! GetSystemMetrics (SM_SAMEDISPLAYFORMAT))
+    {
+      ErrorF ("Monitors do not all have same pixel format / display
depth.\n"
+	      "Using primary display only.\n");
+      pScreenInfo->fMultiplemonitors = FALSE;
+    }
+  
   /* Create display window */
   if (!(*pScreenPriv->pwinCreateBoundingWindow) (pScreen))
     {
@@ -123,8 +133,28 @@
 
   /* Store the initial height, width, and depth of the display */
   hdc = GetDC (pScreenPriv->hwndScreen);
+  /* Are we using multiple monitors? */
+  if (pScreenInfo->fMultiplemonitors)
+    {
+      pScreenPriv->dwLastWindowsWidth = GetSystemMetrics
(SM_CXVIRTUALSCREEN);
+      pScreenPriv->dwLastWindowsHeight = GetSystemMetrics
(SM_CYVIRTUALSCREEN);
+      /* In this case, some of the defaults set in
+	 winInitializeDefaultScreens() are not correct ... */
+      if (!pScreenInfo->fUserGaveHeightAndWidth)
+	{
+	  pScreenInfo->dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+	  pScreenInfo->dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+	  pScreenInfo->dwWidth_mm = (pScreenInfo->dwWidth /
WIN_DEFAULT_DPI)
+	    * 25.4;
+	  pScreenInfo->dwHeight_mm = (pScreenInfo->dwHeight /
WIN_DEFAULT_DPI)
+	    * 25.4;
+	}
+    }
+  else
+    {
   pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXSCREEN);
   pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYSCREEN);
+    }
   pScreenPriv->dwLastWindowsBitsPixel
     = GetDeviceCaps (hdc, BITSPIXEL);
   ReleaseDC (pScreenPriv->hwndScreen, hdc);
diff -uw ./winshaddd.c
../../x-devel/build/opt/programs/Xserver/hw/xwin/winshaddd.c
--- ./winshaddd.c	2002-10-19 04:56:53.000000000 +0100
+++ ../../x-devel/build/opt/programs/Xserver/hw/xwin/winshaddd.c
2003-01-10 09:48:28.000000000 +0000
@@ -230,6 +230,7 @@
     {
       DDSURFACEDESC	ddsdCurrent;
       DWORD		dwRefreshRateCurrent = 0;
+      DWORD             dwWidth, dwHeight;
       HDC		hdc = NULL;
 
       /* Set the cooperative level to full screen */
@@ -289,8 +290,18 @@
 	}
 
       /* Only change the video mode when different than current mode */
-      if (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
-	  || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
+      if (pScreenInfo->fMultiplemonitors)
+	{
+	  dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+	  dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+	}
+      else
+	{
+	  dwWidth = GetSystemMetrics (SM_CXSCREEN);
+	  dwHeight = GetSystemMetrics (SM_CYSCREEN);
+	}
+      if (pScreenInfo->dwWidth != dwWidth
+	  || pScreenInfo->dwHeight != dwHeight
 	  || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
 	  || pScreenInfo->dwRefreshRate != 0)
 	{
diff -uw ./winshadddnl.c
../../x-devel/build/opt/programs/Xserver/hw/xwin/winshadddnl.c
--- ./winshadddnl.c	2002-10-19 04:56:53.000000000 +0100
+++ ../../x-devel/build/opt/programs/Xserver/hw/xwin/winshadddnl.c
2003-01-10 09:51:55.000000000 +0000
@@ -248,6 +248,7 @@
     {
       DDSURFACEDESC2	ddsdCurrent;
       DWORD		dwRefreshRateCurrent = 0;
+      DWORD             dwWidth, dwHeight;
       HDC		hdc = NULL;
 
       /* Set the cooperative level to full screen */
@@ -307,8 +308,18 @@
 	}
 
       /* Only change the video mode when different than current mode */
-      if (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
-	  || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
+      if (pScreenInfo->fMultiplemonitors)
+	{
+	  dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+	  dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+	}
+      else
+	{
+	  dwWidth = GetSystemMetrics (SM_CXSCREEN);
+	  dwHeight = GetSystemMetrics (SM_CYSCREEN);
+	}
+      if (pScreenInfo->dwWidth != dwWidth
+	  || pScreenInfo->dwHeight != dwHeight
 	  || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
 	  || pScreenInfo->dwRefreshRate != 0)
 	{
diff -uw ./winwndproc.c
../../x-devel/build/opt/programs/Xserver/hw/xwin/winwndproc.c
--- ./winwndproc.c	2002-10-19 04:56:53.000000000 +0100
+++ ../../x-devel/build/opt/programs/Xserver/hw/xwin/winwndproc.c
2003-01-10 09:45:48.000000000 +0000
@@ -137,8 +137,20 @@
 	   * We do this here for future compatibility in case we
 	   * ever allow switching from fullscreen to windowed mode.
 	   */
-	  s_pScreenPriv->dwLastWindowsWidth = GetSystemMetrics
(SM_CXSCREEN);
-	  s_pScreenPriv->dwLastWindowsHeight = GetSystemMetrics
(SM_CYSCREEN);
+	  if (s_pScreenInfo->fMultiplemonitors)
+	    {	
+	      s_pScreenPriv->dwLastWindowsWidth 
+                = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+	      s_pScreenPriv->dwLastWindowsHeight 
+                = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+	    }
+	  else
+	    {
+	      s_pScreenPriv->dwLastWindowsWidth
+                = GetSystemMetrics (SM_CXSCREEN);
+	      s_pScreenPriv->dwLastWindowsHeight
+                = GetSystemMetrics (SM_CYSCREEN);
+	    }
 	  s_pScreenPriv->dwLastWindowsBitsPixel
 	    = GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL);

 	  break;
@@ -280,8 +292,18 @@
 	}
 
       /* Store the new display dimensions and depth */
+      if (s_pScreenInfo->fMultiplemonitors)
+	{	
+	  s_pScreenPriv->dwLastWindowsWidth
+            = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+	  s_pScreenPriv->dwLastWindowsHeight
+            = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+	}
+      else
+	{
       s_pScreenPriv->dwLastWindowsWidth = GetSystemMetrics
(SM_CXSCREEN);
       s_pScreenPriv->dwLastWindowsHeight = GetSystemMetrics
(SM_CYSCREEN);
+	}
       s_pScreenPriv->dwLastWindowsBitsPixel
 	= GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL);
       break;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]