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