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