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