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 38/* 39 * Answer queries about the RandR features supported. 40 */ 41 42static Bool 43winRandRGetInfo(ScreenPtr pScreen, Rotation * pRotations) 44{ 45 winDebug("winRandRGetInfo ()\n"); 46 47 /* Don't support rotations */ 48 *pRotations = RR_Rotate_0; 49 50 return TRUE; 51} 52 53static void 54winRandRUpdateMode(ScreenPtr pScreen, RROutputPtr output) 55{ 56 /* Delete previous mode */ 57 if (output->modes[0]) 58 { 59 RRModeDestroy(output->modes[0]); 60 RRModeDestroy(output->crtc->mode); 61 } 62 63 /* Register current mode */ 64 { 65 xRRModeInfo modeInfo; 66 RRModePtr mode; 67 char name[100]; 68 69 memset(&modeInfo, '\0', sizeof(modeInfo)); 70 snprintf(name, sizeof(name), "%dx%d", pScreen->width, pScreen->height); 71 72 modeInfo.width = pScreen->width; 73 modeInfo.height = pScreen->height; 74 modeInfo.hTotal = pScreen->width; 75 modeInfo.vTotal = pScreen->height; 76 modeInfo.dotClock = 0; 77 modeInfo.nameLength = strlen(name); 78 mode = RRModeGet(&modeInfo, name); 79 80 output->modes[0] = mode; 81 output->numModes = 1; 82 83 mode = RRModeGet(&modeInfo, name); 84 output->crtc->mode = mode; 85 } 86} 87 88/* 89 90*/ 91void 92winDoRandRScreenSetSize(ScreenPtr pScreen, 93 CARD16 width, 94 CARD16 height, CARD32 mmWidth, CARD32 mmHeight) 95{ 96 rrScrPrivPtr pRRScrPriv; 97 winScreenPriv(pScreen); 98 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 99 WindowPtr pRoot = pScreen->root; 100 101 /* Ignore changes which do nothing */ 102 if ((pScreen->width == width) && (pScreen->height == height) && 103 (pScreen->mmWidth == mmWidth) && (pScreen->mmHeight == mmHeight)) 104 return; 105 106 // Prevent screen updates while we change things around 107 SetRootClip(pScreen, ROOT_CLIP_NONE); 108 109 /* Update the screen size as requested */ 110 pScreenInfo->dwWidth = width; 111 pScreenInfo->dwHeight = height; 112 113 /* Reallocate the framebuffer used by the drawing engine */ 114 (*pScreenPriv->pwinFreeFB) (pScreen); 115 if (!(*pScreenPriv->pwinAllocateFB) (pScreen)) { 116 ErrorF("winDoRandRScreenSetSize - Could not reallocate framebuffer\n"); 117 } 118 119 pScreen->width = width; 120 pScreen->height = height; 121 pScreen->mmWidth = mmWidth; 122 pScreen->mmHeight = mmHeight; 123 124 /* Update the screen pixmap to point to the new framebuffer */ 125 winUpdateFBPointer(pScreen, pScreenInfo->pfb); 126 127 // pScreen->devPrivate == pScreen->GetScreenPixmap(screen) ? 128 // resize the root window 129 //pScreen->ResizeWindow(pRoot, 0, 0, width, height, NULL); 130 // does this emit a ConfigureNotify?? 131 132 // Restore the ability to update screen, now with new dimensions 133 SetRootClip(pScreen, ROOT_CLIP_FULL); 134 135 // and arrange for it to be repainted 136 pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); 137 138 // Set mode to current display size 139 pRRScrPriv = rrGetScrPriv(pScreen); 140 winRandRUpdateMode(pScreen, pRRScrPriv->primaryOutput); 141 142 /* Indicate that a screen size change took place */ 143 RRScreenSizeNotify(pScreen); 144} 145 146/* 147 * Respond to resize request 148 */ 149static 150 Bool 151winRandRScreenSetSize(ScreenPtr pScreen, 152 CARD16 width, 153 CARD16 height, CARD32 mmWidth, CARD32 mmHeight) 154{ 155 winScreenPriv(pScreen); 156 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 157 158 winDebug("winRandRScreenSetSize ()\n"); 159 160 /* 161 It doesn't currently make sense to allow resize in fullscreen mode 162 (we'd actually have to list the supported resolutions) 163 */ 164 if (pScreenInfo->fFullScreen) { 165 ErrorF 166 ("winRandRScreenSetSize - resize not supported in fullscreen mode\n"); 167 return FALSE; 168 } 169 170 /* 171 Client resize requests aren't allowed in rootless modes, even if 172 the X screen is monitor or virtual desktop size, we'd need to 173 resize the native display size 174 */ 175 if (FALSE 176 || pScreenInfo->fRootless 177 || pScreenInfo->fMultiWindow 178 ) { 179 ErrorF 180 ("winRandRScreenSetSize - resize not supported in rootless modes\n"); 181 return FALSE; 182 } 183 184 winDoRandRScreenSetSize(pScreen, width, height, mmWidth, mmHeight); 185 186 /* Cause the native window for the screen to resize itself */ 187 { 188 DWORD dwStyle, dwExStyle; 189 RECT rcClient; 190 191 rcClient.left = 0; 192 rcClient.top = 0; 193 rcClient.right = width; 194 rcClient.bottom = height; 195 196 ErrorF("winRandRScreenSetSize new client area w: %d h: %d\n", width, 197 height); 198 199 /* Get the Windows window style and extended style */ 200 dwExStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_EXSTYLE); 201 dwStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_STYLE); 202 203 /* 204 * Calculate the window size needed for the given client area 205 * adjusting for any decorations it will have 206 */ 207 AdjustWindowRectEx(&rcClient, dwStyle, FALSE, dwExStyle); 208 209 ErrorF("winRandRScreenSetSize new window area w: %d h: %d\n", 210 (int)(rcClient.right - rcClient.left), 211 (int)(rcClient.bottom - rcClient.top)); 212 213 SetWindowPos(pScreenPriv->hwndScreen, NULL, 214 0, 0, rcClient.right - rcClient.left, 215 rcClient.bottom - rcClient.top, SWP_NOZORDER | SWP_NOMOVE); 216 } 217 218 return TRUE; 219} 220 221/* 222 * Initialize the RandR layer. 223 */ 224 225Bool 226winRandRInit(ScreenPtr pScreen) 227{ 228 rrScrPrivPtr pRRScrPriv; 229 230 winDebug("winRandRInit ()\n"); 231 232 if (!RRScreenInit(pScreen)) { 233 ErrorF("winRandRInit () - RRScreenInit () failed\n"); 234 return FALSE; 235 } 236 237 /* Set some RandR function pointers */ 238 pRRScrPriv = rrGetScrPriv(pScreen); 239 pRRScrPriv->rrGetInfo = winRandRGetInfo; 240 pRRScrPriv->rrSetConfig = NULL; 241 pRRScrPriv->rrScreenSetSize = winRandRScreenSetSize; 242 pRRScrPriv->rrCrtcSet = NULL; 243 pRRScrPriv->rrCrtcSetGamma = NULL; 244 245 /* Create a CRTC and an output for the screen, and hook them together */ 246 { 247 RRCrtcPtr crtc; 248 RROutputPtr output; 249 250 crtc = RRCrtcCreate(pScreen, NULL); 251 if (!crtc) 252 return FALSE; 253 254 crtc->rotations = RR_Rotate_0; 255 256 output = RROutputCreate(pScreen, "default", 7, NULL); 257 if (!output) 258 return FALSE; 259 260 RROutputSetCrtcs(output, &crtc, 1); 261 RROutputSetConnection(output, RR_Connected); 262 RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen)); 263 264 output->crtc = crtc; 265 266 /* Set crtc outputs (should use RRCrtcNotify?) */ 267 crtc->outputs = malloc(sizeof(RROutputPtr)); 268 crtc->outputs[0] = output; 269 crtc->numOutputs = 1; 270 271 pRRScrPriv->primaryOutput = output; 272 273 /* Ensure we have space for exactly one mode */ 274 output->modes = malloc(sizeof(RRModePtr)); 275 output->modes[0] = NULL; 276 277 /* Set mode to current display size */ 278 winRandRUpdateMode(pScreen, output); 279 280 /* Make up some physical dimensions */ 281 output->mmWidth = (pScreen->width * 25.4)/monitorResolution; 282 output->mmHeight = (pScreen->height * 25.4)/monitorResolution; 283 284 /* Allocate and make up a (fixed, linear) gamma ramp */ 285 { 286 int i; 287 RRCrtcGammaSetSize(crtc, 256); 288 for (i = 0; i < crtc->gammaSize; i++) { 289 crtc->gammaRed[i] = i << 8; 290 crtc->gammaBlue[i] = i << 8; 291 crtc->gammaGreen[i] = i << 8; 292 } 293 } 294 } 295 296 /* 297 The screen doesn't have to be limited to the actual 298 monitor size (we can have scrollbars :-), so set the 299 upper limit to the maximum coordinates X11 can use. 300 */ 301 RRScreenSetSizeRange(pScreen, 0, 0, 32768, 32768); 302 303 return TRUE; 304} 305