vmwarexinerama.c revision 6df26cac
1/*
2 * Copyright 2006 by VMware, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * vmwarexinerama.c --
30 *
31 *      The implementation of the Xinerama protocol extension.
32 */
33
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#define NEED_REPLIES
40#define NEED_EVENTS
41#include "dixstruct.h"
42#include "extnsionst.h"
43#include <X11/X.h>
44#include <X11/extensions/panoramiXproto.h>
45
46#include "vmware.h"
47
48
49/*
50 *----------------------------------------------------------------------------
51 *
52 * VMwareXineramaQueryVersion --
53 *
54 *      Implementation of QueryVersion command handler. Initialises and
55 *      sends a reply.
56 *
57 * Results:
58 *      Standard response codes.
59 *
60 * Side effects:
61 *      Writes reply to client.
62 *
63 *----------------------------------------------------------------------------
64 */
65
66static int
67VMwareXineramaQueryVersion(ClientPtr client)
68{
69    xPanoramiXQueryVersionReply	  rep;
70    register int		  n;
71
72    REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
73    rep.type = X_Reply;
74    rep.length = 0;
75    rep.sequenceNumber = client->sequence;
76    rep.majorVersion = 1;
77    rep.minorVersion = 0;
78    if(client->swapped) {
79        swaps(&rep.sequenceNumber, n);
80        swapl(&rep.length, n);
81        swaps(&rep.majorVersion, n);
82        swaps(&rep.minorVersion, n);
83    }
84    WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep);
85    return (client->noClientException);
86}
87
88
89/*
90 *----------------------------------------------------------------------------
91 *
92 * VMwareXineramaGetState --
93 *
94 *      Implementation of GetState command handler. Initialises and
95 *      sends a reply.
96 *
97 * Results:
98 *      Standard response codes.
99 *
100 * Side effects:
101 *      Writes reply to client.
102 *
103 *----------------------------------------------------------------------------
104 */
105
106static int
107VMwareXineramaGetState(ClientPtr client)
108{
109    REQUEST(xPanoramiXGetStateReq);
110    WindowPtr			pWin;
111    xPanoramiXGetStateReply	rep;
112    register int		n;
113    ExtensionEntry *ext;
114    ScrnInfoPtr pScrn;
115    VMWAREPtr pVMWARE;
116
117    REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
118    pWin = LookupWindow(stuff->window, client);
119    if(!pWin) return BadWindow;
120
121    if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) {
122       return BadMatch;
123    }
124    pScrn = ext->extPrivate;
125    pVMWARE = VMWAREPTR(pScrn);
126
127    rep.type = X_Reply;
128    rep.length = 0;
129    rep.sequenceNumber = client->sequence;
130    rep.state = pVMWARE->xinerama;
131    if(client->swapped) {
132       swaps (&rep.sequenceNumber, n);
133       swapl (&rep.length, n);
134       swaps (&rep.state, n);
135    }
136    WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep);
137    return client->noClientException;
138}
139
140
141/*
142 *----------------------------------------------------------------------------
143 *
144 * VMwareXineramaGetScreenCount --
145 *
146 *      Implementation of GetScreenCount command handler. Initialises and
147 *      sends a reply.
148 *
149 * Results:
150 *      Standard response codes.
151 *
152 * Side effects:
153 *      Writes reply to client.
154 *
155 *----------------------------------------------------------------------------
156 */
157
158static int
159VMwareXineramaGetScreenCount(ClientPtr client)
160{
161    REQUEST(xPanoramiXGetScreenCountReq);
162    WindowPtr				pWin;
163    xPanoramiXGetScreenCountReply	rep;
164    register int			n;
165    ExtensionEntry *ext;
166    ScrnInfoPtr pScrn;
167    VMWAREPtr pVMWARE;
168
169    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
170    pWin = LookupWindow(stuff->window, client);
171    if(!pWin) return BadWindow;
172
173    if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) {
174       return BadMatch;
175    }
176    pScrn = ext->extPrivate;
177    pVMWARE = VMWAREPTR(pScrn);
178
179    rep.type = X_Reply;
180    rep.length = 0;
181    rep.sequenceNumber = client->sequence;
182    rep.ScreenCount = pVMWARE->xineramaNumOutputs;
183    if(client->swapped) {
184       swaps(&rep.sequenceNumber, n);
185       swapl(&rep.length, n);
186       swaps(&rep.ScreenCount, n);
187    }
188    WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
189    return client->noClientException;
190}
191
192
193/*
194 *----------------------------------------------------------------------------
195 *
196 * VMwareXineramaGetScreenSize --
197 *
198 *      Implementation of GetScreenSize command handler. Initialises and
199 *      sends a reply.
200 *
201 * Results:
202 *      Standard response codes.
203 *
204 * Side effects:
205 *      Writes reply to client.
206 *
207 *----------------------------------------------------------------------------
208 */
209
210static int
211VMwareXineramaGetScreenSize(ClientPtr client)
212{
213    REQUEST(xPanoramiXGetScreenSizeReq);
214    WindowPtr				pWin;
215    xPanoramiXGetScreenSizeReply	rep;
216    register int			n;
217    ExtensionEntry *ext;
218    ScrnInfoPtr pScrn;
219    VMWAREPtr pVMWARE;
220
221    REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
222    pWin = LookupWindow (stuff->window, client);
223    if(!pWin)  return BadWindow;
224
225    if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) {
226       return BadMatch;
227    }
228    pScrn = ext->extPrivate;
229    pVMWARE = VMWAREPTR(pScrn);
230
231    rep.type = X_Reply;
232    rep.length = 0;
233    rep.sequenceNumber = client->sequence;
234    rep.width  = pVMWARE->xineramaState[stuff->screen].width;
235    rep.height  = pVMWARE->xineramaState[stuff->screen].height;
236    if(client->swapped) {
237       swaps(&rep.sequenceNumber, n);
238       swapl(&rep.length, n);
239       swaps(&rep.width, n);
240       swaps(&rep.height, n);
241    }
242    WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
243    return client->noClientException;
244}
245
246
247/*
248 *----------------------------------------------------------------------------
249 *
250 * VMwareXineramaIsActive --
251 *
252 *      Implementation of IsActive command handler. Initialises and
253 *      sends a reply.
254 *
255 * Results:
256 *      Standard response codes.
257 *
258 * Side effects:
259 *      Writes reply to client.
260 *
261 *----------------------------------------------------------------------------
262 */
263
264static int
265VMwareXineramaIsActive(ClientPtr client)
266{
267    xXineramaIsActiveReply	rep;
268    ExtensionEntry *ext;
269    ScrnInfoPtr pScrn;
270    VMWAREPtr pVMWARE;
271
272    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
273
274    if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) {
275       return BadMatch;
276    }
277    pScrn = ext->extPrivate;
278    pVMWARE = VMWAREPTR(pScrn);
279
280    rep.type = X_Reply;
281    rep.length = 0;
282    rep.sequenceNumber = client->sequence;
283    rep.state = pVMWARE->xinerama;
284    if(client->swapped) {
285	register int n;
286	swaps(&rep.sequenceNumber, n);
287	swapl(&rep.length, n);
288	swapl(&rep.state, n);
289    }
290    WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep);
291    return client->noClientException;
292}
293
294
295/*
296 *----------------------------------------------------------------------------
297 *
298 * VMwareXineramaQueryScreens --
299 *
300 *      Implementation of QueryScreens command handler. Initialises and
301 *      sends a reply.
302 *
303 * Results:
304 *      Standard response codes.
305 *
306 * Side effects:
307 *      Writes reply to client.
308 *
309 *----------------------------------------------------------------------------
310 */
311
312static int
313VMwareXineramaQueryScreens(ClientPtr client)
314{
315    xXineramaQueryScreensReply	rep;
316    ExtensionEntry *ext;
317    ScrnInfoPtr pScrn;
318    VMWAREPtr pVMWARE;
319
320    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
321
322    if (!(ext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) {
323       return BadMatch;
324    }
325    pScrn = ext->extPrivate;
326    pVMWARE = VMWAREPTR(pScrn);
327
328    rep.type = X_Reply;
329    rep.sequenceNumber = client->sequence;
330    rep.number = pVMWARE->xinerama ? pVMWARE->xineramaNumOutputs : 0;
331    rep.length = rep.number * sz_XineramaScreenInfo >> 2;
332    if(client->swapped) {
333       register int n;
334       swaps(&rep.sequenceNumber, n);
335       swapl(&rep.length, n);
336       swapl(&rep.number, n);
337    }
338    WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep);
339
340    if(pVMWARE->xinerama) {
341       xXineramaScreenInfo scratch;
342       int i;
343
344       for(i = 0; i < pVMWARE->xineramaNumOutputs; i++) {
345	  scratch.x_org  = pVMWARE->xineramaState[i].x_org;
346	  scratch.y_org  = pVMWARE->xineramaState[i].y_org;
347	  scratch.width  = pVMWARE->xineramaState[i].width;
348	  scratch.height = pVMWARE->xineramaState[i].height;
349	  if(client->swapped) {
350	     register int n;
351	     swaps(&scratch.x_org, n);
352	     swaps(&scratch.y_org, n);
353	     swaps(&scratch.width, n);
354	     swaps(&scratch.height, n);
355	  }
356	  WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch);
357       }
358    }
359
360    return client->noClientException;
361}
362
363
364/*
365 *----------------------------------------------------------------------------
366 *
367 * VMwareXineramaDispatch --
368 *
369 *      Dispatcher for Xinerama commands. Calls the correct handler for
370 *      each command type.
371 *
372 * Results:
373 *      Standard response codes.
374 *
375 * Side effects:
376 *      Side effects of individual command handlers.
377 *
378 *----------------------------------------------------------------------------
379 */
380
381static int
382VMwareXineramaDispatch(ClientPtr client)
383{
384    REQUEST(xReq);
385    switch (stuff->data) {
386	case X_PanoramiXQueryVersion:
387	     return VMwareXineramaQueryVersion(client);
388	case X_PanoramiXGetState:
389	     return VMwareXineramaGetState(client);
390	case X_PanoramiXGetScreenCount:
391	     return VMwareXineramaGetScreenCount(client);
392	case X_PanoramiXGetScreenSize:
393	     return VMwareXineramaGetScreenSize(client);
394	case X_XineramaIsActive:
395	     return VMwareXineramaIsActive(client);
396	case X_XineramaQueryScreens:
397	     return VMwareXineramaQueryScreens(client);
398    }
399    return BadRequest;
400}
401
402
403/*
404 *----------------------------------------------------------------------------
405 *
406 * SVMwareXineramaQueryVersion --
407 *
408 *      Wrapper for QueryVersion handler that handles input from other-endian
409 *      clients.
410 *
411 * Results:
412 *      Standard response codes.
413 *
414 * Side effects:
415 *      Side effects of unswapped implementation.
416 *
417 *----------------------------------------------------------------------------
418 */
419
420static int
421SVMwareXineramaQueryVersion (ClientPtr client)
422{
423    REQUEST(xPanoramiXQueryVersionReq);
424    register int n;
425    swaps(&stuff->length,n);
426    REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
427    return VMwareXineramaQueryVersion(client);
428}
429
430
431/*
432 *----------------------------------------------------------------------------
433 *
434 * SVMwareXineramaGetState --
435 *
436 *      Wrapper for GetState handler that handles input from other-endian
437 *      clients.
438 *
439 * Results:
440 *      Standard response codes.
441 *
442 * Side effects:
443 *      Side effects of unswapped implementation.
444 *
445 *----------------------------------------------------------------------------
446 */
447
448static int
449SVMwareXineramaGetState(ClientPtr client)
450{
451    REQUEST(xPanoramiXGetStateReq);
452    register int n;
453    swaps (&stuff->length, n);
454    REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
455    return VMwareXineramaGetState(client);
456}
457
458
459/*
460 *----------------------------------------------------------------------------
461 *
462 * SVMwareXineramaGetScreenCount --
463 *
464 *      Wrapper for GetScreenCount handler that handles input from other-endian
465 *      clients.
466 *
467 * Results:
468 *      Standard response codes.
469 *
470 * Side effects:
471 *      Side effects of unswapped implementation.
472 *
473 *----------------------------------------------------------------------------
474 */
475
476static int
477SVMwareXineramaGetScreenCount(ClientPtr client)
478{
479    REQUEST(xPanoramiXGetScreenCountReq);
480    register int n;
481    swaps (&stuff->length, n);
482    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
483    return VMwareXineramaGetScreenCount(client);
484}
485
486
487/*
488 *----------------------------------------------------------------------------
489 *
490 * SVMwareXineramaGetScreenSize --
491 *
492 *      Wrapper for GetScreenSize handler that handles input from other-endian
493 *      clients.
494 *
495 * Results:
496 *      Standard response codes.
497 *
498 * Side effects:
499 *      Side effects of unswapped implementation.
500 *
501 *----------------------------------------------------------------------------
502 */
503
504static int
505SVMwareXineramaGetScreenSize(ClientPtr client)
506{
507    REQUEST(xPanoramiXGetScreenSizeReq);
508    register int n;
509    swaps (&stuff->length, n);
510    REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
511    return VMwareXineramaGetScreenSize(client);
512}
513
514
515/*
516 *----------------------------------------------------------------------------
517 *
518 * SVMwareXineramaIsActive --
519 *
520 *      Wrapper for IsActive handler that handles input from other-endian
521 *      clients.
522 *
523 * Results:
524 *      Standard response codes.
525 *
526 * Side effects:
527 *      Side effects of unswapped implementation.
528 *
529 *----------------------------------------------------------------------------
530 */
531
532static int
533SVMwareXineramaIsActive(ClientPtr client)
534{
535    REQUEST(xXineramaIsActiveReq);
536    register int n;
537    swaps (&stuff->length, n);
538    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
539    return VMwareXineramaIsActive(client);
540}
541
542
543/*
544 *----------------------------------------------------------------------------
545 *
546 * SVMwareXineramaQueryScreens --
547 *
548 *      Wrapper for QueryScreens handler that handles input from other-endian
549 *      clients.
550 *
551 * Results:
552 *      Standard response codes.
553 *
554 * Side effects:
555 *      Side effects of unswapped implementation.
556 *
557 *----------------------------------------------------------------------------
558 */
559
560static int
561SVMwareXineramaQueryScreens(ClientPtr client)
562{
563    REQUEST(xXineramaQueryScreensReq);
564    register int n;
565    swaps (&stuff->length, n);
566    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
567    return VMwareXineramaQueryScreens(client);
568}
569
570
571/*
572 *----------------------------------------------------------------------------
573 *
574 * SVMwareXineramaDispatch --
575 *
576 *      Wrapper for dispatcher that handles input from other-endian clients.
577 *
578 * Results:
579 *      Standard response codes.
580 *
581 * Side effects:
582 *      Side effects of individual command handlers.
583 *
584 *----------------------------------------------------------------------------
585 */
586
587static int
588SVMwareXineramaDispatch(ClientPtr client)
589{
590    REQUEST(xReq);
591    switch (stuff->data) {
592	case X_PanoramiXQueryVersion:
593	     return SVMwareXineramaQueryVersion(client);
594	case X_PanoramiXGetState:
595	     return SVMwareXineramaGetState(client);
596	case X_PanoramiXGetScreenCount:
597	     return SVMwareXineramaGetScreenCount(client);
598	case X_PanoramiXGetScreenSize:
599	     return SVMwareXineramaGetScreenSize(client);
600	case X_XineramaIsActive:
601	     return SVMwareXineramaIsActive(client);
602	case X_XineramaQueryScreens:
603	     return SVMwareXineramaQueryScreens(client);
604    }
605    return BadRequest;
606}
607
608
609/*
610 *----------------------------------------------------------------------------
611 *
612 * VMwareXineramaResetProc --
613 *
614 *      Cleanup handler called when the extension is removed.
615 *
616 * Results:
617 *      None
618 *
619 * Side effects:
620 *      None
621 *
622 *----------------------------------------------------------------------------
623 */
624
625static void
626VMwareXineramaResetProc(ExtensionEntry* extEntry)
627{
628    /* Called by CloseDownExtensions() */
629
630   ScrnInfoPtr pScrn = extEntry->extPrivate;
631   VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
632
633   if (pVMWARE->xineramaState) {
634      xfree(pVMWARE->xineramaState);
635      pVMWARE->xineramaState = NULL;
636      pVMWARE->xineramaNumOutputs = 0;
637      pVMWARE->xinerama = FALSE;
638   }
639}
640
641
642/*
643 *----------------------------------------------------------------------------
644 *
645 * VMwareCtrl_ExitInit --
646 *
647 *      Initialiser for the Xinerama protocol extension.
648 *
649 * Results:
650 *      None.
651 *
652 * Side effects:
653 *      Protocol extension will be registered if successful.
654 *
655 *----------------------------------------------------------------------------
656 */
657
658void
659VMwareXinerama_ExtInit(ScrnInfoPtr pScrn)
660{
661   ExtensionEntry *myext;
662   VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
663
664#ifdef PANORAMIX
665   if(!noPanoramiXExtension) {
666      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
667                 "Built-in Xinerama active, not initializing VMware Xinerama\n");
668      pVMWARE->xinerama = FALSE;
669      return;
670   }
671#endif
672
673   if (!(myext = CheckExtension(PANORAMIX_PROTOCOL_NAME))) {
674      if (!(myext = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
675                                 VMwareXineramaDispatch,
676                                 SVMwareXineramaDispatch,
677                                 VMwareXineramaResetProc,
678                                 StandardMinorOpcode))) {
679         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
680                    "Failed to add VMware Xinerama extension.\n");
681         return;
682      }
683
684      pVMWARE->xinerama = TRUE;
685
686      myext->extPrivate = pScrn;
687
688      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
689                 "Initialized VMware Xinerama extension.\n");
690   }
691}
692