1/* 2 *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved. 3 *Copyright (C) 2009-2010 Jon TURNEY 4 * 5 *Permission is hereby granted, free of charge, to any person obtaining 6 *a copy of this software and associated documentation files (the 7 *"Software"), to deal in the Software without restriction, including 8 *without limitation the rights to use, copy, modify, merge, publish, 9 *distribute, sublicense, and/or sell copies of the Software, and to 10 *permit persons to whom the Software is furnished to do so, subject to 11 *the following conditions: 12 * 13 *The above copyright notice and this permission notice shall be 14 *included in all copies or substantial portions of the Software. 15 * 16 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR 20 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 21 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 *Except as contained in this notice, the name of the author(s) 25 *shall not be used in advertising or otherwise to promote the sale, use 26 *or other dealings in this Software without prior written authorization 27 *from the author(s) 28 * 29 * Authors: Harold L Hunt II 30 * Jon TURNEY 31 */ 32 33#ifdef HAVE_XWIN_CONFIG_H 34#include <xwin-config.h> 35#endif 36#include "win.h" 37#include "mivalidate.h" // for union _Validate used by windowstr.h 38 39#ifndef RANDR_12_INTERFACE 40#error X server must have RandR 1.2 interface 41#endif 42 43 44/* 45 * Answer queries about the RandR features supported. 46 */ 47 48static Bool 49winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) 50{ 51 winDebug ("winRandRGetInfo ()\n"); 52 53 /* Don't support rotations */ 54 *pRotations = RR_Rotate_0; 55 56 /* 57 The screen doesn't have to be limited to the actual 58 monitor size (we can have scrollbars :-), so what is 59 the upper limit? 60 */ 61 RRScreenSetSizeRange(pScreen, 0, 0, 4096, 4096); 62 63 return TRUE; 64} 65 66 67/* 68 Copied from the xfree86 DDX 69 70 Why can't this be in DIX? 71 Does union _Validate vary depending on DDX?? 72 */ 73static void 74xf86SetRootClip (ScreenPtr pScreen, Bool enable) 75{ 76 WindowPtr pWin = pScreen->root; 77 WindowPtr pChild; 78 Bool WasViewable = (Bool)(pWin->viewable); 79 Bool anyMarked = FALSE; 80 WindowPtr pLayerWin; 81 BoxRec box; 82 83 if (WasViewable) 84 { 85 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) 86 { 87 (void) (*pScreen->MarkOverlappedWindows)(pChild, 88 pChild, 89 &pLayerWin); 90 } 91 (*pScreen->MarkWindow) (pWin); 92 anyMarked = TRUE; 93 if (pWin->valdata) 94 { 95 if (HasBorder (pWin)) 96 { 97 RegionPtr borderVisible; 98 99 borderVisible = REGION_CREATE(pScreen, NullBox, 1); 100 REGION_SUBTRACT(pScreen, borderVisible, 101 &pWin->borderClip, &pWin->winSize); 102 pWin->valdata->before.borderVisible = borderVisible; 103 } 104 pWin->valdata->before.resized = TRUE; 105 } 106 } 107 108 /* 109 * Use REGION_BREAK to avoid optimizations in ValidateTree 110 * that assume the root borderClip can't change well, normally 111 * it doesn't...) 112 */ 113 if (enable) 114 { 115 box.x1 = 0; 116 box.y1 = 0; 117 box.x2 = pScreen->width; 118 box.y2 = pScreen->height; 119 REGION_INIT (pScreen, &pWin->winSize, &box, 1); 120 REGION_INIT (pScreen, &pWin->borderSize, &box, 1); 121 if (WasViewable) 122 REGION_RESET(pScreen, &pWin->borderClip, &box); 123 pWin->drawable.width = pScreen->width; 124 pWin->drawable.height = pScreen->height; 125 REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); 126 } 127 else 128 { 129 REGION_EMPTY(pScreen, &pWin->borderClip); 130 REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); 131 } 132 133 ResizeChildrenWinSize (pWin, 0, 0, 0, 0); 134 135 if (WasViewable) 136 { 137 if (pWin->firstChild) 138 { 139 anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, 140 pWin->firstChild, 141 (WindowPtr *)NULL); 142 } 143 else 144 { 145 (*pScreen->MarkWindow) (pWin); 146 anyMarked = TRUE; 147 } 148 149 150 if (anyMarked) 151 (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); 152 } 153 154 if (WasViewable) 155 { 156 if (anyMarked) 157 (*pScreen->HandleExposures)(pWin); 158 if (anyMarked && pScreen->PostValidateTree) 159 (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); 160 } 161 if (pWin->realized) 162 WindowsRestructured (); 163 FlushAllOutput (); 164} 165 166/* 167 168*/ 169void 170winDoRandRScreenSetSize (ScreenPtr pScreen, 171 CARD16 width, 172 CARD16 height, 173 CARD32 mmWidth, 174 CARD32 mmHeight) 175{ 176 winScreenPriv(pScreen); 177 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 178 WindowPtr pRoot = pScreen->root; 179 180 // Prevent screen updates while we change things around 181 xf86SetRootClip(pScreen, FALSE); 182 183 /* Update the screen size as requested */ 184 pScreenInfo->dwWidth = width; 185 pScreenInfo->dwHeight = height; 186 187 /* Reallocate the framebuffer used by the drawing engine */ 188 (*pScreenPriv->pwinFreeFB)(pScreen); 189 if (!(*pScreenPriv->pwinAllocateFB)(pScreen)) 190 { 191 ErrorF ("winDoRandRScreenSetSize - Could not reallocate framebuffer\n"); 192 } 193 194 pScreen->width = width; 195 pScreen->height = height; 196 pScreen->mmWidth = mmWidth; 197 pScreen->mmHeight = mmHeight; 198 199 /* Update the screen pixmap to point to the new framebuffer */ 200 winUpdateFBPointer(pScreen, pScreenInfo->pfb); 201 202 // pScreen->devPrivate == pScreen->GetScreenPixmap(screen) ? 203 // resize the root window 204 //pScreen->ResizeWindow(pRoot, 0, 0, width, height, NULL); 205 // does this emit a ConfigureNotify?? 206 207 // Restore the ability to update screen, now with new dimensions 208 xf86SetRootClip(pScreen, TRUE); 209 210 // and arrange for it to be repainted 211 miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); 212 213 /* Indicate that a screen size change took place */ 214 RRScreenSizeNotify(pScreen); 215} 216 217/* 218 * Respond to resize request 219 */ 220static 221Bool 222winRandRScreenSetSize (ScreenPtr pScreen, 223 CARD16 width, 224 CARD16 height, 225 CARD16 pixWidth, 226 CARD16 pixHeight, 227 CARD32 mmWidth, 228 CARD32 mmHeight) 229{ 230 winScreenPriv(pScreen); 231 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 232 233 winDebug ("winRandRScreenSetSize ()\n"); 234 235 /* 236 It doesn't currently make sense to allow resize in fullscreen mode 237 (we'd actually have to list the supported resolutions) 238 */ 239 if (pScreenInfo->fFullScreen) 240 { 241 ErrorF ("winRandRScreenSetSize - resize not supported in fullscreen mode\n"); 242 return FALSE; 243 } 244 245 /* 246 Client resize requests aren't allowed in rootless modes, even if 247 the X screen is monitor or virtual desktop size, we'd need to 248 resize the native display size 249 */ 250 if (FALSE 251#ifdef XWIN_MULTIWINDOWEXTWM 252 || pScreenInfo->fMWExtWM 253#endif 254 || pScreenInfo->fRootless 255#ifdef XWIN_MULTIWINDOW 256 || pScreenInfo->fMultiWindow 257#endif 258 ) 259 { 260 ErrorF ("winRandRScreenSetSize - resize not supported in rootless modes\n"); 261 return FALSE; 262 } 263 264 winDoRandRScreenSetSize(pScreen, width, height, mmWidth, mmHeight); 265 266 /* Cause the native window for the screen to resize itself */ 267 { 268 DWORD dwStyle, dwExStyle; 269 RECT rcClient; 270 271 rcClient.left = 0; 272 rcClient.top = 0; 273 rcClient.right = width; 274 rcClient.bottom = height; 275 276 ErrorF ("winRandRScreenSetSize new client area w: %d h: %d\n", width, height); 277 278 /* Get the Windows window style and extended style */ 279 dwExStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_EXSTYLE); 280 dwStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_STYLE); 281 282 /* 283 * Calculate the window size needed for the given client area 284 * adjusting for any decorations it will have 285 */ 286 AdjustWindowRectEx(&rcClient, dwStyle, FALSE, dwExStyle); 287 288 ErrorF ("winRandRScreenSetSize new window area w: %ld h: %ld\n", rcClient.right-rcClient.left, rcClient.bottom-rcClient.top); 289 290 SetWindowPos(pScreenPriv->hwndScreen, NULL, 291 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, 292 SWP_NOZORDER | SWP_NOMOVE); 293 } 294 295 return TRUE; 296} 297 298/* 299 * Initialize the RandR layer. 300 */ 301 302Bool 303winRandRInit (ScreenPtr pScreen) 304{ 305 rrScrPrivPtr pRRScrPriv; 306 winDebug ("winRandRInit ()\n"); 307 308 if (!RRScreenInit (pScreen)) 309 { 310 ErrorF ("winRandRInit () - RRScreenInit () failed\n"); 311 return FALSE; 312 } 313 314 /* Set some RandR function pointers */ 315 pRRScrPriv = rrGetScrPriv (pScreen); 316 pRRScrPriv->rrGetInfo = winRandRGetInfo; 317 pRRScrPriv->rrSetConfig = NULL; 318 pRRScrPriv->rrScreenSetSize = winRandRScreenSetSize; 319 pRRScrPriv->rrCrtcSet = NULL; 320 pRRScrPriv->rrCrtcSetGamma = NULL; 321 322 return TRUE; 323} 324