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]

RE: Patch for multiple monitors


Nick,

I am merging your patch right now.

However, I have a few questions.

In winshaddd.c/winAllocateFBShadowDD () (etc.) you load the height and width
(dwHeight, dwWidth) of either the screen or the virtual screen, depending
upon whether we are using multiple monitors or not.  You then use the
equality or non-equality of the height and width of the screen or virtual
screen versus the size specified on the command-line to determine whether or
not to switch the display mode of only the primary display.

That doesn't make much sense.  We really can't be switching modes of any of
the multiple monitors when the size of the virtual screen does not match the
requested size.  I mean, how would we know which monitor to change the
resolution of, and by how much, without some extensive logic that is simply
not present?

I suggest that we leave out the changes in winAllocateFBShadowDD and its
cousins.

Am I simply misunderstanding things, or does this make sense to you too?

Harold

-----Original Message-----
From: cygwin-xfree-owner@cygwin.com
[mailto:cygwin-xfree-owner@cygwin.com]On Behalf Of Nick Crabtree
Sent: Friday, January 10, 2003 11:24 AM
To: cygwin-xfree@cygwin.com
Subject: 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]