Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / dmx.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright 2002-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28/*
29 * Authors:
30 * Rickard E. (Rik) Faith <faith@redhat.com>
31 *
32 */
33
34/** \file
35 * This file implements the server-side part of the DMX protocol. A
36 * vector of fucntions is provided at extension initialization time, so
37 * most all of the useful functions in this file are declared static and
38 * do not appear in the doxygen documentation.
39 *
40 * Much of the low-level work is done by functions in \a dmxextension.c
41 *
42 * Please see the Client-to-Server DMX Extension to the X Protocol
43 * document for details about the protocol. */
44
45#ifdef HAVE_DMX_CONFIG_H
46#include <dmx-config.h>
47#endif
48
49#include <X11/X.h>
50#include <X11/Xproto.h>
51#include "misc.h"
52#include "os.h"
53#include "dixstruct.h"
54#include "extnsionst.h"
55#include "extinit.h"
56#include "opaque.h"
57
58#include "dmxextension.h"
59#include <X11/extensions/dmxproto.h>
60#include <X11/extensions/dmx.h>
61#include "protocol-versions.h"
62
63#ifdef PANORAMIX
64#include "panoramiX.h"
65extern unsigned long XRT_WINDOW;
66extern int PanoramiXNumScreens;
67#endif
68
69static unsigned char DMXCode;
70
71static int
72_DMXXineramaActive(void)
73{
74#ifdef PANORAMIX
75 return !noPanoramiXExtension;
76#else
77 return 0;
78#endif
79}
80
81static void
82dmxSetScreenAttribute(int bit, DMXScreenAttributesPtr attr, CARD32 value)
83{
84 switch (1 << bit) {
85 case DMXScreenWindowWidth:
86 attr->screenWindowWidth = value;
87 break;
88 case DMXScreenWindowHeight:
89 attr->screenWindowHeight = value;
90 break;
91 case DMXScreenWindowXoffset:
92 attr->screenWindowXoffset = value;
93 break;
94 case DMXScreenWindowYoffset:
95 attr->screenWindowYoffset = value;
96 break;
97 case DMXRootWindowWidth:
98 attr->rootWindowWidth = value;
99 break;
100 case DMXRootWindowHeight:
101 attr->rootWindowHeight = value;
102 break;
103 case DMXRootWindowXoffset:
104 attr->rootWindowXoffset = value;
105 break;
106 case DMXRootWindowYoffset:
107 attr->rootWindowYoffset = value;
108 break;
109 case DMXRootWindowXorigin:
110 attr->rootWindowXorigin = value;
111 break;
112 case DMXRootWindowYorigin:
113 attr->rootWindowYorigin = value;
114 break;
115 }
116}
117
118static int
119dmxFetchScreenAttributes(unsigned int mask,
120 DMXScreenAttributesPtr attr, CARD32 *value_list)
121{
122 int i;
123 CARD32 *value = value_list;
124 int count = 0;
125
126 for (i = 0; i < 32; i++) {
127 if (mask & (1 << i)) {
128 dmxSetScreenAttribute(i, attr, *value);
129 ++value;
130 ++count;
131 }
132 }
133 return count;
134}
135
136static void
137dmxSetDesktopAttribute(int bit, DMXDesktopAttributesPtr attr, CARD32 value)
138{
139 switch (1 << bit) {
140 case DMXDesktopWidth:
141 attr->width = value;
142 break;
143 case DMXDesktopHeight:
144 attr->height = value;
145 break;
146 case DMXDesktopShiftX:
147 attr->shiftX = value;
148 break;
149 case DMXDesktopShiftY:
150 attr->shiftY = value;
151 break;
152 }
153}
154
155static int
156dmxFetchDesktopAttributes(unsigned int mask,
157 DMXDesktopAttributesPtr attr, CARD32 *value_list)
158{
159 int i;
160 CARD32 *value = value_list;
161 int count = 0;
162
163 for (i = 0; i < 32; i++) {
164 if (mask & (1 << i)) {
165 dmxSetDesktopAttribute(i, attr, *value);
166 ++value;
167 ++count;
168 }
169 }
170 return count;
171}
172
173static void
174dmxSetInputAttribute(int bit, DMXInputAttributesPtr attr, CARD32 value)
175{
176 switch (1 << bit) {
177 case DMXInputType:
178 attr->inputType = value;
179 break;
180 case DMXInputPhysicalScreen:
181 attr->physicalScreen = value;
182 break;
183 case DMXInputSendsCore:
184 attr->sendsCore = ! !value;
185 break;
186 }
187}
188
189static int
190dmxFetchInputAttributes(unsigned int mask,
191 DMXInputAttributesPtr attr, CARD32 *value_list)
192{
193 int i;
194 CARD32 *value = value_list;
195 int count = 0;
196
197 for (i = 0; i < 32; i++) {
198 if (mask & (1 << i)) {
199 dmxSetInputAttribute(i, attr, *value);
200 ++value;
201 ++count;
202 }
203 }
204 return count;
205}
206
207static int
208ProcDMXQueryVersion(ClientPtr client)
209{
210 xDMXQueryVersionReply rep = {
211 .type = X_Reply,
212 .sequenceNumber = client->sequence,
213 .length = 0,
214 .majorVersion = SERVER_DMX_MAJOR_VERSION,
215 .minorVersion = SERVER_DMX_MINOR_VERSION,
216 .patchVersion = SERVER_DMX_PATCH_VERSION
217 };
218
219 REQUEST_SIZE_MATCH(xDMXQueryVersionReq);
220
221 if (client->swapped) {
222 swaps(&rep.sequenceNumber);
223 swapl(&rep.length);
224 swapl(&rep.majorVersion);
225 swapl(&rep.minorVersion);
226 swapl(&rep.patchVersion);
227 }
228 WriteToClient(client, sizeof(xDMXQueryVersionReply), &rep);
229 return Success;
230}
231
232static int
233ProcDMXSync(ClientPtr client)
234{
235 xDMXSyncReply rep;
236
237 REQUEST_SIZE_MATCH(xDMXSyncReq);
238
239 dmxFlushPendingSyncs();
240
241 rep = (xDMXSyncReply) {
242 .type = X_Reply,
243 .sequenceNumber = client->sequence,
244 .length = 0,
245 .status = 0
246 };
247 if (client->swapped) {
248 swaps(&rep.sequenceNumber);
249 swapl(&rep.length);
250 swapl(&rep.status);
251 }
252 WriteToClient(client, sizeof(xDMXSyncReply), &rep);
253 return Success;
254}
255
256static int
257ProcDMXForceWindowCreation(ClientPtr client)
258{
259 xDMXForceWindowCreationReply rep;
260
261 REQUEST(xDMXForceWindowCreationReq);
262 WindowPtr pWin;
263
264 REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq);
265
266#ifdef PANORAMIX
267 if (!noPanoramiXExtension) {
268 PanoramiXRes *win;
269 int i;
270
271 if (Success != dixLookupResourceByType((pointer *) &win,
272 stuff->window, XRT_WINDOW,
273 client, DixReadAccess))
274 return -1; /* BadWindow */
275
276 FOR_NSCREENS(i) {
277 if (Success != dixLookupWindow(&pWin, win->info[i].id, client,
278 DixReadAccess))
279 return -1; /* BadWindow */
280
281 dmxForceWindowCreation(pWin);
282 }
283 goto doreply;
284 }
285#endif
286
287 if (Success != dixLookupWindow(&pWin, stuff->window, client, DixReadAccess))
288 return -1; /* BadWindow */
289
290 dmxForceWindowCreation(pWin);
291 doreply:
292 dmxFlushPendingSyncs();
293 rep = (xDMXForceWindowCreationReply) {
294 .type = X_Reply,
295 .sequenceNumber = client->sequence,
296 .length = 0,
297 .status = 0
298 };
299 if (client->swapped) {
300 swaps(&rep.sequenceNumber);
301 swapl(&rep.length);
302 swapl(&rep.status);
303 }
304 WriteToClient(client, sizeof(xDMXForceWindowCreationReply), &rep);
305 return Success;
306}
307
308static int
309ProcDMXGetScreenCount(ClientPtr client)
310{
311 xDMXGetScreenCountReply rep;
312
313 REQUEST_SIZE_MATCH(xDMXGetScreenCountReq);
314
315 rep = (xDMXGetScreenCountReply) {
316 .type = X_Reply,
317 .sequenceNumber = client->sequence,
318 .length = 0,
319 .screenCount = dmxGetNumScreens()
320 };
321 if (client->swapped) {
322 swaps(&rep.sequenceNumber);
323 swapl(&rep.length);
324 swapl(&rep.screenCount);
325 }
326 WriteToClient(client, sizeof(xDMXGetScreenCountReply), &rep);
327 return Success;
328}
329
330static int
331ProcDMXGetScreenAttributes(ClientPtr client)
332{
333 REQUEST(xDMXGetScreenAttributesReq);
334 xDMXGetScreenAttributesReply rep;
335 int length;
336 int paddedLength;
337 DMXScreenAttributesRec attr;
338
339 REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq);
340
341 if (stuff->physicalScreen < 0
342 || stuff->physicalScreen >= dmxGetNumScreens())
343 return BadValue;
344
345 if (!dmxGetScreenAttributes(stuff->physicalScreen, &attr))
346 return BadValue;
347
348 length = attr.displayName ? strlen(attr.displayName) : 0;
349 paddedLength = pad_to_int32(length);
350
351 rep = (xDMXGetScreenAttributesReply) {
352 .type = X_Reply,
353 .sequenceNumber = client->sequence,
354 .length =
355 bytes_to_int32((sizeof(xDMXGetScreenAttributesReply) -
356 sizeof(xGenericReply))
357 + paddedLength),
358 .displayNameLength = length,
359 .logicalScreen = attr.logicalScreen,
360 .screenWindowWidth = attr.screenWindowWidth,
361 .screenWindowHeight = attr.screenWindowHeight,
362 .screenWindowXoffset = attr.screenWindowXoffset,
363 .screenWindowYoffset = attr.screenWindowYoffset,
364 .rootWindowWidth = attr.rootWindowWidth,
365 .rootWindowHeight = attr.rootWindowHeight,
366 .rootWindowXoffset = attr.rootWindowXoffset,
367 .rootWindowYoffset = attr.rootWindowYoffset,
368 .rootWindowXorigin = attr.rootWindowXorigin,
369 .rootWindowYorigin = attr.rootWindowYorigin
370 };
371
372 if (client->swapped) {
373 swaps(&rep.sequenceNumber);
374 swapl(&rep.length);
375 swapl(&rep.displayNameLength);
376 swapl(&rep.logicalScreen);
377 swaps(&rep.screenWindowWidth);
378 swaps(&rep.screenWindowHeight);
379 swaps(&rep.screenWindowXoffset);
380 swaps(&rep.screenWindowYoffset);
381 swaps(&rep.rootWindowWidth);
382 swaps(&rep.rootWindowHeight);
383 swaps(&rep.rootWindowXoffset);
384 swaps(&rep.rootWindowYoffset);
385 swaps(&rep.rootWindowXorigin);
386 swaps(&rep.rootWindowYorigin);
387 }
388 WriteToClient(client, sizeof(xDMXGetScreenAttributesReply), &rep);
389 if (length)
390 WriteToClient(client, length, attr.displayName);
391 return Success;
392}
393
394static int
395ProcDMXChangeScreensAttributes(ClientPtr client)
396{
397 REQUEST(xDMXChangeScreensAttributesReq);
398 xDMXChangeScreensAttributesReply rep;
399 int status = DMX_BAD_XINERAMA;
400 unsigned int mask = 0;
401 unsigned int i;
402 CARD32 *screen_list;
403 CARD32 *mask_list;
404 CARD32 *value_list;
405 DMXScreenAttributesPtr attribs;
406 int errorScreen = 0;
407 unsigned int len;
408 int ones = 0;
409
410 REQUEST_AT_LEAST_SIZE(xDMXChangeScreensAttributesReq);
411 len =
412 client->req_len -
413 bytes_to_int32(sizeof(xDMXChangeScreensAttributesReq));
414 if (len < stuff->screenCount + stuff->maskCount)
415 return BadLength;
416
417 screen_list = (CARD32 *) (stuff + 1);
418 mask_list = &screen_list[stuff->screenCount];
419 value_list = &mask_list[stuff->maskCount];
420
421 for (i = 0; i < stuff->maskCount; i++)
422 ones += Ones(mask_list[i]);
423 if (len != stuff->screenCount + stuff->maskCount + ones)
424 return BadLength;
425
426 if (!_DMXXineramaActive())
427 goto noxinerama;
428
429 if (!(attribs = malloc(stuff->screenCount * sizeof(*attribs))))
430 return BadAlloc;
431
432 for (i = 0; i < stuff->screenCount; i++) {
433 int count;
434
435 if (i < stuff->maskCount)
436 mask = mask_list[i];
437 dmxGetScreenAttributes(screen_list[i], &attribs[i]);
438 count = dmxFetchScreenAttributes(mask, &attribs[i], value_list);
439 value_list += count;
440 }
441
442#if PANORAMIX
443 status = dmxConfigureScreenWindows(stuff->screenCount,
444 screen_list, attribs, &errorScreen);
445#endif
446
447 free(attribs);
448
449 if (status == BadValue)
450 return status;
451
452 noxinerama:
453 rep = (xDMXChangeScreensAttributesReply) {
454 .type = X_Reply,
455 .sequenceNumber = client->sequence,
456 .length = 0,
457 .status = status,
458 .errorScreen = errorScreen
459 };
460 if (client->swapped) {
461 swaps(&rep.sequenceNumber);
462 swapl(&rep.length);
463 swapl(&rep.status);
464 swapl(&rep.errorScreen);
465 }
466 WriteToClient(client, sizeof(xDMXChangeScreensAttributesReply), &rep);
467 return Success;
468}
469
470static int
471ProcDMXAddScreen(ClientPtr client)
472{
473 REQUEST(xDMXAddScreenReq);
474 xDMXAddScreenReply rep;
475 int status = 0;
476 CARD32 *value_list;
477 DMXScreenAttributesRec attr;
478 int count;
479 char *name;
480 int len;
481 int paddedLength;
482
483 REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq);
484 paddedLength = pad_to_int32(stuff->displayNameLength);
485 len = client->req_len - bytes_to_int32(sizeof(xDMXAddScreenReq));
486 if (len != Ones(stuff->valueMask) + paddedLength / 4)
487 return BadLength;
488
489 memset(&attr, 0, sizeof(attr));
490 dmxGetScreenAttributes(stuff->physicalScreen, &attr);
491 value_list = (CARD32 *) (stuff + 1);
492 count = dmxFetchScreenAttributes(stuff->valueMask, &attr, value_list);
493
494 if (!(name = malloc(stuff->displayNameLength + 1 + 4)))
495 return BadAlloc;
496 memcpy(name, &value_list[count], stuff->displayNameLength);
497 name[stuff->displayNameLength] = '\0';
498 attr.displayName = name;
499
500 status = dmxAttachScreen(stuff->physicalScreen, &attr);
501
502 free(name);
503
504 rep = (xDMXAddScreenReply) {
505 .type = X_Reply,
506 .sequenceNumber = client->sequence,
507 .length = 0,
508 .status = status,
509 .physicalScreen = stuff->physicalScreen
510 };
511 if (client->swapped) {
512 swaps(&rep.sequenceNumber);
513 swapl(&rep.length);
514 swapl(&rep.status);
515 swapl(&rep.physicalScreen);
516 }
517 WriteToClient(client, sizeof(xDMXAddScreenReply), &rep);
518 return Success;
519}
520
521static int
522ProcDMXRemoveScreen(ClientPtr client)
523{
524 REQUEST(xDMXRemoveScreenReq);
525 xDMXRemoveScreenReply rep;
526 int status = 0;
527
528 REQUEST_SIZE_MATCH(xDMXRemoveScreenReq);
529
530 status = dmxDetachScreen(stuff->physicalScreen);
531
532 rep = (xDMXRemoveScreenReply) {
533 .type = X_Reply,
534 .sequenceNumber = client->sequence,
535 .length = 0,
536 .status = status
537 };
538 if (client->swapped) {
539 swaps(&rep.sequenceNumber);
540 swapl(&rep.length);
541 swapl(&rep.status);
542 }
543 WriteToClient(client, sizeof(xDMXRemoveScreenReply), &rep);
544 return Success;
545}
546
547#ifdef PANORAMIX
548static int
549dmxPopulatePanoramiX(ClientPtr client, Window window,
550 CARD32 *screens, CARD32 *windows,
551 xRectangle *pos, xRectangle *vis)
552{
553 WindowPtr pWin;
554 PanoramiXRes *win;
555 int i;
556 int count = 0;
557 DMXWindowAttributesRec attr;
558
559 if (Success != dixLookupResourceByType((pointer *) &win,
560 window, XRT_WINDOW,
561 client, DixReadAccess))
562 return -1; /* BadWindow */
563
564 FOR_NSCREENS(i) {
565 if (Success != dixLookupWindow(&pWin, win->info[i].id, client,
566 DixReadAccess))
567 return -1; /* BadWindow */
568 if (dmxGetWindowAttributes(pWin, &attr)) {
569 screens[count] = attr.screen;
570 windows[count] = attr.window;
571 pos[count] = attr.pos;
572 vis[count] = attr.vis;
573 ++count; /* Only count existing windows */
574 }
575 }
576 return count;
577}
578#endif
579
580static int
581dmxPopulate(ClientPtr client, Window window, CARD32 *screens,
582 CARD32 *windows, xRectangle *pos, xRectangle *vis)
583{
584 WindowPtr pWin;
585 DMXWindowAttributesRec attr;
586
587#ifdef PANORAMIX
588 if (!noPanoramiXExtension)
589 return dmxPopulatePanoramiX(client, window, screens, windows, pos, vis);
590#endif
591
592 if (Success != dixLookupWindow(&pWin, window, client, DixReadAccess))
593 return -1; /* BadWindow */
594
595 dmxGetWindowAttributes(pWin, &attr);
596 *screens = attr.screen;
597 *windows = attr.window;
598 *pos = attr.pos;
599 *vis = attr.vis;
600 return 1;
601}
602
603static int
604dmxMaxNumScreens(void)
605{
606#ifdef PANORAMIX
607 if (!noPanoramiXExtension)
608 return PanoramiXNumScreens;
609#endif
610 return 1;
611}
612
613static int
614ProcDMXGetWindowAttributes(ClientPtr client)
615{
616 REQUEST(xDMXGetWindowAttributesReq);
617 xDMXGetWindowAttributesReply rep;
618 int i;
619 CARD32 *screens;
620 CARD32 *windows;
621 xRectangle *pos, *vis;
622 int count = dmxMaxNumScreens();
623
624 REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq);
625
626 if (!(screens = malloc(count * sizeof(*screens))))
627 return BadAlloc;
628 if (!(windows = malloc(count * sizeof(*windows)))) {
629 free(screens);
630 return BadAlloc;
631 }
632 if (!(pos = malloc(count * sizeof(*pos)))) {
633 free(windows);
634 free(screens);
635 return BadAlloc;
636 }
637 if (!(vis = malloc(count * sizeof(*vis)))) {
638 free(pos);
639 free(windows);
640 free(screens);
641 return BadAlloc;
642 }
643
644 if ((count = dmxPopulate(client, stuff->window, screens, windows,
645 pos, vis)) < 0) {
646 free(vis);
647 free(pos);
648 free(windows);
649 free(screens);
650 return BadWindow;
651 }
652
653 rep = (xDMXGetWindowAttributesReply) {
654 .type = X_Reply,
655 .sequenceNumber = client->sequence,
656 .length = count * 6,
657 .screenCount = count
658 };
659 if (client->swapped) {
660 swaps(&rep.sequenceNumber);
661 swapl(&rep.length);
662 swapl(&rep.screenCount);
663 for (i = 0; i < count; i++) {
664 swapl(&screens[i]);
665 swapl(&windows[i]);
666
667 swaps(&pos[i].x);
668 swaps(&pos[i].y);
669 swaps(&pos[i].width);
670 swaps(&pos[i].height);
671
672 swaps(&vis[i].x);
673 swaps(&vis[i].y);
674 swaps(&vis[i].width);
675 swaps(&vis[i].height);
676 }
677 }
678
679 dmxFlushPendingSyncs();
680
681 WriteToClient(client, sizeof(xDMXGetWindowAttributesReply), &rep);
682 if (count) {
683 WriteToClient(client, count * sizeof(*screens), screens);
684 WriteToClient(client, count * sizeof(*windows), windows);
685 WriteToClient(client, count * sizeof(*pos), pos);
686 WriteToClient(client, count * sizeof(*vis), vis);
687 }
688
689 free(vis);
690 free(pos);
691 free(windows);
692 free(screens);
693
694 return Success;
695}
696
697static int
698ProcDMXGetDesktopAttributes(ClientPtr client)
699{
700 xDMXGetDesktopAttributesReply rep;
701 DMXDesktopAttributesRec attr;
702
703 REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq);
704
705 dmxGetDesktopAttributes(&attr);
706
707 rep = (xDMXGetDesktopAttributesReply) {
708 .type = X_Reply,
709 .sequenceNumber = client->sequence,
710 .length = 0,
711 .width = attr.width,
712 .height = attr.height,
713 .shiftX = attr.shiftX,
714 .shiftY = attr.shiftY
715 };
716
717 if (client->swapped) {
718 swaps(&rep.sequenceNumber);
719 swapl(&rep.length);
720 swaps(&rep.width);
721 swaps(&rep.height);
722 swaps(&rep.shiftX);
723 swaps(&rep.shiftY);
724 }
725 WriteToClient(client, sizeof(xDMXGetDesktopAttributesReply), &rep);
726 return Success;
727}
728
729static int
730ProcDMXChangeDesktopAttributes(ClientPtr client)
731{
732 REQUEST(xDMXChangeDesktopAttributesReq);
733 xDMXChangeDesktopAttributesReply rep;
734 int status = DMX_BAD_XINERAMA;
735 CARD32 *value_list;
736 DMXDesktopAttributesRec attr;
737 int len;
738
739 REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq);
740 len = client->req_len - (sizeof(xDMXChangeDesktopAttributesReq) >> 2);
741 if (len != Ones(stuff->valueMask))
742 return BadLength;
743
744 if (!_DMXXineramaActive())
745 goto noxinerama;
746
747 value_list = (CARD32 *) (stuff + 1);
748
749 dmxGetDesktopAttributes(&attr);
750 dmxFetchDesktopAttributes(stuff->valueMask, &attr, value_list);
751
752#if PANORAMIX
753 status = dmxConfigureDesktop(&attr);
754#endif
755 if (status == BadValue)
756 return status;
757
758 noxinerama:
759 rep = (xDMXChangeDesktopAttributesReply) {
760 .type = X_Reply,
761 .sequenceNumber = client->sequence,
762 .length = 0,
763 .status = status
764 };
765 if (client->swapped) {
766 swaps(&rep.sequenceNumber);
767 swapl(&rep.length);
768 swapl(&rep.status);
769 }
770 WriteToClient(client, sizeof(xDMXChangeDesktopAttributesReply), &rep);
771 return Success;
772}
773
774static int
775ProcDMXGetInputCount(ClientPtr client)
776{
777 xDMXGetInputCountReply rep;
778
779 REQUEST_SIZE_MATCH(xDMXGetInputCountReq);
780
781 rep = (xDMXGetInputCountReply) {
782 .type = X_Reply,
783 .sequenceNumber = client->sequence,
784 .length = 0,
785 .inputCount = dmxGetInputCount()
786 };
787 if (client->swapped) {
788 swaps(&rep.sequenceNumber);
789 swapl(&rep.length);
790 swapl(&rep.inputCount);
791 }
792 WriteToClient(client, sizeof(xDMXGetInputCountReply), &rep);
793 return Success;
794}
795
796static int
797ProcDMXGetInputAttributes(ClientPtr client)
798{
799 REQUEST(xDMXGetInputAttributesReq);
800 xDMXGetInputAttributesReply rep;
801 int length;
802 int paddedLength;
803 DMXInputAttributesRec attr;
804
805 REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq);
806
807 if (dmxGetInputAttributes(stuff->deviceId, &attr))
808 return BadValue;
809
810 length = attr.name ? strlen(attr.name) : 0;
811 paddedLength = pad_to_int32(length);
812
813 rep = (xDMXGetInputAttributesReply) {
814 .type = X_Reply,
815 .sequenceNumber = client->sequence,
816 .length = bytes_to_int32(paddedLength),
817
818 .inputType = attr.inputType,
819 .physicalScreen = attr.physicalScreen,
820 .physicalId = attr.physicalId,
821 .nameLength = length,
822 .isCore = attr.isCore,
823 .sendsCore = attr.sendsCore,
824 .detached = attr.detached
825 };
826
827 if (client->swapped) {
828 swaps(&rep.sequenceNumber);
829 swapl(&rep.length);
830 swapl(&rep.inputType);
831 swapl(&rep.physicalScreen);
832 swapl(&rep.physicalId);
833 swapl(&rep.nameLength);
834 }
835 WriteToClient(client, sizeof(xDMXGetInputAttributesReply), &rep);
836 if (length)
837 WriteToClient(client, length, attr.name);
838 return Success;
839}
840
841static int
842ProcDMXAddInput(ClientPtr client)
843{
844 REQUEST(xDMXAddInputReq);
845 xDMXAddInputReply rep;
846 int status = 0;
847 CARD32 *value_list;
848 DMXInputAttributesRec attr;
849 int count;
850 char *name;
851 int len;
852 int paddedLength;
853 int id = -1;
854
855 REQUEST_AT_LEAST_SIZE(xDMXAddInputReq);
856 paddedLength = pad_to_int32(stuff->displayNameLength);
857 len = client->req_len - (sizeof(xDMXAddInputReq) >> 2);
858 if (len != Ones(stuff->valueMask) + paddedLength / 4)
859 return BadLength;
860
861 memset(&attr, 0, sizeof(attr));
862 value_list = (CARD32 *) (stuff + 1);
863 count = dmxFetchInputAttributes(stuff->valueMask, &attr, value_list);
864
865 if (!(name = malloc(stuff->displayNameLength + 1 + 4)))
866 return BadAlloc;
867 memcpy(name, &value_list[count], stuff->displayNameLength);
868 name[stuff->displayNameLength] = '\0';
869 attr.name = name;
870
871 status = dmxAddInput(&attr, &id);
872
873 free(name);
874
875 if (status)
876 return status;
877
878 rep = (xDMXAddInputReply) {
879 .type = X_Reply,
880 .sequenceNumber = client->sequence,
881 .length = 0,
882 .status = status,
883 .physicalId = id
884 };
885 if (client->swapped) {
886 swaps(&rep.sequenceNumber);
887 swapl(&rep.length);
888 swapl(&rep.status);
889 swapl(&rep.physicalId);
890 }
891 WriteToClient(client, sizeof(xDMXAddInputReply), &rep);
892 return Success;
893}
894
895static int
896ProcDMXRemoveInput(ClientPtr client)
897{
898 REQUEST(xDMXRemoveInputReq);
899 xDMXRemoveInputReply rep;
900 int status = 0;
901
902 REQUEST_SIZE_MATCH(xDMXRemoveInputReq);
903
904 status = dmxRemoveInput(stuff->physicalId);
905
906 if (status)
907 return status;
908
909 rep = (xDMXRemoveInputReply) {
910 .type = X_Reply,
911 .sequenceNumber = client->sequence,
912 .length = 0,
913 .status = status
914 };
915 if (client->swapped) {
916 swaps(&rep.sequenceNumber);
917 swapl(&rep.length);
918 swapl(&rep.status);
919 }
920 WriteToClient(client, sizeof(xDMXRemoveInputReply), &rep);
921 return Success;
922}
923
924static int
925ProcDMXDispatch(ClientPtr client)
926{
927 REQUEST(xReq);
928
929 switch (stuff->data) {
930 case X_DMXQueryVersion:
931 return ProcDMXQueryVersion(client);
932 case X_DMXSync:
933 return ProcDMXSync(client);
934 case X_DMXForceWindowCreation:
935 return ProcDMXForceWindowCreation(client);
936 case X_DMXGetScreenCount:
937 return ProcDMXGetScreenCount(client);
938 case X_DMXGetScreenAttributes:
939 return ProcDMXGetScreenAttributes(client);
940 case X_DMXChangeScreensAttributes:
941 return ProcDMXChangeScreensAttributes(client);
942 case X_DMXAddScreen:
943 return ProcDMXAddScreen(client);
944 case X_DMXRemoveScreen:
945 return ProcDMXRemoveScreen(client);
946 case X_DMXGetWindowAttributes:
947 return ProcDMXGetWindowAttributes(client);
948 case X_DMXGetDesktopAttributes:
949 return ProcDMXGetDesktopAttributes(client);
950 case X_DMXChangeDesktopAttributes:
951 return ProcDMXChangeDesktopAttributes(client);
952 case X_DMXGetInputCount:
953 return ProcDMXGetInputCount(client);
954 case X_DMXGetInputAttributes:
955 return ProcDMXGetInputAttributes(client);
956 case X_DMXAddInput:
957 return ProcDMXAddInput(client);
958 case X_DMXRemoveInput:
959 return ProcDMXRemoveInput(client);
960
961 case X_DMXGetScreenInformationDEPRECATED:
962 case X_DMXForceWindowCreationDEPRECATED:
963 case X_DMXReconfigureScreenDEPRECATED:
964 return BadImplementation;
965
966 default:
967 return BadRequest;
968 }
969}
970
971static int
972SProcDMXQueryVersion(ClientPtr client)
973{
974 REQUEST(xDMXQueryVersionReq);
975
976 swaps(&stuff->length);
977 REQUEST_SIZE_MATCH(xDMXQueryVersionReq);
978 return ProcDMXQueryVersion(client);
979}
980
981static int
982SProcDMXSync(ClientPtr client)
983{
984 REQUEST(xDMXSyncReq);
985
986 swaps(&stuff->length);
987 REQUEST_SIZE_MATCH(xDMXSyncReq);
988 return ProcDMXSync(client);
989}
990
991static int
992SProcDMXForceWindowCreation(ClientPtr client)
993{
994 REQUEST(xDMXForceWindowCreationReq);
995
996 swaps(&stuff->length);
997 REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq);
998 swapl(&stuff->window);
999 return ProcDMXForceWindowCreation(client);
1000}
1001
1002static int
1003SProcDMXGetScreenCount(ClientPtr client)
1004{
1005 REQUEST(xDMXGetScreenCountReq);
1006
1007 swaps(&stuff->length);
1008 REQUEST_SIZE_MATCH(xDMXGetScreenCountReq);
1009 return ProcDMXGetScreenCount(client);
1010}
1011
1012static int
1013SProcDMXGetScreenAttributes(ClientPtr client)
1014{
1015 REQUEST(xDMXGetScreenAttributesReq);
1016
1017 swaps(&stuff->length);
1018 REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq);
1019 swapl(&stuff->physicalScreen);
1020 return ProcDMXGetScreenAttributes(client);
1021}
1022
1023static int
1024SProcDMXChangeScreensAttributes(ClientPtr client)
1025{
1026 REQUEST(xDMXChangeScreensAttributesReq);
1027
1028 swaps(&stuff->length);
1029 REQUEST_AT_LEAST_SIZE(xDMXGetScreenAttributesReq);
1030 swapl(&stuff->screenCount);
1031 swapl(&stuff->maskCount);
1032 SwapRestL(stuff);
1033 return ProcDMXGetScreenAttributes(client);
1034}
1035
1036static int
1037SProcDMXAddScreen(ClientPtr client)
1038{
1039 int paddedLength;
1040
1041 REQUEST(xDMXAddScreenReq);
1042
1043 swaps(&stuff->length);
1044 REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq);
1045 swapl(&stuff->displayNameLength);
1046 swapl(&stuff->valueMask);
1047 paddedLength = pad_to_int32(stuff->displayNameLength);
1048 SwapLongs((CARD32 *) (stuff + 1), LengthRestL(stuff) - paddedLength / 4);
1049 return ProcDMXAddScreen(client);
1050}
1051
1052static int
1053SProcDMXRemoveScreen(ClientPtr client)
1054{
1055 REQUEST(xDMXRemoveScreenReq);
1056
1057 swaps(&stuff->length);
1058 REQUEST_SIZE_MATCH(xDMXRemoveScreenReq);
1059 swapl(&stuff->physicalScreen);
1060 return ProcDMXRemoveScreen(client);
1061}
1062
1063static int
1064SProcDMXGetWindowAttributes(ClientPtr client)
1065{
1066 REQUEST(xDMXGetWindowAttributesReq);
1067
1068 swaps(&stuff->length);
1069 REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq);
1070 swapl(&stuff->window);
1071 return ProcDMXGetWindowAttributes(client);
1072}
1073
1074static int
1075SProcDMXGetDesktopAttributes(ClientPtr client)
1076{
1077 REQUEST(xDMXGetDesktopAttributesReq);
1078
1079 swaps(&stuff->length);
1080 REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq);
1081 return ProcDMXGetDesktopAttributes(client);
1082}
1083
1084static int
1085SProcDMXChangeDesktopAttributes(ClientPtr client)
1086{
1087 REQUEST(xDMXChangeDesktopAttributesReq);
1088
1089 swaps(&stuff->length);
1090 REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq);
1091 swapl(&stuff->valueMask);
1092 SwapRestL(stuff);
1093 return ProcDMXChangeDesktopAttributes(client);
1094}
1095
1096static int
1097SProcDMXGetInputCount(ClientPtr client)
1098{
1099 REQUEST(xDMXGetInputCountReq);
1100
1101 swaps(&stuff->length);
1102 REQUEST_SIZE_MATCH(xDMXGetInputCountReq);
1103 return ProcDMXGetInputCount(client);
1104}
1105
1106static int
1107SProcDMXGetInputAttributes(ClientPtr client)
1108{
1109 REQUEST(xDMXGetInputAttributesReq);
1110
1111 swaps(&stuff->length);
1112 REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq);
1113 swapl(&stuff->deviceId);
1114 return ProcDMXGetInputAttributes(client);
1115}
1116
1117static int
1118SProcDMXAddInput(ClientPtr client)
1119{
1120 int paddedLength;
1121
1122 REQUEST(xDMXAddInputReq);
1123
1124 swaps(&stuff->length);
1125 REQUEST_AT_LEAST_SIZE(xDMXAddInputReq);
1126 swapl(&stuff->displayNameLength);
1127 swapl(&stuff->valueMask);
1128 paddedLength = pad_to_int32(stuff->displayNameLength);
1129 SwapLongs((CARD32 *) (stuff + 1), LengthRestL(stuff) - paddedLength / 4);
1130 return ProcDMXAddInput(client);
1131}
1132
1133static int
1134SProcDMXRemoveInput(ClientPtr client)
1135{
1136 REQUEST(xDMXRemoveInputReq);
1137
1138 swaps(&stuff->length);
1139 REQUEST_SIZE_MATCH(xDMXRemoveInputReq);
1140 swapl(&stuff->physicalId);
1141 return ProcDMXRemoveInput(client);
1142}
1143
1144static int
1145SProcDMXDispatch(ClientPtr client)
1146{
1147 REQUEST(xReq);
1148
1149 switch (stuff->data) {
1150 case X_DMXQueryVersion:
1151 return SProcDMXQueryVersion(client);
1152 case X_DMXSync:
1153 return SProcDMXSync(client);
1154 case X_DMXForceWindowCreation:
1155 return SProcDMXForceWindowCreation(client);
1156 case X_DMXGetScreenCount:
1157 return SProcDMXGetScreenCount(client);
1158 case X_DMXGetScreenAttributes:
1159 return SProcDMXGetScreenAttributes(client);
1160 case X_DMXChangeScreensAttributes:
1161 return SProcDMXChangeScreensAttributes(client);
1162 case X_DMXAddScreen:
1163 return SProcDMXAddScreen(client);
1164 case X_DMXRemoveScreen:
1165 return SProcDMXRemoveScreen(client);
1166 case X_DMXGetWindowAttributes:
1167 return SProcDMXGetWindowAttributes(client);
1168 case X_DMXGetDesktopAttributes:
1169 return SProcDMXGetDesktopAttributes(client);
1170 case X_DMXChangeDesktopAttributes:
1171 return SProcDMXChangeDesktopAttributes(client);
1172 case X_DMXGetInputCount:
1173 return SProcDMXGetInputCount(client);
1174 case X_DMXGetInputAttributes:
1175 return SProcDMXGetInputAttributes(client);
1176 case X_DMXAddInput:
1177 return SProcDMXAddInput(client);
1178 case X_DMXRemoveInput:
1179 return SProcDMXRemoveInput(client);
1180
1181 case X_DMXGetScreenInformationDEPRECATED:
1182 case X_DMXForceWindowCreationDEPRECATED:
1183 case X_DMXReconfigureScreenDEPRECATED:
1184 return BadImplementation;
1185
1186 default:
1187 return BadRequest;
1188 }
1189}
1190
1191/** Initialize the extension. */
1192void
1193DMXExtensionInit(void)
1194{
1195 ExtensionEntry *extEntry;
1196
1197 if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0,
1198 ProcDMXDispatch, SProcDMXDispatch,
1199 NULL, StandardMinorOpcode)))
1200 DMXCode = extEntry->base;
1201}