winrandr.c revision 1b5d61b8
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 || 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 278 /* 279 The screen doesn't have to be limited to the actual 280 monitor size (we can have scrollbars :-), so set the 281 upper limit to the maximum coordinates X11 can use. 282 */ 283 RRScreenSetSizeRange(pScreen, 0, 0, 32768, 32768); 284 285 return TRUE; 286} 287