tizen 2.4 release
[framework/uifw/xorg/server/xorg-server.git] / pseudoramiX / pseudoramiX.c
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
36 #ifdef HAVE_DIX_CONFIG_H
37 #include <dix-config.h>
38 #endif
39
40 #include "pseudoramiX.h"
41 #include "extnsionst.h"
42 #include "extinit.h"
43 #include "dixstruct.h"
44 #include "window.h"
45 #include <X11/extensions/panoramiXproto.h>
46 #include "globals.h"
47
48 #define TRACE PseudoramiXTrace("TRACE " __FILE__ ":%s",__FUNCTION__)
49 #define DEBUG_LOG PseudoramiXDebug
50
51 Bool noPseudoramiXExtension = FALSE;
52
53 extern int
54 ProcPanoramiXQueryVersion(ClientPtr client);
55
56 static void
57 PseudoramiXResetProc(ExtensionEntry *extEntry);
58
59 static int
60 ProcPseudoramiXQueryVersion(ClientPtr client);
61 static int
62 ProcPseudoramiXGetState(ClientPtr client);
63 static int
64 ProcPseudoramiXGetScreenCount(ClientPtr client);
65 static int
66 ProcPseudoramiXGetScreenSize(ClientPtr client);
67 static int
68 ProcPseudoramiXIsActive(ClientPtr client);
69 static int
70 ProcPseudoramiXQueryScreens(ClientPtr client);
71 static int
72 ProcPseudoramiXDispatch(ClientPtr client);
73
74 static int
75 SProcPseudoramiXQueryVersion(ClientPtr client);
76 static int
77 SProcPseudoramiXGetState(ClientPtr client);
78 static int
79 SProcPseudoramiXGetScreenCount(ClientPtr client);
80 static int
81 SProcPseudoramiXGetScreenSize(ClientPtr client);
82 static int
83 SProcPseudoramiXIsActive(ClientPtr client);
84 static int
85 SProcPseudoramiXQueryScreens(ClientPtr client);
86 static int
87 SProcPseudoramiXDispatch(ClientPtr client);
88
89 typedef struct {
90     int x;
91     int y;
92     int w;
93     int h;
94 } PseudoramiXScreenRec;
95
96 static PseudoramiXScreenRec *pseudoramiXScreens = NULL;
97 static int pseudoramiXScreensAllocated = 0;
98 static int pseudoramiXNumScreens = 0;
99 static unsigned long pseudoramiXGeneration = 0;
100
101 static void
102 PseudoramiXTrace(const char *format, ...)
103     _X_ATTRIBUTE_PRINTF(1, 2);
104
105 static void
106 PseudoramiXTrace(const char *format, ...)
107 {
108     va_list ap;
109
110     va_start(ap, format);
111     LogVMessageVerb(X_NONE, 10, format, ap);
112     va_end(ap);
113 }
114
115 static void
116 PseudoramiXDebug(const char *format, ...)
117     _X_ATTRIBUTE_PRINTF(1, 2);
118
119 static void
120 PseudoramiXDebug(const char *format, ...)
121 {
122     va_list ap;
123
124     va_start(ap, format);
125     LogVMessageVerb(X_NONE, 3, format, ap);
126     va_end(ap);
127 }
128
129 // Add a PseudoramiX screen.
130 // The rest of the X server will know nothing about this screen.
131 // Can be called before or after extension init.
132 // Screens must be re-added once per generation.
133 void
134 PseudoramiXAddScreen(int x, int y, int w, int h)
135 {
136     PseudoramiXScreenRec *s;
137
138     if (noPseudoramiXExtension) return;
139
140     if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) {
141         pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1;
142         pseudoramiXScreens = realloc(pseudoramiXScreens,
143                                      pseudoramiXScreensAllocated *
144                                      sizeof(PseudoramiXScreenRec));
145     }
146
147     DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h);
148
149     s = &pseudoramiXScreens[pseudoramiXNumScreens++];
150     s->x = x;
151     s->y = y;
152     s->w = w;
153     s->h = h;
154 }
155
156 // Initialize PseudoramiX.
157 // Copied from PanoramiXExtensionInit
158 void
159 PseudoramiXExtensionInit(void)
160 {
161     Bool success = FALSE;
162     ExtensionEntry      *extEntry;
163
164     if (noPseudoramiXExtension) return;
165
166     TRACE;
167
168     /* Even with only one screen we need to enable PseudoramiX to allow
169        dynamic screen configuration changes. */
170 #if 0
171     if (pseudoramiXNumScreens == 1) {
172         // Only one screen - disable Xinerama extension.
173         noPseudoramiXExtension = TRUE;
174         return;
175     }
176 #endif
177
178     if (pseudoramiXGeneration != serverGeneration) {
179         extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
180                                 ProcPseudoramiXDispatch,
181                                 SProcPseudoramiXDispatch,
182                                 PseudoramiXResetProc,
183                                 StandardMinorOpcode);
184         if (!extEntry) {
185             ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
186         }
187         else {
188             pseudoramiXGeneration = serverGeneration;
189             success = TRUE;
190         }
191     }
192
193     if (!success) {
194         ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
195                PANORAMIX_PROTOCOL_NAME);
196         return;
197     }
198 }
199
200 void
201 PseudoramiXResetScreens(void)
202 {
203     TRACE;
204
205     pseudoramiXNumScreens = 0;
206 }
207
208 static void
209 PseudoramiXResetProc(ExtensionEntry *extEntry)
210 {
211     TRACE;
212
213     PseudoramiXResetScreens();
214 }
215
216 // was PanoramiX
217 static int
218 ProcPseudoramiXQueryVersion(ClientPtr client)
219 {
220     TRACE;
221
222     return ProcPanoramiXQueryVersion(client);
223 }
224
225 // was PanoramiX
226 static int
227 ProcPseudoramiXGetState(ClientPtr client)
228 {
229     REQUEST(xPanoramiXGetStateReq);
230     WindowPtr pWin;
231     xPanoramiXGetStateReply rep;
232     register int rc;
233
234     TRACE;
235
236     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
237     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
238     if (rc != Success)
239         return rc;
240
241     rep.type = X_Reply;
242     rep.length = 0;
243     rep.sequenceNumber = client->sequence;
244     rep.state = !noPseudoramiXExtension;
245     rep.window = stuff->window;
246     if (client->swapped) {
247         swaps(&rep.sequenceNumber);
248         swapl(&rep.length);
249         swapl(&rep.window);
250     }
251     WriteToClient(client, sizeof(xPanoramiXGetStateReply),&rep);
252     return Success;
253 }
254
255 // was PanoramiX
256 static int
257 ProcPseudoramiXGetScreenCount(ClientPtr client)
258 {
259     REQUEST(xPanoramiXGetScreenCountReq);
260     WindowPtr pWin;
261     xPanoramiXGetScreenCountReply rep;
262     register int rc;
263
264     TRACE;
265
266     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
267     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
268     if (rc != Success)
269         return rc;
270
271     rep.type = X_Reply;
272     rep.length = 0;
273     rep.sequenceNumber = client->sequence;
274     rep.ScreenCount = pseudoramiXNumScreens;
275     rep.window = stuff->window;
276     if (client->swapped) {
277         swaps(&rep.sequenceNumber);
278         swapl(&rep.length);
279         swapl(&rep.window);
280     }
281     WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply),&rep);
282     return Success;
283 }
284
285 // was PanoramiX
286 static int
287 ProcPseudoramiXGetScreenSize(ClientPtr client)
288 {
289     REQUEST(xPanoramiXGetScreenSizeReq);
290     WindowPtr pWin;
291     xPanoramiXGetScreenSizeReply rep;
292     register int rc;
293
294     TRACE;
295
296     if (stuff->screen >= pseudoramiXNumScreens)
297       return BadMatch;
298
299     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
300     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
301     if (rc != Success)
302         return rc;
303
304     rep.type = X_Reply;
305     rep.length = 0;
306     rep.sequenceNumber = client->sequence;
307     /* screen dimensions */
308     rep.width = pseudoramiXScreens[stuff->screen].w;
309     // was screenInfo.screens[stuff->screen]->width;
310     rep.height = pseudoramiXScreens[stuff->screen].h;
311     // was screenInfo.screens[stuff->screen]->height;
312     rep.window = stuff->window;
313     rep.screen = stuff->screen;
314     if (client->swapped) {
315         swaps(&rep.sequenceNumber);
316         swapl(&rep.length);
317         swapl(&rep.width);
318         swapl(&rep.height);
319         swapl(&rep.window);
320         swapl(&rep.screen);
321     }
322     WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply),&rep);
323     return Success;
324 }
325
326 // was Xinerama
327 static int
328 ProcPseudoramiXIsActive(ClientPtr client)
329 {
330     /* REQUEST(xXineramaIsActiveReq); */
331     xXineramaIsActiveReply rep;
332
333     TRACE;
334
335     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
336
337     rep.type = X_Reply;
338     rep.length = 0;
339     rep.sequenceNumber = client->sequence;
340     rep.state = !noPseudoramiXExtension;
341     if (client->swapped) {
342         swaps(&rep.sequenceNumber);
343         swapl(&rep.length);
344         swapl(&rep.state);
345     }
346     WriteToClient(client, sizeof(xXineramaIsActiveReply),&rep);
347     return Success;
348 }
349
350 // was Xinerama
351 static int
352 ProcPseudoramiXQueryScreens(ClientPtr client)
353 {
354     /* REQUEST(xXineramaQueryScreensReq); */
355     xXineramaQueryScreensReply rep;
356
357     DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n",
358               noPseudoramiXExtension,
359               pseudoramiXNumScreens);
360
361     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
362
363     rep.type = X_Reply;
364     rep.sequenceNumber = client->sequence;
365     rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens;
366     rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
367     if (client->swapped) {
368         swaps(&rep.sequenceNumber);
369         swapl(&rep.length);
370         swapl(&rep.number);
371     }
372     WriteToClient(client, sizeof(xXineramaQueryScreensReply),&rep);
373
374     if (!noPseudoramiXExtension) {
375         xXineramaScreenInfo scratch;
376         int i;
377
378         for (i = 0; i < pseudoramiXNumScreens; i++) {
379             scratch.x_org = pseudoramiXScreens[i].x;
380             scratch.y_org = pseudoramiXScreens[i].y;
381             scratch.width = pseudoramiXScreens[i].w;
382             scratch.height = pseudoramiXScreens[i].h;
383
384             if (client->swapped) {
385                 swaps(&scratch.x_org);
386                 swaps(&scratch.y_org);
387                 swaps(&scratch.width);
388                 swaps(&scratch.height);
389             }
390             WriteToClient(client, sz_XineramaScreenInfo,&scratch);
391         }
392     }
393
394     return Success;
395 }
396
397 // was PanoramiX
398 static int
399 ProcPseudoramiXDispatch(ClientPtr client)
400 {
401     REQUEST(xReq);
402     TRACE;
403     switch (stuff->data) {
404     case X_PanoramiXQueryVersion:
405         return ProcPseudoramiXQueryVersion(client);
406
407     case X_PanoramiXGetState:
408         return ProcPseudoramiXGetState(client);
409
410     case X_PanoramiXGetScreenCount:
411         return ProcPseudoramiXGetScreenCount(client);
412
413     case X_PanoramiXGetScreenSize:
414         return ProcPseudoramiXGetScreenSize(client);
415
416     case X_XineramaIsActive:
417         return ProcPseudoramiXIsActive(client);
418
419     case X_XineramaQueryScreens:
420         return ProcPseudoramiXQueryScreens(client);
421     }
422     return BadRequest;
423 }
424
425 static int
426 SProcPseudoramiXQueryVersion(ClientPtr client)
427 {
428     REQUEST(xPanoramiXQueryVersionReq);
429
430     TRACE;
431
432     swaps(&stuff->length);
433     REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
434     return ProcPseudoramiXQueryVersion(client);
435 }
436
437 static int
438 SProcPseudoramiXGetState(ClientPtr client)
439 {
440     REQUEST(xPanoramiXGetStateReq);
441
442     TRACE;
443
444     swaps(&stuff->length);
445     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
446     return ProcPseudoramiXGetState(client);
447 }
448
449 static int
450 SProcPseudoramiXGetScreenCount(ClientPtr client)
451 {
452     REQUEST(xPanoramiXGetScreenCountReq);
453
454     TRACE;
455
456     swaps(&stuff->length);
457     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
458     return ProcPseudoramiXGetScreenCount(client);
459 }
460
461 static int
462 SProcPseudoramiXGetScreenSize(ClientPtr client)
463 {
464     REQUEST(xPanoramiXGetScreenSizeReq);
465
466     TRACE;
467
468     swaps(&stuff->length);
469     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
470     return ProcPseudoramiXGetScreenSize(client);
471 }
472
473 static int
474 SProcPseudoramiXIsActive(ClientPtr client)
475 {
476     REQUEST(xXineramaIsActiveReq);
477
478     TRACE;
479
480     swaps(&stuff->length);
481     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
482     return ProcPseudoramiXIsActive(client);
483 }
484
485 static int
486 SProcPseudoramiXQueryScreens(ClientPtr client)
487 {
488     REQUEST(xXineramaQueryScreensReq);
489
490     TRACE;
491
492     swaps(&stuff->length);
493     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
494     return ProcPseudoramiXQueryScreens(client);
495 }
496
497 static int
498 SProcPseudoramiXDispatch(ClientPtr client)
499 {
500     REQUEST(xReq);
501
502     TRACE;
503
504     switch (stuff->data) {
505     case X_PanoramiXQueryVersion:
506         return SProcPseudoramiXQueryVersion(client);
507
508     case X_PanoramiXGetState:
509         return SProcPseudoramiXGetState(client);
510
511     case X_PanoramiXGetScreenCount:
512         return SProcPseudoramiXGetScreenCount(client);
513
514     case X_PanoramiXGetScreenSize:
515         return SProcPseudoramiXGetScreenSize(client);
516
517     case X_XineramaIsActive:
518         return SProcPseudoramiXIsActive(client);
519
520     case X_XineramaQueryScreens:
521         return SProcPseudoramiXQueryScreens(client);
522     }
523     return BadRequest;
524 }