Cygwin/X: Generate RANDR change on WM_DISPLAYCHANGE for rootless modes

When RANDR resizing is enabled, generate an internal RANDR change when
WM_DISPLAYCHANGE occurs in rootless modes for screens which occupy an
entire monitor or the virtual desktop.

Store the monitor number and use that to handle WM_DISPLAYCHANGE for a
screen specified with '-screen @monitor'

In rooted mode, WM_DISPLAYCHANGE isn't relevant (except where display
depth changes may cause problems). (A maximized screen window will get
WM_SIZE to adjust it to the new monitor size)

In rooted fullscreen mode, WM_DISPLAYCHANGE shouldn't be seen, as we
have the resolution we have selected for the fullscreen session)
(Could client randr requests be handled in fullscreen to cause a change
of the fullscreen resolution? )

Don't bother do a RANDR resize if the dimensions aren't actually changing
when WM_DISPLAYCHANGE is sent (should handle WM_DISPLAYCHANGE to size 0x0
that the intel driver seems to like to send)

Various debug output improvements

Also, remove the note that XWin can't handle display mode changes from
the man page

Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
Tested-by: Colin Harrison <colin.harrison@virgin.net>
This commit is contained in:
Jon TURNEY 2010-03-30 19:49:41 +01:00
parent bbc511e80b
commit 33106e1e80
4 changed files with 104 additions and 39 deletions

View File

@ -376,12 +376,9 @@ X(__miscmansuffix__), Xserver(1), xdm(1), xinit(1), XWinrc(__filemansuffix__), s
.SH BUGS
.I XWin
and this man page still have many limitations. Some of the more obvious
ones are:
.br
- The display mode can not be changed once the X server has started.
.br
- The \fIXWin\fP software is continuously developing; it is therefore possible that
and this man page still have many limitations.
The \fIXWin\fP software is continuously developing; it is therefore possible that
this man page is not up to date. It is always prudent to
look also at the output of \fIXWin -help\fP in order to
check the options that are operative.

View File

@ -400,6 +400,8 @@ typedef struct
Bool fUserGaveHeightAndWidth;
DWORD dwScreen;
int iMonitor;
DWORD dwUserWidth;
DWORD dwUserHeight;
DWORD dwWidth;

View File

@ -95,6 +95,7 @@ winInitializeScreenDefaults(void)
if (monitorResolution == 0)
monitorResolution = WIN_DEFAULT_DPI;
defaultScreenInfo.iMonitor = 1;
defaultScreenInfo.dwWidth = dwWidth;
defaultScreenInfo.dwHeight = dwHeight;
defaultScreenInfo.dwUserWidth = dwWidth;
@ -318,6 +319,7 @@ ddxProcessArgument (int argc, char *argv[], int i)
iArgsProcessed = 3;
g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
g_ScreenInfo[nScreenNum].dwWidth = data.monitorWidth;
g_ScreenInfo[nScreenNum].dwHeight = data.monitorHeight;
g_ScreenInfo[nScreenNum].dwUserWidth = data.monitorWidth;
@ -370,6 +372,7 @@ ddxProcessArgument (int argc, char *argv[], int i)
"Querying monitors is not supported on NT4 and Win95\n");
} else if (data.bMonitorSpecifiedExists == TRUE)
{
g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
g_ScreenInfo[nScreenNum].dwInitialX += data.monitorOffsetX;
g_ScreenInfo[nScreenNum].dwInitialY += data.monitorOffsetY;
}
@ -399,6 +402,7 @@ ddxProcessArgument (int argc, char *argv[], int i)
{
winErrorFVerb (2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor);
g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
}

View File

@ -40,6 +40,7 @@
#include "winprefs.h"
#include "winconfig.h"
#include "winmsg.h"
#include "winmonitors.h"
#include "inputstr.h"
/*
@ -177,12 +178,9 @@ winWindowProc (HWND hwnd, UINT message,
break;
}
ErrorF ("winWindowProc - WM_DISPLAYCHANGE - new bpp: %d\n",
wParam);
ErrorF ("winWindowProc - WM_DISPLAYCHANGE - new width: %d "
"new height: %d\n",
LOWORD (lParam), HIWORD (lParam));
"new height: %d new bpp: %d\n",
LOWORD (lParam), HIWORD (lParam), wParam);
/*
* TrueColor --> TrueColor depth changes are disruptive for:
@ -254,6 +252,89 @@ winWindowProc (HWND hwnd, UINT message,
* the display dimensions change.
*/
{
#if CYGDEBUG
winDebug ("winWindowProc - WM_DISPLAYCHANGE - Recreated "
"primary surface\n");
#endif
/*
In rootless modes which are monitor or virtual desktop size
use RandR to resize the X screen
*/
if ((!s_pScreenInfo->fUserGaveHeightAndWidth) &&
(s_pScreenInfo->iResizeMode == resizeWithRandr) &&
(FALSE
#ifdef XWIN_MULTIWINDOWEXTWM
|| s_pScreenInfo->fMWExtWM
#endif
|| s_pScreenInfo->fRootless
#ifdef XWIN_MULTIWINDOW
|| s_pScreenInfo->fMultiWindow
#endif
))
{
DWORD dwWidth, dwHeight;
if (s_pScreenInfo->fMultipleMonitors)
{
/* resize to new virtual desktop size */
dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
else
{
/* resize to new size of specified monitor */
struct GetMonitorInfoData data;
if (QueryMonitor(s_pScreenInfo->iMonitor, &data))
{
if (data.bMonitorSpecifiedExists == TRUE)
{
dwWidth = data.monitorWidth;
dwHeight = data.monitorHeight;
/*
XXX: monitor may have changed position,
so we might need to update xinerama data
*/
}
else
{
ErrorF ("Monitor number %d no longer exists!\n", s_pScreenInfo->iMonitor);
}
}
}
/*
XXX: probably a small bug here: we don't compute the work area
and allow for task bar
XXX: generally, we don't allow for the task bar being moved after
the server is started
*/
/* Set screen size to match new size, if it is different to current */
if ((s_pScreenInfo->dwWidth != dwWidth) ||
(s_pScreenInfo->dwHeight != dwHeight))
{
winDoRandRScreenSetSize(s_pScreen,
dwWidth,
dwHeight,
(dwWidth * 25.4) / monitorResolution,
(dwHeight * 25.4) / monitorResolution);
}
}
else
{
/*
If we get here, we are either windowed and using the GDI engine
or windowed and non-fullscreen using any engine
*/
/*
* For ddraw engines, we need to (try to) recreate the same-sized primary surface
* when display dimensions change (but not depth, that is disruptive)
*/
/*
* NOTE: The non-DirectDraw engines set the ReleasePrimarySurface
* and CreatePrimarySurface function pointers to point
@ -262,33 +343,14 @@ winWindowProc (HWND hwnd, UINT message,
* relevant to the current engine (e.g., Shadow GDI).
*/
#if CYGDEBUG
winDebug ("winWindowProc - WM_DISPLAYCHANGE - Dimensions changed\n");
#endif
winDebug ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n");
/* Release the old primary surface */
(*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
#if CYGDEBUG
winDebug ("winWindowProc - WM_DISPLAYCHANGE - Released "
"primary surface\n");
#endif
/* Create the new primary surface */
(*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
#if CYGDEBUG
winDebug ("winWindowProc - WM_DISPLAYCHANGE - Recreated "
"primary surface\n");
#endif
#if 0
/* Multi-Window mode uses RandR for resizes */
if (s_pScreenInfo->fMultiWindow)
{
RRSetScreenConfig ();
}
#endif
}
break;