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