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