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 /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
36 
37 #include "pseudoramiX.h"
38 
39 #include "extnsionst.h"
40 #include "dixstruct.h"
41 #include "window.h"
42 #include "panoramiXproto.h"
43 #include "globals.h"
44 
45 extern int ProcPanoramiXQueryVersion (ClientPtr client);
46 
47 static void PseudoramiXResetProc(ExtensionEntry *extEntry);
48 
49 static int ProcPseudoramiXQueryVersion(ClientPtr client);
50 static int ProcPseudoramiXGetState(ClientPtr client);
51 static int ProcPseudoramiXGetScreenCount(ClientPtr client);
52 static int ProcPseudoramiXGetScreenSize(ClientPtr client);
53 static int ProcPseudoramiXIsActive(ClientPtr client);
54 static int ProcPseudoramiXQueryScreens(ClientPtr client);
55 static int ProcPseudoramiXDispatch(ClientPtr client);
56 
57 static int SProcPseudoramiXQueryVersion(ClientPtr client);
58 static int SProcPseudoramiXGetState(ClientPtr client);
59 static int SProcPseudoramiXGetScreenCount(ClientPtr client);
60 static int SProcPseudoramiXGetScreenSize(ClientPtr client);
61 static int SProcPseudoramiXIsActive(ClientPtr client);
62 static int SProcPseudoramiXQueryScreens(ClientPtr client);
63 static int SProcPseudoramiXDispatch(ClientPtr client);
64 
65 
66 typedef struct {
67     int x;
68     int y;
69     int w;
70     int h;
71 } PseudoramiXScreenRec;
72 
73 static PseudoramiXScreenRec *pseudoramiXScreens = NULL;
74 static int pseudoramiXScreensAllocated = 0;
75 static int pseudoramiXNumScreens = 0;
76 static int pseudoramiXGeneration = -1;
77 
78 
79 // Add a PseudoramiX screen.
80 // The rest of the X server will know nothing about this screen.
81 // Can be called before or after extension init.
82 // Screens must be re-added once per generation.
83 void
PseudoramiXAddScreen(int x,int y,int w,int h)84 PseudoramiXAddScreen(int x, int y, int w, int h)
85 {
86     PseudoramiXScreenRec *s;
87 
88     if (noPseudoramiXExtension) return;
89 
90     if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) {
91         pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1;
92         pseudoramiXScreens = xrealloc(pseudoramiXScreens,
93                                       pseudoramiXScreensAllocated *
94                                       sizeof(PseudoramiXScreenRec));
95     }
96 
97     s = &pseudoramiXScreens[pseudoramiXNumScreens++];
98     s->x = x;
99     s->y = y;
100     s->w = w;
101     s->h = h;
102 }
103 
104 
105 // Initialize PseudoramiX.
106 // Copied from PanoramiXExtensionInit
PseudoramiXExtensionInit(int argc,char * argv[])107 void PseudoramiXExtensionInit(int argc, char *argv[])
108 {
109     Bool	     	success = FALSE;
110     ExtensionEntry 	*extEntry;
111 
112     if (noPseudoramiXExtension) return;
113 
114 #if 0
115     if (pseudoramiXNumScreens == 1) {
116         // Only one screen - disable Xinerama extension.
117         noPseudoramiXExtension = TRUE;
118         return;
119     }
120 #endif
121 
122     // The server must not run the PanoramiX operations.
123     noPanoramiXExtension = TRUE;
124 
125     if (pseudoramiXGeneration != serverGeneration) {
126         extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
127                                 ProcPseudoramiXDispatch,
128                                 SProcPseudoramiXDispatch,
129                                 PseudoramiXResetProc,
130                                 StandardMinorOpcode);
131         if (!extEntry) {
132             ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
133         } else {
134             pseudoramiXGeneration = serverGeneration;
135             success = TRUE;
136         }
137     }
138 
139     if (!success) {
140         ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
141                PANORAMIX_PROTOCOL_NAME);
142         return;
143     }
144 }
145 
146 
PseudoramiXResetProc(ExtensionEntry * extEntry)147 static void PseudoramiXResetProc(ExtensionEntry *extEntry)
148 {
149     pseudoramiXNumScreens = 0;
150 }
151 
PseudoramiXResetScreens(void)152 void PseudoramiXResetScreens (void)
153 {
154     pseudoramiXNumScreens = 0;
155 }
156 
157 // was PanoramiX
ProcPseudoramiXQueryVersion(ClientPtr client)158 static int ProcPseudoramiXQueryVersion(ClientPtr client)
159 {
160     return ProcPanoramiXQueryVersion(client);
161 }
162 
163 
164 // was PanoramiX
ProcPseudoramiXGetState(ClientPtr client)165 static int ProcPseudoramiXGetState(ClientPtr client)
166 {
167     REQUEST(xPanoramiXGetStateReq);
168     WindowPtr pWin;
169     xPanoramiXGetStateReply rep;
170     register int n;
171 
172     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
173     pWin = LookupWindow (stuff->window, client);
174     if (!pWin)
175         return BadWindow;
176     rep.type = X_Reply;
177     rep.length = 0;
178     rep.sequenceNumber = client->sequence;
179     rep.state = !noPseudoramiXExtension;
180     if (client->swapped) {
181         swaps (&rep.sequenceNumber, n);
182         swapl (&rep.length, n);
183         swaps (&rep.state, n);
184     }
185     WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
186     return client->noClientException;
187 }
188 
189 
190 // was PanoramiX
ProcPseudoramiXGetScreenCount(ClientPtr client)191 static int ProcPseudoramiXGetScreenCount(ClientPtr client)
192 {
193     REQUEST(xPanoramiXGetScreenCountReq);
194     WindowPtr pWin;
195     xPanoramiXGetScreenCountReply rep;
196     register int n;
197 
198     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
199     pWin = LookupWindow (stuff->window, client);
200     if (!pWin)
201         return BadWindow;
202     rep.type = X_Reply;
203     rep.length = 0;
204     rep.sequenceNumber = client->sequence;
205     rep.ScreenCount = pseudoramiXNumScreens;
206     if (client->swapped) {
207         swaps (&rep.sequenceNumber, n);
208         swapl (&rep.length, n);
209         swaps (&rep.ScreenCount, n);
210     }
211     WriteToClient (client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
212     return client->noClientException;
213 }
214 
215 
216 // was PanoramiX
ProcPseudoramiXGetScreenSize(ClientPtr client)217 static int ProcPseudoramiXGetScreenSize(ClientPtr client)
218 {
219     REQUEST(xPanoramiXGetScreenSizeReq);
220     WindowPtr			pWin;
221     xPanoramiXGetScreenSizeReply	rep;
222     register int			n;
223 
224     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
225     pWin = LookupWindow (stuff->window, client);
226     if (!pWin)
227         return BadWindow;
228     rep.type = X_Reply;
229     rep.length = 0;
230     rep.sequenceNumber = client->sequence;
231     /* screen dimensions */
232     rep.width  = pseudoramiXScreens[stuff->screen].w;
233     // was panoramiXdataPtr[stuff->screen].width;
234     rep.height = pseudoramiXScreens[stuff->screen].h;
235     // was panoramiXdataPtr[stuff->screen].height;
236     if (client->swapped) {
237         swaps (&rep.sequenceNumber, n);
238         swapl (&rep.length, n);
239         swaps (&rep.width, n);
240         swaps (&rep.height, n);
241     }
242     WriteToClient (client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
243     return client->noClientException;
244 }
245 
246 
247 // was Xinerama
ProcPseudoramiXIsActive(ClientPtr client)248 static int ProcPseudoramiXIsActive(ClientPtr client)
249 {
250     /* REQUEST(xXineramaIsActiveReq); */
251     xXineramaIsActiveReply	rep;
252 
253     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
254 
255     rep.type = X_Reply;
256     rep.length = 0;
257     rep.sequenceNumber = client->sequence;
258     rep.state = !noPseudoramiXExtension;
259     if (client->swapped) {
260 	register int n;
261 	swaps (&rep.sequenceNumber, n);
262 	swapl (&rep.length, n);
263 	swapl (&rep.state, n);
264     }
265     WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
266     return client->noClientException;
267 }
268 
269 
270 // was Xinerama
ProcPseudoramiXQueryScreens(ClientPtr client)271 static int ProcPseudoramiXQueryScreens(ClientPtr client)
272 {
273     /* REQUEST(xXineramaQueryScreensReq); */
274     xXineramaQueryScreensReply	rep;
275 
276     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
277 
278     rep.type = X_Reply;
279     rep.sequenceNumber = client->sequence;
280     rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens;
281     rep.length = rep.number * sz_XineramaScreenInfo >> 2;
282     if (client->swapped) {
283 	register int n;
284 	swaps (&rep.sequenceNumber, n);
285 	swapl (&rep.length, n);
286 	swapl (&rep.number, n);
287     }
288     WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep);
289 
290     if (!noPseudoramiXExtension) {
291 	xXineramaScreenInfo scratch;
292 	int i;
293 
294 	for(i = 0; i < pseudoramiXNumScreens; i++) {
295 	    scratch.x_org  = pseudoramiXScreens[i].x;
296 	    scratch.y_org  = pseudoramiXScreens[i].y;
297 	    scratch.width  = pseudoramiXScreens[i].w;
298 	    scratch.height = pseudoramiXScreens[i].h;
299 
300 	    if(client->swapped) {
301 		register int n;
302 		swaps (&scratch.x_org, n);
303 		swaps (&scratch.y_org, n);
304 		swaps (&scratch.width, n);
305 		swaps (&scratch.height, n);
306 	    }
307 	    WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch);
308 	}
309     }
310 
311     return client->noClientException;
312 }
313 
314 
315 // was PanoramiX
ProcPseudoramiXDispatch(ClientPtr client)316 static int ProcPseudoramiXDispatch (ClientPtr client)
317 {   REQUEST(xReq);
318     switch (stuff->data)
319     {
320 	case X_PanoramiXQueryVersion:
321 	     return ProcPseudoramiXQueryVersion(client);
322 	case X_PanoramiXGetState:
323 	     return ProcPseudoramiXGetState(client);
324 	case X_PanoramiXGetScreenCount:
325 	     return ProcPseudoramiXGetScreenCount(client);
326 	case X_PanoramiXGetScreenSize:
327 	     return ProcPseudoramiXGetScreenSize(client);
328 	case X_XineramaIsActive:
329 	     return ProcPseudoramiXIsActive(client);
330 	case X_XineramaQueryScreens:
331 	     return ProcPseudoramiXQueryScreens(client);
332     }
333     return BadRequest;
334 }
335 
336 
337 
338 static int
SProcPseudoramiXQueryVersion(ClientPtr client)339 SProcPseudoramiXQueryVersion (ClientPtr client)
340 {
341 	REQUEST(xPanoramiXQueryVersionReq);
342 	register int n;
343 
344 	swaps(&stuff->length,n);
345 	REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
346 	return ProcPseudoramiXQueryVersion(client);
347 }
348 
349 static int
SProcPseudoramiXGetState(ClientPtr client)350 SProcPseudoramiXGetState(ClientPtr client)
351 {
352 	REQUEST(xPanoramiXGetStateReq);
353 	register int n;
354 
355  	swaps (&stuff->length, n);
356 	REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
357 	return ProcPseudoramiXGetState(client);
358 }
359 
360 static int
SProcPseudoramiXGetScreenCount(ClientPtr client)361 SProcPseudoramiXGetScreenCount(ClientPtr client)
362 {
363 	REQUEST(xPanoramiXGetScreenCountReq);
364 	register int n;
365 
366 	swaps (&stuff->length, n);
367 	REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
368 	return ProcPseudoramiXGetScreenCount(client);
369 }
370 
371 static int
SProcPseudoramiXGetScreenSize(ClientPtr client)372 SProcPseudoramiXGetScreenSize(ClientPtr client)
373 {
374 	REQUEST(xPanoramiXGetScreenSizeReq);
375 	register int n;
376 
377 	swaps (&stuff->length, n);
378 	REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
379 	return ProcPseudoramiXGetScreenSize(client);
380 }
381 
382 
383 static int
SProcPseudoramiXIsActive(ClientPtr client)384 SProcPseudoramiXIsActive(ClientPtr client)
385 {
386 	REQUEST(xXineramaIsActiveReq);
387 	register int n;
388 
389 	swaps (&stuff->length, n);
390 	REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
391 	return ProcPseudoramiXIsActive(client);
392 }
393 
394 
395 static int
SProcPseudoramiXQueryScreens(ClientPtr client)396 SProcPseudoramiXQueryScreens(ClientPtr client)
397 {
398 	REQUEST(xXineramaQueryScreensReq);
399 	register int n;
400 
401 	swaps (&stuff->length, n);
402 	REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
403 	return ProcPseudoramiXQueryScreens(client);
404 }
405 
406 
407 static int
SProcPseudoramiXDispatch(ClientPtr client)408 SProcPseudoramiXDispatch (ClientPtr client)
409 {   REQUEST(xReq);
410     switch (stuff->data)
411     {
412 	case X_PanoramiXQueryVersion:
413 	     return SProcPseudoramiXQueryVersion(client);
414 	case X_PanoramiXGetState:
415 	     return SProcPseudoramiXGetState(client);
416 	case X_PanoramiXGetScreenCount:
417 	     return SProcPseudoramiXGetScreenCount(client);
418 	case X_PanoramiXGetScreenSize:
419 	     return SProcPseudoramiXGetScreenSize(client);
420 	case X_XineramaIsActive:
421 	     return SProcPseudoramiXIsActive(client);
422 	case X_XineramaQueryScreens:
423 	     return SProcPseudoramiXQueryScreens(client);
424     }
425     return BadRequest;
426 }
427