pseudoramiX.c revision 706f2543
1/* 2 * Minimal implementation of PanoramiX/Xinerama 3 * 4 * This is used in rootless mode where the underlying window server 5 * already provides an abstracted view of multiple screens as one 6 * large screen area. 7 * 8 * This code is largely based on panoramiX.c, which contains the 9 * following copyright notice: 10 */ 11/***************************************************************** 12Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 13Permission is hereby granted, free of charge, to any person obtaining a copy 14of this software and associated documentation files (the "Software"), to deal 15in the Software without restriction, including without limitation the rights 16to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17copies of the Software. 18 19The above copyright notice and this permission notice shall be included in 20all copies or substantial portions of the Software. 21 22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 26BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 27WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 28IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 30Except as contained in this notice, the name of Digital Equipment Corporation 31shall not be used in advertising or otherwise to promote the sale, use or other 32dealings in this Software without prior written authorization from Digital 33Equipment Corporation. 34******************************************************************/ 35 36#ifdef HAVE_DIX_CONFIG_H 37#include <dix-config.h> 38#endif 39 40#include "darwin.h" 41#include "pseudoramiX.h" 42#include "extnsionst.h" 43#include "dixstruct.h" 44#include "window.h" 45#include <X11/extensions/panoramiXproto.h> 46#include "globals.h" 47 48Bool noPseudoramiXExtension = FALSE; 49 50extern int ProcPanoramiXQueryVersion (ClientPtr client); 51 52static void PseudoramiXResetProc(ExtensionEntry *extEntry); 53 54static int ProcPseudoramiXQueryVersion(ClientPtr client); 55static int ProcPseudoramiXGetState(ClientPtr client); 56static int ProcPseudoramiXGetScreenCount(ClientPtr client); 57static int ProcPseudoramiXGetScreenSize(ClientPtr client); 58static int ProcPseudoramiXIsActive(ClientPtr client); 59static int ProcPseudoramiXQueryScreens(ClientPtr client); 60static int ProcPseudoramiXDispatch(ClientPtr client); 61 62static int SProcPseudoramiXQueryVersion(ClientPtr client); 63static int SProcPseudoramiXGetState(ClientPtr client); 64static int SProcPseudoramiXGetScreenCount(ClientPtr client); 65static int SProcPseudoramiXGetScreenSize(ClientPtr client); 66static int SProcPseudoramiXIsActive(ClientPtr client); 67static int SProcPseudoramiXQueryScreens(ClientPtr client); 68static int SProcPseudoramiXDispatch(ClientPtr client); 69 70 71typedef struct { 72 int x; 73 int y; 74 int w; 75 int h; 76} PseudoramiXScreenRec; 77 78static PseudoramiXScreenRec *pseudoramiXScreens = NULL; 79static int pseudoramiXScreensAllocated = 0; 80static int pseudoramiXNumScreens = 0; 81static unsigned long pseudoramiXGeneration = 0; 82 83 84// Add a PseudoramiX screen. 85// The rest of the X server will know nothing about this screen. 86// Can be called before or after extension init. 87// Screens must be re-added once per generation. 88void 89PseudoramiXAddScreen(int x, int y, int w, int h) 90{ 91 PseudoramiXScreenRec *s; 92 93 if (noPseudoramiXExtension) return; 94 95 if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) { 96 pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1; 97 pseudoramiXScreens = realloc(pseudoramiXScreens, 98 pseudoramiXScreensAllocated * 99 sizeof(PseudoramiXScreenRec)); 100 } 101 102 DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h); 103 104 s = &pseudoramiXScreens[pseudoramiXNumScreens++]; 105 s->x = x; 106 s->y = y; 107 s->w = w; 108 s->h = h; 109} 110 111 112// Initialize PseudoramiX. 113// Copied from PanoramiXExtensionInit 114void PseudoramiXExtensionInit(int argc, char *argv[]) 115{ 116 Bool success = FALSE; 117 ExtensionEntry *extEntry; 118 119 if (noPseudoramiXExtension) return; 120 121 TRACE(); 122 123 /* Even with only one screen we need to enable PseudoramiX to allow 124 dynamic screen configuration changes. */ 125#if 0 126 if (pseudoramiXNumScreens == 1) { 127 // Only one screen - disable Xinerama extension. 128 noPseudoramiXExtension = TRUE; 129 return; 130 } 131#endif 132 133 if (pseudoramiXGeneration != serverGeneration) { 134 extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0, 135 ProcPseudoramiXDispatch, 136 SProcPseudoramiXDispatch, 137 PseudoramiXResetProc, 138 StandardMinorOpcode); 139 if (!extEntry) { 140 ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n"); 141 } else { 142 pseudoramiXGeneration = serverGeneration; 143 success = TRUE; 144 } 145 } 146 147 if (!success) { 148 ErrorF("%s Extension (PseudoramiX) failed to initialize\n", 149 PANORAMIX_PROTOCOL_NAME); 150 return; 151 } 152} 153 154 155void PseudoramiXResetScreens(void) 156{ 157 TRACE(); 158 159 pseudoramiXNumScreens = 0; 160} 161 162 163static void PseudoramiXResetProc(ExtensionEntry *extEntry) 164{ 165 TRACE(); 166 167 PseudoramiXResetScreens(); 168} 169 170 171// was PanoramiX 172static int ProcPseudoramiXQueryVersion(ClientPtr client) 173{ 174 TRACE(); 175 176 return ProcPanoramiXQueryVersion(client); 177} 178 179 180// was PanoramiX 181static int ProcPseudoramiXGetState(ClientPtr client) 182{ 183 REQUEST(xPanoramiXGetStateReq); 184 WindowPtr pWin; 185 xPanoramiXGetStateReply rep; 186 register int n, rc; 187 188 TRACE(); 189 190 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 191 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 192 if (rc != Success) 193 return rc; 194 195 rep.type = X_Reply; 196 rep.length = 0; 197 rep.sequenceNumber = client->sequence; 198 rep.state = !noPseudoramiXExtension; 199 if (client->swapped) { 200 swaps (&rep.sequenceNumber, n); 201 swapl (&rep.length, n); 202 swaps (&rep.state, n); 203 } 204 WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); 205 return Success; 206} 207 208 209// was PanoramiX 210static int ProcPseudoramiXGetScreenCount(ClientPtr client) 211{ 212 REQUEST(xPanoramiXGetScreenCountReq); 213 WindowPtr pWin; 214 xPanoramiXGetScreenCountReply rep; 215 register int n, rc; 216 217 TRACE(); 218 219 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 220 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 221 if (rc != Success) 222 return rc; 223 224 rep.type = X_Reply; 225 rep.length = 0; 226 rep.sequenceNumber = client->sequence; 227 rep.ScreenCount = pseudoramiXNumScreens; 228 if (client->swapped) { 229 swaps (&rep.sequenceNumber, n); 230 swapl (&rep.length, n); 231 swaps (&rep.ScreenCount, n); 232 } 233 WriteToClient (client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 234 return Success; 235} 236 237 238// was PanoramiX 239static int ProcPseudoramiXGetScreenSize(ClientPtr client) 240{ 241 REQUEST(xPanoramiXGetScreenSizeReq); 242 WindowPtr pWin; 243 xPanoramiXGetScreenSizeReply rep; 244 register int n, rc; 245 246 TRACE(); 247 248 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 249 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 250 if (rc != Success) 251 return rc; 252 253 rep.type = X_Reply; 254 rep.length = 0; 255 rep.sequenceNumber = client->sequence; 256 /* screen dimensions */ 257 rep.width = pseudoramiXScreens[stuff->screen].w; 258 // was screenInfo.screens[stuff->screen]->width; 259 rep.height = pseudoramiXScreens[stuff->screen].h; 260 // was screenInfo.screens[stuff->screen]->height; 261 if (client->swapped) { 262 swaps (&rep.sequenceNumber, n); 263 swapl (&rep.length, n); 264 swaps (&rep.width, n); 265 swaps (&rep.height, n); 266 } 267 WriteToClient (client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 268 return Success; 269} 270 271 272// was Xinerama 273static int ProcPseudoramiXIsActive(ClientPtr client) 274{ 275 /* REQUEST(xXineramaIsActiveReq); */ 276 xXineramaIsActiveReply rep; 277 278 TRACE(); 279 280 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 281 282 rep.type = X_Reply; 283 rep.length = 0; 284 rep.sequenceNumber = client->sequence; 285 rep.state = !noPseudoramiXExtension; 286 if (client->swapped) { 287 register int n; 288 swaps (&rep.sequenceNumber, n); 289 swapl (&rep.length, n); 290 swapl (&rep.state, n); 291 } 292 WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); 293 return Success; 294} 295 296 297// was Xinerama 298static int ProcPseudoramiXQueryScreens(ClientPtr client) 299{ 300 /* REQUEST(xXineramaQueryScreensReq); */ 301 xXineramaQueryScreensReply rep; 302 303 DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n", noPseudoramiXExtension, pseudoramiXNumScreens); 304 305 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 306 307 rep.type = X_Reply; 308 rep.sequenceNumber = client->sequence; 309 rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens; 310 rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); 311 if (client->swapped) { 312 register int n; 313 swaps (&rep.sequenceNumber, n); 314 swapl (&rep.length, n); 315 swapl (&rep.number, n); 316 } 317 WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); 318 319 if (!noPseudoramiXExtension) { 320 xXineramaScreenInfo scratch; 321 int i; 322 323 for(i = 0; i < pseudoramiXNumScreens; i++) { 324 scratch.x_org = pseudoramiXScreens[i].x; 325 scratch.y_org = pseudoramiXScreens[i].y; 326 scratch.width = pseudoramiXScreens[i].w; 327 scratch.height = pseudoramiXScreens[i].h; 328 329 if(client->swapped) { 330 register int n; 331 swaps (&scratch.x_org, n); 332 swaps (&scratch.y_org, n); 333 swaps (&scratch.width, n); 334 swaps (&scratch.height, n); 335 } 336 WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); 337 } 338 } 339 340 return Success; 341} 342 343 344// was PanoramiX 345static int ProcPseudoramiXDispatch (ClientPtr client) 346{ REQUEST(xReq); 347 TRACE(); 348 switch (stuff->data) 349 { 350 case X_PanoramiXQueryVersion: 351 return ProcPseudoramiXQueryVersion(client); 352 case X_PanoramiXGetState: 353 return ProcPseudoramiXGetState(client); 354 case X_PanoramiXGetScreenCount: 355 return ProcPseudoramiXGetScreenCount(client); 356 case X_PanoramiXGetScreenSize: 357 return ProcPseudoramiXGetScreenSize(client); 358 case X_XineramaIsActive: 359 return ProcPseudoramiXIsActive(client); 360 case X_XineramaQueryScreens: 361 return ProcPseudoramiXQueryScreens(client); 362 } 363 return BadRequest; 364} 365 366 367 368static int 369SProcPseudoramiXQueryVersion (ClientPtr client) 370{ 371 REQUEST(xPanoramiXQueryVersionReq); 372 register int n; 373 374 TRACE(); 375 376 swaps(&stuff->length,n); 377 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 378 return ProcPseudoramiXQueryVersion(client); 379} 380 381static int 382SProcPseudoramiXGetState(ClientPtr client) 383{ 384 REQUEST(xPanoramiXGetStateReq); 385 register int n; 386 387 TRACE(); 388 389 swaps (&stuff->length, n); 390 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 391 return ProcPseudoramiXGetState(client); 392} 393 394static int 395SProcPseudoramiXGetScreenCount(ClientPtr client) 396{ 397 REQUEST(xPanoramiXGetScreenCountReq); 398 register int n; 399 400 TRACE(); 401 402 swaps (&stuff->length, n); 403 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 404 return ProcPseudoramiXGetScreenCount(client); 405} 406 407static int 408SProcPseudoramiXGetScreenSize(ClientPtr client) 409{ 410 REQUEST(xPanoramiXGetScreenSizeReq); 411 register int n; 412 413 TRACE(); 414 415 swaps (&stuff->length, n); 416 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 417 return ProcPseudoramiXGetScreenSize(client); 418} 419 420 421static int 422SProcPseudoramiXIsActive(ClientPtr client) 423{ 424 REQUEST(xXineramaIsActiveReq); 425 register int n; 426 427 TRACE(); 428 429 swaps (&stuff->length, n); 430 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 431 return ProcPseudoramiXIsActive(client); 432} 433 434 435static int 436SProcPseudoramiXQueryScreens(ClientPtr client) 437{ 438 REQUEST(xXineramaQueryScreensReq); 439 register int n; 440 441 TRACE(); 442 443 swaps (&stuff->length, n); 444 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 445 return ProcPseudoramiXQueryScreens(client); 446} 447 448 449static int 450SProcPseudoramiXDispatch (ClientPtr client) 451{ REQUEST(xReq); 452 453 TRACE(); 454 455 switch (stuff->data) 456 { 457 case X_PanoramiXQueryVersion: 458 return SProcPseudoramiXQueryVersion(client); 459 case X_PanoramiXGetState: 460 return SProcPseudoramiXGetState(client); 461 case X_PanoramiXGetScreenCount: 462 return SProcPseudoramiXGetScreenCount(client); 463 case X_PanoramiXGetScreenSize: 464 return SProcPseudoramiXGetScreenSize(client); 465 case X_XineramaIsActive: 466 return SProcPseudoramiXIsActive(client); 467 case X_XineramaQueryScreens: 468 return SProcPseudoramiXQueryScreens(client); 469 } 470 return BadRequest; 471} 472