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