2 * Minimal implementation of PanoramiX/Xinerama
4 * This is used in rootless mode where the underlying window server
5 * already provides an abstracted view of multiple screens as one
8 * This code is largely based on panoramiX.c, which contains the
9 * following copyright notice:
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.
19 The above copyright notice and this permission notice shall be included in
20 all copies or substantial portions of the Software.
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.
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 ******************************************************************/
36 #ifdef HAVE_DIX_CONFIG_H
37 #include <dix-config.h>
40 #include "pseudoramiX.h"
41 #include "extnsionst.h"
43 #include "dixstruct.h"
45 #include <X11/extensions/panoramiXproto.h>
48 #define TRACE PseudoramiXTrace("TRACE " __FILE__ ":%s",__FUNCTION__)
49 #define DEBUG_LOG PseudoramiXDebug
51 Bool noPseudoramiXExtension = FALSE;
54 ProcPanoramiXQueryVersion(ClientPtr client);
57 PseudoramiXResetProc(ExtensionEntry *extEntry);
60 ProcPseudoramiXQueryVersion(ClientPtr client);
62 ProcPseudoramiXGetState(ClientPtr client);
64 ProcPseudoramiXGetScreenCount(ClientPtr client);
66 ProcPseudoramiXGetScreenSize(ClientPtr client);
68 ProcPseudoramiXIsActive(ClientPtr client);
70 ProcPseudoramiXQueryScreens(ClientPtr client);
72 ProcPseudoramiXDispatch(ClientPtr client);
75 SProcPseudoramiXQueryVersion(ClientPtr client);
77 SProcPseudoramiXGetState(ClientPtr client);
79 SProcPseudoramiXGetScreenCount(ClientPtr client);
81 SProcPseudoramiXGetScreenSize(ClientPtr client);
83 SProcPseudoramiXIsActive(ClientPtr client);
85 SProcPseudoramiXQueryScreens(ClientPtr client);
87 SProcPseudoramiXDispatch(ClientPtr client);
94 } PseudoramiXScreenRec;
96 static PseudoramiXScreenRec *pseudoramiXScreens = NULL;
97 static int pseudoramiXScreensAllocated = 0;
98 static int pseudoramiXNumScreens = 0;
99 static unsigned long pseudoramiXGeneration = 0;
102 PseudoramiXTrace(const char *format, ...)
103 _X_ATTRIBUTE_PRINTF(1, 2);
106 PseudoramiXTrace(const char *format, ...)
110 va_start(ap, format);
111 LogVMessageVerb(X_NONE, 10, format, ap);
116 PseudoramiXDebug(const char *format, ...)
117 _X_ATTRIBUTE_PRINTF(1, 2);
120 PseudoramiXDebug(const char *format, ...)
124 va_start(ap, format);
125 LogVMessageVerb(X_NONE, 3, format, ap);
129 // Add a PseudoramiX screen.
130 // The rest of the X server will know nothing about this screen.
131 // Can be called before or after extension init.
132 // Screens must be re-added once per generation.
134 PseudoramiXAddScreen(int x, int y, int w, int h)
136 PseudoramiXScreenRec *s;
138 if (noPseudoramiXExtension) return;
140 if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) {
141 pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1;
142 pseudoramiXScreens = realloc(pseudoramiXScreens,
143 pseudoramiXScreensAllocated *
144 sizeof(PseudoramiXScreenRec));
147 DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h);
149 s = &pseudoramiXScreens[pseudoramiXNumScreens++];
156 // Initialize PseudoramiX.
157 // Copied from PanoramiXExtensionInit
159 PseudoramiXExtensionInit(void)
161 Bool success = FALSE;
162 ExtensionEntry *extEntry;
164 if (noPseudoramiXExtension) return;
168 /* Even with only one screen we need to enable PseudoramiX to allow
169 dynamic screen configuration changes. */
171 if (pseudoramiXNumScreens == 1) {
172 // Only one screen - disable Xinerama extension.
173 noPseudoramiXExtension = TRUE;
178 if (pseudoramiXGeneration != serverGeneration) {
179 extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
180 ProcPseudoramiXDispatch,
181 SProcPseudoramiXDispatch,
182 PseudoramiXResetProc,
183 StandardMinorOpcode);
185 ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
188 pseudoramiXGeneration = serverGeneration;
194 ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
195 PANORAMIX_PROTOCOL_NAME);
201 PseudoramiXResetScreens(void)
205 pseudoramiXNumScreens = 0;
209 PseudoramiXResetProc(ExtensionEntry *extEntry)
213 PseudoramiXResetScreens();
218 ProcPseudoramiXQueryVersion(ClientPtr client)
222 return ProcPanoramiXQueryVersion(client);
227 ProcPseudoramiXGetState(ClientPtr client)
229 REQUEST(xPanoramiXGetStateReq);
231 xPanoramiXGetStateReply rep;
236 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
237 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
243 rep.sequenceNumber = client->sequence;
244 rep.state = !noPseudoramiXExtension;
245 rep.window = stuff->window;
246 if (client->swapped) {
247 swaps(&rep.sequenceNumber);
251 WriteToClient(client, sizeof(xPanoramiXGetStateReply),&rep);
257 ProcPseudoramiXGetScreenCount(ClientPtr client)
259 REQUEST(xPanoramiXGetScreenCountReq);
261 xPanoramiXGetScreenCountReply rep;
266 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
267 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
273 rep.sequenceNumber = client->sequence;
274 rep.ScreenCount = pseudoramiXNumScreens;
275 rep.window = stuff->window;
276 if (client->swapped) {
277 swaps(&rep.sequenceNumber);
281 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply),&rep);
287 ProcPseudoramiXGetScreenSize(ClientPtr client)
289 REQUEST(xPanoramiXGetScreenSizeReq);
291 xPanoramiXGetScreenSizeReply rep;
296 if (stuff->screen >= pseudoramiXNumScreens)
299 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
300 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
306 rep.sequenceNumber = client->sequence;
307 /* screen dimensions */
308 rep.width = pseudoramiXScreens[stuff->screen].w;
309 // was screenInfo.screens[stuff->screen]->width;
310 rep.height = pseudoramiXScreens[stuff->screen].h;
311 // was screenInfo.screens[stuff->screen]->height;
312 rep.window = stuff->window;
313 rep.screen = stuff->screen;
314 if (client->swapped) {
315 swaps(&rep.sequenceNumber);
322 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply),&rep);
328 ProcPseudoramiXIsActive(ClientPtr client)
330 /* REQUEST(xXineramaIsActiveReq); */
331 xXineramaIsActiveReply rep;
335 REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
339 rep.sequenceNumber = client->sequence;
340 rep.state = !noPseudoramiXExtension;
341 if (client->swapped) {
342 swaps(&rep.sequenceNumber);
346 WriteToClient(client, sizeof(xXineramaIsActiveReply),&rep);
352 ProcPseudoramiXQueryScreens(ClientPtr client)
354 /* REQUEST(xXineramaQueryScreensReq); */
355 xXineramaQueryScreensReply rep;
357 DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n",
358 noPseudoramiXExtension,
359 pseudoramiXNumScreens);
361 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
364 rep.sequenceNumber = client->sequence;
365 rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens;
366 rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
367 if (client->swapped) {
368 swaps(&rep.sequenceNumber);
372 WriteToClient(client, sizeof(xXineramaQueryScreensReply),&rep);
374 if (!noPseudoramiXExtension) {
375 xXineramaScreenInfo scratch;
378 for (i = 0; i < pseudoramiXNumScreens; i++) {
379 scratch.x_org = pseudoramiXScreens[i].x;
380 scratch.y_org = pseudoramiXScreens[i].y;
381 scratch.width = pseudoramiXScreens[i].w;
382 scratch.height = pseudoramiXScreens[i].h;
384 if (client->swapped) {
385 swaps(&scratch.x_org);
386 swaps(&scratch.y_org);
387 swaps(&scratch.width);
388 swaps(&scratch.height);
390 WriteToClient(client, sz_XineramaScreenInfo,&scratch);
399 ProcPseudoramiXDispatch(ClientPtr client)
403 switch (stuff->data) {
404 case X_PanoramiXQueryVersion:
405 return ProcPseudoramiXQueryVersion(client);
407 case X_PanoramiXGetState:
408 return ProcPseudoramiXGetState(client);
410 case X_PanoramiXGetScreenCount:
411 return ProcPseudoramiXGetScreenCount(client);
413 case X_PanoramiXGetScreenSize:
414 return ProcPseudoramiXGetScreenSize(client);
416 case X_XineramaIsActive:
417 return ProcPseudoramiXIsActive(client);
419 case X_XineramaQueryScreens:
420 return ProcPseudoramiXQueryScreens(client);
426 SProcPseudoramiXQueryVersion(ClientPtr client)
428 REQUEST(xPanoramiXQueryVersionReq);
432 swaps(&stuff->length);
433 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
434 return ProcPseudoramiXQueryVersion(client);
438 SProcPseudoramiXGetState(ClientPtr client)
440 REQUEST(xPanoramiXGetStateReq);
444 swaps(&stuff->length);
445 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
446 return ProcPseudoramiXGetState(client);
450 SProcPseudoramiXGetScreenCount(ClientPtr client)
452 REQUEST(xPanoramiXGetScreenCountReq);
456 swaps(&stuff->length);
457 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
458 return ProcPseudoramiXGetScreenCount(client);
462 SProcPseudoramiXGetScreenSize(ClientPtr client)
464 REQUEST(xPanoramiXGetScreenSizeReq);
468 swaps(&stuff->length);
469 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
470 return ProcPseudoramiXGetScreenSize(client);
474 SProcPseudoramiXIsActive(ClientPtr client)
476 REQUEST(xXineramaIsActiveReq);
480 swaps(&stuff->length);
481 REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
482 return ProcPseudoramiXIsActive(client);
486 SProcPseudoramiXQueryScreens(ClientPtr client)
488 REQUEST(xXineramaQueryScreensReq);
492 swaps(&stuff->length);
493 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
494 return ProcPseudoramiXQueryScreens(client);
498 SProcPseudoramiXDispatch(ClientPtr client)
504 switch (stuff->data) {
505 case X_PanoramiXQueryVersion:
506 return SProcPseudoramiXQueryVersion(client);
508 case X_PanoramiXGetState:
509 return SProcPseudoramiXGetState(client);
511 case X_PanoramiXGetScreenCount:
512 return SProcPseudoramiXGetScreenCount(client);
514 case X_PanoramiXGetScreenSize:
515 return SProcPseudoramiXGetScreenSize(client);
517 case X_XineramaIsActive:
518 return SProcPseudoramiXIsActive(client);
520 case X_XineramaQueryScreens:
521 return SProcPseudoramiXQueryScreens(client);