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
, ...)
106 va_start(ap
, format
);
107 LogVMessageVerb(X_NONE
, 10, format
, ap
);
112 PseudoramiXDebug(const char *format
, ...)
116 va_start(ap
, format
);
117 LogVMessageVerb(X_NONE
, 3, format
, ap
);
121 // Add a PseudoramiX screen.
122 // The rest of the X server will know nothing about this screen.
123 // Can be called before or after extension init.
124 // Screens must be re-added once per generation.
126 PseudoramiXAddScreen(int x
, int y
, int w
, int h
)
128 PseudoramiXScreenRec
*s
;
130 if (noPseudoramiXExtension
) return;
132 if (pseudoramiXNumScreens
== pseudoramiXScreensAllocated
) {
133 pseudoramiXScreensAllocated
+= pseudoramiXScreensAllocated
+ 1;
134 pseudoramiXScreens
= realloc(pseudoramiXScreens
,
135 pseudoramiXScreensAllocated
*
136 sizeof(PseudoramiXScreenRec
));
139 DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x
, y
, w
, h
);
141 s
= &pseudoramiXScreens
[pseudoramiXNumScreens
++];
148 // Initialize PseudoramiX.
149 // Copied from PanoramiXExtensionInit
151 PseudoramiXExtensionInit(void)
153 Bool success
= FALSE
;
154 ExtensionEntry
*extEntry
;
156 if (noPseudoramiXExtension
) return;
160 /* Even with only one screen we need to enable PseudoramiX to allow
161 dynamic screen configuration changes. */
163 if (pseudoramiXNumScreens
== 1) {
164 // Only one screen - disable Xinerama extension.
165 noPseudoramiXExtension
= TRUE
;
170 if (pseudoramiXGeneration
!= serverGeneration
) {
171 extEntry
= AddExtension(PANORAMIX_PROTOCOL_NAME
, 0, 0,
172 ProcPseudoramiXDispatch
,
173 SProcPseudoramiXDispatch
,
174 PseudoramiXResetProc
,
175 StandardMinorOpcode
);
177 ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
180 pseudoramiXGeneration
= serverGeneration
;
186 ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
187 PANORAMIX_PROTOCOL_NAME
);
193 PseudoramiXResetScreens(void)
197 pseudoramiXNumScreens
= 0;
201 PseudoramiXResetProc(ExtensionEntry
*extEntry
)
205 PseudoramiXResetScreens();
210 ProcPseudoramiXQueryVersion(ClientPtr client
)
214 return ProcPanoramiXQueryVersion(client
);
219 ProcPseudoramiXGetState(ClientPtr client
)
221 REQUEST(xPanoramiXGetStateReq
);
223 xPanoramiXGetStateReply rep
;
228 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
229 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
235 rep
.sequenceNumber
= client
->sequence
;
236 rep
.state
= !noPseudoramiXExtension
;
237 rep
.window
= stuff
->window
;
238 if (client
->swapped
) {
239 swaps(&rep
.sequenceNumber
);
243 WriteToClient(client
, sizeof(xPanoramiXGetStateReply
),&rep
);
249 ProcPseudoramiXGetScreenCount(ClientPtr client
)
251 REQUEST(xPanoramiXGetScreenCountReq
);
253 xPanoramiXGetScreenCountReply rep
;
258 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
259 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
265 rep
.sequenceNumber
= client
->sequence
;
266 rep
.ScreenCount
= pseudoramiXNumScreens
;
267 rep
.window
= stuff
->window
;
268 if (client
->swapped
) {
269 swaps(&rep
.sequenceNumber
);
273 WriteToClient(client
, sizeof(xPanoramiXGetScreenCountReply
),&rep
);
279 ProcPseudoramiXGetScreenSize(ClientPtr client
)
281 REQUEST(xPanoramiXGetScreenSizeReq
);
283 xPanoramiXGetScreenSizeReply rep
;
288 if (stuff
->screen
>= pseudoramiXNumScreens
)
291 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
292 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
298 rep
.sequenceNumber
= client
->sequence
;
299 /* screen dimensions */
300 rep
.width
= pseudoramiXScreens
[stuff
->screen
].w
;
301 // was screenInfo.screens[stuff->screen]->width;
302 rep
.height
= pseudoramiXScreens
[stuff
->screen
].h
;
303 // was screenInfo.screens[stuff->screen]->height;
304 rep
.window
= stuff
->window
;
305 rep
.screen
= stuff
->screen
;
306 if (client
->swapped
) {
307 swaps(&rep
.sequenceNumber
);
314 WriteToClient(client
, sizeof(xPanoramiXGetScreenSizeReply
),&rep
);
320 ProcPseudoramiXIsActive(ClientPtr client
)
322 /* REQUEST(xXineramaIsActiveReq); */
323 xXineramaIsActiveReply rep
;
327 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
331 rep
.sequenceNumber
= client
->sequence
;
332 rep
.state
= !noPseudoramiXExtension
;
333 if (client
->swapped
) {
334 swaps(&rep
.sequenceNumber
);
338 WriteToClient(client
, sizeof(xXineramaIsActiveReply
),&rep
);
344 ProcPseudoramiXQueryScreens(ClientPtr client
)
346 /* REQUEST(xXineramaQueryScreensReq); */
347 xXineramaQueryScreensReply rep
;
349 DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n",
350 noPseudoramiXExtension
,
351 pseudoramiXNumScreens
);
353 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
356 rep
.sequenceNumber
= client
->sequence
;
357 rep
.number
= noPseudoramiXExtension
? 0 : pseudoramiXNumScreens
;
358 rep
.length
= bytes_to_int32(rep
.number
* sz_XineramaScreenInfo
);
359 if (client
->swapped
) {
360 swaps(&rep
.sequenceNumber
);
364 WriteToClient(client
, sizeof(xXineramaQueryScreensReply
),&rep
);
366 if (!noPseudoramiXExtension
) {
367 xXineramaScreenInfo scratch
;
370 for (i
= 0; i
< pseudoramiXNumScreens
; i
++) {
371 scratch
.x_org
= pseudoramiXScreens
[i
].x
;
372 scratch
.y_org
= pseudoramiXScreens
[i
].y
;
373 scratch
.width
= pseudoramiXScreens
[i
].w
;
374 scratch
.height
= pseudoramiXScreens
[i
].h
;
376 if (client
->swapped
) {
377 swaps(&scratch
.x_org
);
378 swaps(&scratch
.y_org
);
379 swaps(&scratch
.width
);
380 swaps(&scratch
.height
);
382 WriteToClient(client
, sz_XineramaScreenInfo
,&scratch
);
391 ProcPseudoramiXDispatch(ClientPtr client
)
395 switch (stuff
->data
) {
396 case X_PanoramiXQueryVersion
:
397 return ProcPseudoramiXQueryVersion(client
);
399 case X_PanoramiXGetState
:
400 return ProcPseudoramiXGetState(client
);
402 case X_PanoramiXGetScreenCount
:
403 return ProcPseudoramiXGetScreenCount(client
);
405 case X_PanoramiXGetScreenSize
:
406 return ProcPseudoramiXGetScreenSize(client
);
408 case X_XineramaIsActive
:
409 return ProcPseudoramiXIsActive(client
);
411 case X_XineramaQueryScreens
:
412 return ProcPseudoramiXQueryScreens(client
);
418 SProcPseudoramiXQueryVersion(ClientPtr client
)
420 REQUEST(xPanoramiXQueryVersionReq
);
424 swaps(&stuff
->length
);
425 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq
);
426 return ProcPseudoramiXQueryVersion(client
);
430 SProcPseudoramiXGetState(ClientPtr client
)
432 REQUEST(xPanoramiXGetStateReq
);
436 swaps(&stuff
->length
);
437 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
438 return ProcPseudoramiXGetState(client
);
442 SProcPseudoramiXGetScreenCount(ClientPtr client
)
444 REQUEST(xPanoramiXGetScreenCountReq
);
448 swaps(&stuff
->length
);
449 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
450 return ProcPseudoramiXGetScreenCount(client
);
454 SProcPseudoramiXGetScreenSize(ClientPtr client
)
456 REQUEST(xPanoramiXGetScreenSizeReq
);
460 swaps(&stuff
->length
);
461 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
462 return ProcPseudoramiXGetScreenSize(client
);
466 SProcPseudoramiXIsActive(ClientPtr client
)
468 REQUEST(xXineramaIsActiveReq
);
472 swaps(&stuff
->length
);
473 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
474 return ProcPseudoramiXIsActive(client
);
478 SProcPseudoramiXQueryScreens(ClientPtr client
)
480 REQUEST(xXineramaQueryScreensReq
);
484 swaps(&stuff
->length
);
485 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
486 return ProcPseudoramiXQueryScreens(client
);
490 SProcPseudoramiXDispatch(ClientPtr client
)
496 switch (stuff
->data
) {
497 case X_PanoramiXQueryVersion
:
498 return SProcPseudoramiXQueryVersion(client
);
500 case X_PanoramiXGetState
:
501 return SProcPseudoramiXGetState(client
);
503 case X_PanoramiXGetScreenCount
:
504 return SProcPseudoramiXGetScreenCount(client
);
506 case X_PanoramiXGetScreenSize
:
507 return SProcPseudoramiXGetScreenSize(client
);
509 case X_XineramaIsActive
:
510 return SProcPseudoramiXIsActive(client
);
512 case X_XineramaQueryScreens
:
513 return SProcPseudoramiXQueryScreens(client
);