diff options
Diffstat (limited to 'hw/xwin/winrandr.c')
-rw-r--r-- | hw/xwin/winrandr.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/hw/xwin/winrandr.c b/hw/xwin/winrandr.c new file mode 100644 index 0000000..2484048 --- /dev/null +++ b/hw/xwin/winrandr.c @@ -0,0 +1,323 @@ +/* + *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved. + *Copyright (C) 2009-2010 Jon TURNEY + * + *Permission is hereby granted, free of charge, to any person obtaining + *a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the author(s) + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the author(s) + * + * Authors: Harold L Hunt II + * Jon TURNEY + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" +#include "mivalidate.h" // for union _Validate used by windowstr.h + +#ifndef RANDR_12_INTERFACE +#error X server must have RandR 1.2 interface +#endif + + +/* + * Answer queries about the RandR features supported. + */ + +static Bool +winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) +{ + winDebug ("winRandRGetInfo ()\n"); + + /* Don't support rotations */ + *pRotations = RR_Rotate_0; + + /* + The screen doesn't have to be limited to the actual + monitor size (we can have scrollbars :-), so what is + the upper limit? + */ + RRScreenSetSizeRange(pScreen, 0, 0, 4096, 4096); + + return TRUE; +} + + +/* + Copied from the xfree86 DDX + + Why can't this be in DIX? + Does union _Validate vary depending on DDX?? + */ +static void +xf86SetRootClip (ScreenPtr pScreen, Bool enable) +{ + WindowPtr pWin = pScreen->root; + WindowPtr pChild; + Bool WasViewable = (Bool)(pWin->viewable); + Bool anyMarked = FALSE; + WindowPtr pLayerWin; + BoxRec box; + + if (WasViewable) + { + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + (void) (*pScreen->MarkOverlappedWindows)(pChild, + pChild, + &pLayerWin); + } + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + /* + * Use REGION_BREAK to avoid optimizations in ValidateTree + * that assume the root borderClip can't change well, normally + * it doesn't...) + */ + if (enable) + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT (pScreen, &pWin->winSize, &box, 1); + REGION_INIT (pScreen, &pWin->borderSize, &box, 1); + if (WasViewable) + REGION_RESET(pScreen, &pWin->borderClip, &box); + pWin->drawable.width = pScreen->width; + pWin->drawable.height = pScreen->height; + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + else + { + REGION_EMPTY(pScreen, &pWin->borderClip); + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + + ResizeChildrenWinSize (pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->firstChild) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, + pWin->firstChild, + (WindowPtr *)NULL); + } + else + { + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + } + + + if (anyMarked) + (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); + } + + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pWin); + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + FlushAllOutput (); +} + +/* + +*/ +void +winDoRandRScreenSetSize (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + WindowPtr pRoot = pScreen->root; + + // Prevent screen updates while we change things around + xf86SetRootClip(pScreen, FALSE); + + /* Update the screen size as requested */ + pScreenInfo->dwWidth = width; + pScreenInfo->dwHeight = height; + + /* Reallocate the framebuffer used by the drawing engine */ + (*pScreenPriv->pwinFreeFB)(pScreen); + if (!(*pScreenPriv->pwinAllocateFB)(pScreen)) + { + ErrorF ("winDoRandRScreenSetSize - Could not reallocate framebuffer\n"); + } + + pScreen->width = width; + pScreen->height = height; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + + /* Update the screen pixmap to point to the new framebuffer */ + winUpdateFBPointer(pScreen, pScreenInfo->pfb); + + // pScreen->devPrivate == pScreen->GetScreenPixmap(screen) ? + // resize the root window + //pScreen->ResizeWindow(pRoot, 0, 0, width, height, NULL); + // does this emit a ConfigureNotify?? + + // Restore the ability to update screen, now with new dimensions + xf86SetRootClip(pScreen, TRUE); + + // and arrange for it to be repainted + miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + + /* Indicate that a screen size change took place */ + RRScreenSizeNotify(pScreen); +} + +/* + * Respond to resize request + */ +static +Bool +winRandRScreenSetSize (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD16 pixWidth, + CARD16 pixHeight, + CARD32 mmWidth, + CARD32 mmHeight) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + winDebug ("winRandRScreenSetSize ()\n"); + + /* + It doesn't currently make sense to allow resize in fullscreen mode + (we'd actually have to list the supported resolutions) + */ + if (pScreenInfo->fFullScreen) + { + ErrorF ("winRandRScreenSetSize - resize not supported in fullscreen mode\n"); + return FALSE; + } + + /* + Client resize requests aren't allowed in rootless modes, even if + the X screen is monitor or virtual desktop size, we'd need to + resize the native display size + */ + if (FALSE +#ifdef XWIN_MULTIWINDOWEXTWM + || pScreenInfo->fMWExtWM +#endif + || pScreenInfo->fRootless +#ifdef XWIN_MULTIWINDOW + || pScreenInfo->fMultiWindow +#endif + ) + { + ErrorF ("winRandRScreenSetSize - resize not supported in rootless modes\n"); + return FALSE; + } + + winDoRandRScreenSetSize(pScreen, width, height, mmWidth, mmHeight); + + /* Cause the native window for the screen to resize itself */ + { + DWORD dwStyle, dwExStyle; + RECT rcClient; + + rcClient.left = 0; + rcClient.top = 0; + rcClient.right = width; + rcClient.bottom = height; + + ErrorF ("winRandRScreenSetSize new client area w: %d h: %d\n", width, height); + + /* Get the Windows window style and extended style */ + dwExStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_EXSTYLE); + dwStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_STYLE); + + /* + * Calculate the window size needed for the given client area + * adjusting for any decorations it will have + */ + AdjustWindowRectEx(&rcClient, dwStyle, FALSE, dwExStyle); + + ErrorF ("winRandRScreenSetSize new window area w: %ld h: %ld\n", rcClient.right-rcClient.left, rcClient.bottom-rcClient.top); + + SetWindowPos(pScreenPriv->hwndScreen, NULL, + 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, + SWP_NOZORDER | SWP_NOMOVE); + } + + return TRUE; +} + +/* + * Initialize the RandR layer. + */ + +Bool +winRandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr pRRScrPriv; + winDebug ("winRandRInit ()\n"); + + if (!RRScreenInit (pScreen)) + { + ErrorF ("winRandRInit () - RRScreenInit () failed\n"); + return FALSE; + } + + /* Set some RandR function pointers */ + pRRScrPriv = rrGetScrPriv (pScreen); + pRRScrPriv->rrGetInfo = winRandRGetInfo; + pRRScrPriv->rrSetConfig = NULL; + pRRScrPriv->rrScreenSetSize = winRandRScreenSetSize; + pRRScrPriv->rrCrtcSet = NULL; + pRRScrPriv->rrCrtcSetGamma = NULL; + + return TRUE; +} |