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 #include "pseudoramiX.h"
37 #ifdef HAVE_XORG_CONFIG_H
38 #include <xorg-config.h>
40 #include "extnsionst.h"
41 #include "dixstruct.h"
43 #include <X11/extensions/panoramiXproto.h>
46 extern int ProcPanoramiXQueryVersion (ClientPtr client
);
48 static void PseudoramiXResetProc(ExtensionEntry
*extEntry
);
50 static int ProcPseudoramiXQueryVersion(ClientPtr client
);
51 static int ProcPseudoramiXGetState(ClientPtr client
);
52 static int ProcPseudoramiXGetScreenCount(ClientPtr client
);
53 static int ProcPseudoramiXGetScreenSize(ClientPtr client
);
54 static int ProcPseudoramiXIsActive(ClientPtr client
);
55 static int ProcPseudoramiXQueryScreens(ClientPtr client
);
56 static int ProcPseudoramiXDispatch(ClientPtr client
);
58 static int SProcPseudoramiXQueryVersion(ClientPtr client
);
59 static int SProcPseudoramiXGetState(ClientPtr client
);
60 static int SProcPseudoramiXGetScreenCount(ClientPtr client
);
61 static int SProcPseudoramiXGetScreenSize(ClientPtr client
);
62 static int SProcPseudoramiXIsActive(ClientPtr client
);
63 static int SProcPseudoramiXQueryScreens(ClientPtr client
);
64 static int SProcPseudoramiXDispatch(ClientPtr client
);
72 } PseudoramiXScreenRec
;
74 static PseudoramiXScreenRec
*pseudoramiXScreens
= NULL
;
75 static int pseudoramiXScreensAllocated
= 0;
76 static int pseudoramiXNumScreens
= 0;
77 static unsigned long pseudoramiXGeneration
= 0;
80 // Add a PseudoramiX screen.
81 // The rest of the X server will know nothing about this screen.
82 // Can be called before or after extension init.
83 // Screens must be re-added once per generation.
85 PseudoramiXAddScreen(int x
, int y
, int w
, int h
)
87 PseudoramiXScreenRec
*s
;
89 if (noPseudoramiXExtension
) return;
91 if (pseudoramiXNumScreens
== pseudoramiXScreensAllocated
) {
92 pseudoramiXScreensAllocated
+= pseudoramiXScreensAllocated
+ 1;
93 pseudoramiXScreens
= xrealloc(pseudoramiXScreens
,
94 pseudoramiXScreensAllocated
*
95 sizeof(PseudoramiXScreenRec
));
98 s
= &pseudoramiXScreens
[pseudoramiXNumScreens
++];
106 // Initialize PseudoramiX.
107 // Copied from PanoramiXExtensionInit
108 void PseudoramiXExtensionInit(int argc
, char *argv
[])
110 Bool success
= FALSE
;
111 ExtensionEntry
*extEntry
;
113 if (noPseudoramiXExtension
) return;
115 /* Even with only one screen we need to enable PseudoramiX to allow
116 dynamic screen configuration changes. */
118 if (pseudoramiXNumScreens
== 1) {
119 // Only one screen - disable Xinerama extension.
120 noPseudoramiXExtension
= TRUE
;
125 // The server must not run the PanoramiX operations.
126 noPanoramiXExtension
= TRUE
;
128 if (pseudoramiXGeneration
!= serverGeneration
) {
129 extEntry
= AddExtension(PANORAMIX_PROTOCOL_NAME
, 0, 0,
130 ProcPseudoramiXDispatch
,
131 SProcPseudoramiXDispatch
,
132 PseudoramiXResetProc
,
133 StandardMinorOpcode
);
135 ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
137 pseudoramiXGeneration
= serverGeneration
;
143 ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
144 PANORAMIX_PROTOCOL_NAME
);
150 void PseudoramiXResetScreens(void)
152 pseudoramiXNumScreens
= 0;
156 static void PseudoramiXResetProc(ExtensionEntry
*extEntry
)
158 PseudoramiXResetScreens();
163 static int ProcPseudoramiXQueryVersion(ClientPtr client
)
165 return ProcPanoramiXQueryVersion(client
);
170 static int ProcPseudoramiXGetState(ClientPtr client
)
172 REQUEST(xPanoramiXGetStateReq
);
174 xPanoramiXGetStateReply rep
;
177 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
178 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
184 rep
.sequenceNumber
= client
->sequence
;
185 rep
.state
= !noPseudoramiXExtension
;
186 if (client
->swapped
) {
187 swaps (&rep
.sequenceNumber
, n
);
188 swapl (&rep
.length
, n
);
189 swaps (&rep
.state
, n
);
191 WriteToClient (client
, sizeof (xPanoramiXGetStateReply
), (char *) &rep
);
192 return client
->noClientException
;
197 static int ProcPseudoramiXGetScreenCount(ClientPtr client
)
199 REQUEST(xPanoramiXGetScreenCountReq
);
201 xPanoramiXGetScreenCountReply rep
;
204 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
205 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
211 rep
.sequenceNumber
= client
->sequence
;
212 rep
.ScreenCount
= pseudoramiXNumScreens
;
213 if (client
->swapped
) {
214 swaps (&rep
.sequenceNumber
, n
);
215 swapl (&rep
.length
, n
);
216 swaps (&rep
.ScreenCount
, n
);
218 WriteToClient (client
, sizeof(xPanoramiXGetScreenCountReply
), (char *)&rep
);
219 return client
->noClientException
;
224 static int ProcPseudoramiXGetScreenSize(ClientPtr client
)
226 REQUEST(xPanoramiXGetScreenSizeReq
);
228 xPanoramiXGetScreenSizeReply rep
;
231 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
232 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixUnknownAccess
);
238 rep
.sequenceNumber
= client
->sequence
;
239 /* screen dimensions */
240 rep
.width
= pseudoramiXScreens
[stuff
->screen
].w
;
241 // was panoramiXdataPtr[stuff->screen].width;
242 rep
.height
= pseudoramiXScreens
[stuff
->screen
].h
;
243 // was panoramiXdataPtr[stuff->screen].height;
244 if (client
->swapped
) {
245 swaps (&rep
.sequenceNumber
, n
);
246 swapl (&rep
.length
, n
);
247 swaps (&rep
.width
, n
);
248 swaps (&rep
.height
, n
);
250 WriteToClient (client
, sizeof(xPanoramiXGetScreenSizeReply
), (char *)&rep
);
251 return client
->noClientException
;
256 static int ProcPseudoramiXIsActive(ClientPtr client
)
258 /* REQUEST(xXineramaIsActiveReq); */
259 xXineramaIsActiveReply rep
;
261 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
265 rep
.sequenceNumber
= client
->sequence
;
266 rep
.state
= !noPseudoramiXExtension
;
267 if (client
->swapped
) {
269 swaps (&rep
.sequenceNumber
, n
);
270 swapl (&rep
.length
, n
);
271 swapl (&rep
.state
, n
);
273 WriteToClient (client
, sizeof (xXineramaIsActiveReply
), (char *) &rep
);
274 return client
->noClientException
;
279 static int ProcPseudoramiXQueryScreens(ClientPtr client
)
281 /* REQUEST(xXineramaQueryScreensReq); */
282 xXineramaQueryScreensReply rep
;
284 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
287 rep
.sequenceNumber
= client
->sequence
;
288 rep
.number
= noPseudoramiXExtension
? 0 : pseudoramiXNumScreens
;
289 rep
.length
= rep
.number
* sz_XineramaScreenInfo
>> 2;
290 if (client
->swapped
) {
292 swaps (&rep
.sequenceNumber
, n
);
293 swapl (&rep
.length
, n
);
294 swapl (&rep
.number
, n
);
296 WriteToClient (client
, sizeof (xXineramaQueryScreensReply
), (char *) &rep
);
298 if (!noPseudoramiXExtension
) {
299 xXineramaScreenInfo scratch
;
302 for(i
= 0; i
< pseudoramiXNumScreens
; i
++) {
303 scratch
.x_org
= pseudoramiXScreens
[i
].x
;
304 scratch
.y_org
= pseudoramiXScreens
[i
].y
;
305 scratch
.width
= pseudoramiXScreens
[i
].w
;
306 scratch
.height
= pseudoramiXScreens
[i
].h
;
308 if(client
->swapped
) {
310 swaps (&scratch
.x_org
, n
);
311 swaps (&scratch
.y_org
, n
);
312 swaps (&scratch
.width
, n
);
313 swaps (&scratch
.height
, n
);
315 WriteToClient (client
, sz_XineramaScreenInfo
, (char *) &scratch
);
319 return client
->noClientException
;
324 static int ProcPseudoramiXDispatch (ClientPtr client
)
328 case X_PanoramiXQueryVersion
:
329 return ProcPseudoramiXQueryVersion(client
);
330 case X_PanoramiXGetState
:
331 return ProcPseudoramiXGetState(client
);
332 case X_PanoramiXGetScreenCount
:
333 return ProcPseudoramiXGetScreenCount(client
);
334 case X_PanoramiXGetScreenSize
:
335 return ProcPseudoramiXGetScreenSize(client
);
336 case X_XineramaIsActive
:
337 return ProcPseudoramiXIsActive(client
);
338 case X_XineramaQueryScreens
:
339 return ProcPseudoramiXQueryScreens(client
);
347 SProcPseudoramiXQueryVersion (ClientPtr client
)
349 REQUEST(xPanoramiXQueryVersionReq
);
352 swaps(&stuff
->length
,n
);
353 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq
);
354 return ProcPseudoramiXQueryVersion(client
);
358 SProcPseudoramiXGetState(ClientPtr client
)
360 REQUEST(xPanoramiXGetStateReq
);
363 swaps (&stuff
->length
, n
);
364 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq
);
365 return ProcPseudoramiXGetState(client
);
369 SProcPseudoramiXGetScreenCount(ClientPtr client
)
371 REQUEST(xPanoramiXGetScreenCountReq
);
374 swaps (&stuff
->length
, n
);
375 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq
);
376 return ProcPseudoramiXGetScreenCount(client
);
380 SProcPseudoramiXGetScreenSize(ClientPtr client
)
382 REQUEST(xPanoramiXGetScreenSizeReq
);
385 swaps (&stuff
->length
, n
);
386 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq
);
387 return ProcPseudoramiXGetScreenSize(client
);
392 SProcPseudoramiXIsActive(ClientPtr client
)
394 REQUEST(xXineramaIsActiveReq
);
397 swaps (&stuff
->length
, n
);
398 REQUEST_SIZE_MATCH(xXineramaIsActiveReq
);
399 return ProcPseudoramiXIsActive(client
);
404 SProcPseudoramiXQueryScreens(ClientPtr client
)
406 REQUEST(xXineramaQueryScreensReq
);
409 swaps (&stuff
->length
, n
);
410 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq
);
411 return ProcPseudoramiXQueryScreens(client
);
416 SProcPseudoramiXDispatch (ClientPtr client
)
420 case X_PanoramiXQueryVersion
:
421 return SProcPseudoramiXQueryVersion(client
);
422 case X_PanoramiXGetState
:
423 return SProcPseudoramiXGetState(client
);
424 case X_PanoramiXGetScreenCount
:
425 return SProcPseudoramiXGetScreenCount(client
);
426 case X_PanoramiXGetScreenSize
:
427 return SProcPseudoramiXGetScreenSize(client
);
428 case X_XineramaIsActive
:
429 return SProcPseudoramiXIsActive(client
);
430 case X_XineramaQueryScreens
:
431 return SProcPseudoramiXQueryScreens(client
);