1 /*
2  * Xephyr - A kdrive X server thats runs in a host X window.
3  *          Authored by Matthew Allum <mallum@openedhand.com>
4  *
5  * Copyright © 2004 Nokia
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Nokia not be used in
12  * advertising or publicity pertaining to distribution of the software without
13  * specific, written prior permission. Nokia makes no
14  * representations about the suitability of this software for any purpose.  It
15  * is provided "as is" without express or implied warranty.
16  *
17  * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19  * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  */
25 
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
28 #endif
29 
30 #include <xcb/xcb_keysyms.h>
31 #include <X11/keysym.h>
32 
33 #include "ephyr.h"
34 
35 #include "inputstr.h"
36 #include "scrnintstr.h"
37 #include "ephyrlog.h"
38 
39 #ifdef GLAMOR
40 #include "glamor.h"
41 #endif
42 #include "ephyr_glamor_glx.h"
43 #include "glx_extinit.h"
44 #include "xkbsrv.h"
45 
46 extern Bool ephyr_glamor;
47 
48 KdKeyboardInfo *ephyrKbd;
49 KdPointerInfo *ephyrMouse;
50 Bool ephyrNoDRI = FALSE;
51 Bool ephyrNoXV = FALSE;
52 
53 static int mouseState = 0;
54 static Rotation ephyrRandr = RR_Rotate_0;
55 
56 typedef struct _EphyrInputPrivate {
57     Bool enabled;
58 } EphyrKbdPrivate, EphyrPointerPrivate;
59 
60 Bool EphyrWantGrayScale = 0;
61 Bool EphyrWantResize = 0;
62 Bool EphyrWantNoHostGrab = 0;
63 
64 Bool
ephyrInitialize(KdCardInfo * card,EphyrPriv * priv)65 ephyrInitialize(KdCardInfo * card, EphyrPriv * priv)
66 {
67     OsSignal(SIGUSR1, hostx_handle_signal);
68 
69     priv->base = 0;
70     priv->bytes_per_line = 0;
71     return TRUE;
72 }
73 
74 Bool
ephyrCardInit(KdCardInfo * card)75 ephyrCardInit(KdCardInfo * card)
76 {
77     EphyrPriv *priv;
78 
79     priv = (EphyrPriv *) malloc(sizeof(EphyrPriv));
80     if (!priv)
81         return FALSE;
82 
83     if (!ephyrInitialize(card, priv)) {
84         free(priv);
85         return FALSE;
86     }
87     card->driver = priv;
88 
89     return TRUE;
90 }
91 
92 Bool
ephyrScreenInitialize(KdScreenInfo * screen)93 ephyrScreenInitialize(KdScreenInfo *screen)
94 {
95     EphyrScrPriv *scrpriv = screen->driver;
96     int x = 0, y = 0;
97     int width = 640, height = 480;
98     CARD32 redMask, greenMask, blueMask;
99 
100     if (hostx_want_screen_geometry(screen, &width, &height, &x, &y)
101         || !screen->width || !screen->height) {
102         screen->width = width;
103         screen->height = height;
104         screen->x = x;
105         screen->y = y;
106     }
107 
108     if (EphyrWantGrayScale)
109         screen->fb.depth = 8;
110 
111     if (screen->fb.depth && screen->fb.depth != hostx_get_depth()) {
112         if (screen->fb.depth < hostx_get_depth()
113             && (screen->fb.depth == 24 || screen->fb.depth == 16
114                 || screen->fb.depth == 8)) {
115             scrpriv->server_depth = screen->fb.depth;
116         }
117         else
118             ErrorF
119                 ("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
120     }
121 
122     screen->fb.depth = hostx_get_server_depth(screen);
123     screen->rate = 72;
124 
125     if (screen->fb.depth <= 8) {
126         if (EphyrWantGrayScale)
127             screen->fb.visuals = ((1 << StaticGray) | (1 << GrayScale));
128         else
129             screen->fb.visuals = ((1 << StaticGray) |
130                                   (1 << GrayScale) |
131                                   (1 << StaticColor) |
132                                   (1 << PseudoColor) |
133                                   (1 << TrueColor) | (1 << DirectColor));
134 
135         screen->fb.redMask = 0x00;
136         screen->fb.greenMask = 0x00;
137         screen->fb.blueMask = 0x00;
138         screen->fb.depth = 8;
139         screen->fb.bitsPerPixel = 8;
140     }
141     else {
142         screen->fb.visuals = (1 << TrueColor);
143 
144         if (screen->fb.depth <= 15) {
145             screen->fb.depth = 15;
146             screen->fb.bitsPerPixel = 16;
147         }
148         else if (screen->fb.depth <= 16) {
149             screen->fb.depth = 16;
150             screen->fb.bitsPerPixel = 16;
151         }
152         else if (screen->fb.depth <= 24) {
153             screen->fb.depth = 24;
154             screen->fb.bitsPerPixel = 32;
155         }
156         else if (screen->fb.depth <= 30) {
157             screen->fb.depth = 30;
158             screen->fb.bitsPerPixel = 32;
159         }
160         else {
161             ErrorF("\nXephyr: Unsupported screen depth %d\n", screen->fb.depth);
162             return FALSE;
163         }
164 
165         hostx_get_visual_masks(screen, &redMask, &greenMask, &blueMask);
166 
167         screen->fb.redMask = (Pixel) redMask;
168         screen->fb.greenMask = (Pixel) greenMask;
169         screen->fb.blueMask = (Pixel) blueMask;
170 
171     }
172 
173     scrpriv->randr = screen->randr;
174 
175     return ephyrMapFramebuffer(screen);
176 }
177 
178 void *
ephyrWindowLinear(ScreenPtr pScreen,CARD32 row,CARD32 offset,int mode,CARD32 * size,void * closure)179 ephyrWindowLinear(ScreenPtr pScreen,
180                   CARD32 row,
181                   CARD32 offset, int mode, CARD32 *size, void *closure)
182 {
183     KdScreenPriv(pScreen);
184     EphyrPriv *priv = pScreenPriv->card->driver;
185 
186     if (!pScreenPriv->enabled)
187         return 0;
188 
189     *size = priv->bytes_per_line;
190     return priv->base + row * priv->bytes_per_line + offset;
191 }
192 
193 /**
194  * Figure out display buffer size. If fakexa is enabled, allocate a larger
195  * buffer so that fakexa has space to put offscreen pixmaps.
196  */
197 int
ephyrBufferHeight(KdScreenInfo * screen)198 ephyrBufferHeight(KdScreenInfo * screen)
199 {
200     int buffer_height;
201 
202     if (ephyrFuncs.initAccel == NULL)
203         buffer_height = screen->height;
204     else
205         buffer_height = 3 * screen->height;
206     return buffer_height;
207 }
208 
209 Bool
ephyrMapFramebuffer(KdScreenInfo * screen)210 ephyrMapFramebuffer(KdScreenInfo * screen)
211 {
212     EphyrScrPriv *scrpriv = screen->driver;
213     EphyrPriv *priv = screen->card->driver;
214     KdPointerMatrix m;
215     int buffer_height;
216 
217     EPHYR_LOG("screen->width: %d, screen->height: %d index=%d",
218               screen->width, screen->height, screen->mynum);
219 
220     /*
221      * Use the rotation last applied to ourselves (in the Xephyr case the fb
222      * coordinate system moves independently of the pointer coordiante system).
223      */
224     KdComputePointerMatrix(&m, ephyrRandr, screen->width, screen->height);
225     KdSetPointerMatrix(&m);
226 
227     buffer_height = ephyrBufferHeight(screen);
228 
229     priv->base =
230         hostx_screen_init(screen, screen->x, screen->y,
231                           screen->width, screen->height, buffer_height,
232                           &priv->bytes_per_line, &screen->fb.bitsPerPixel);
233 
234     if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) {
235         scrpriv->shadow = FALSE;
236 
237         screen->fb.byteStride = priv->bytes_per_line;
238         screen->fb.pixelStride = screen->width;
239         screen->fb.frameBuffer = (CARD8 *) (priv->base);
240     }
241     else {
242         /* Rotated/Reflected so we need to use shadow fb */
243         scrpriv->shadow = TRUE;
244 
245         EPHYR_LOG("allocing shadow");
246 
247         KdShadowFbAlloc(screen,
248                         scrpriv->randr & (RR_Rotate_90 | RR_Rotate_270));
249     }
250 
251     return TRUE;
252 }
253 
254 void
ephyrSetScreenSizes(ScreenPtr pScreen)255 ephyrSetScreenSizes(ScreenPtr pScreen)
256 {
257     KdScreenPriv(pScreen);
258     KdScreenInfo *screen = pScreenPriv->screen;
259     EphyrScrPriv *scrpriv = screen->driver;
260 
261     if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) {
262         pScreen->width = screen->width;
263         pScreen->height = screen->height;
264         pScreen->mmWidth = screen->width_mm;
265         pScreen->mmHeight = screen->height_mm;
266     }
267     else {
268         pScreen->width = screen->height;
269         pScreen->height = screen->width;
270         pScreen->mmWidth = screen->height_mm;
271         pScreen->mmHeight = screen->width_mm;
272     }
273 }
274 
275 Bool
ephyrUnmapFramebuffer(KdScreenInfo * screen)276 ephyrUnmapFramebuffer(KdScreenInfo * screen)
277 {
278     EphyrScrPriv *scrpriv = screen->driver;
279 
280     if (scrpriv->shadow)
281         KdShadowFbFree(screen);
282 
283     /* Note, priv->base will get freed when XImage recreated */
284 
285     return TRUE;
286 }
287 
288 void
ephyrShadowUpdate(ScreenPtr pScreen,shadowBufPtr pBuf)289 ephyrShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
290 {
291     KdScreenPriv(pScreen);
292     KdScreenInfo *screen = pScreenPriv->screen;
293 
294     EPHYR_LOG("slow paint");
295 
296     /* FIXME: Slow Rotated/Reflected updates could be much
297      * much faster efficiently updating via tranforming
298      * pBuf->pDamage  regions
299      */
300     shadowUpdateRotatePacked(pScreen, pBuf);
301     hostx_paint_rect(screen, 0, 0, 0, 0, screen->width, screen->height);
302 }
303 
304 static void
ephyrInternalDamageRedisplay(ScreenPtr pScreen)305 ephyrInternalDamageRedisplay(ScreenPtr pScreen)
306 {
307     KdScreenPriv(pScreen);
308     KdScreenInfo *screen = pScreenPriv->screen;
309     EphyrScrPriv *scrpriv = screen->driver;
310     RegionPtr pRegion;
311 
312     if (!scrpriv || !scrpriv->pDamage)
313         return;
314 
315     pRegion = DamageRegion(scrpriv->pDamage);
316 
317     if (RegionNotEmpty(pRegion)) {
318         int nbox;
319         BoxPtr pbox;
320 
321         if (ephyr_glamor) {
322             ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion);
323         } else {
324             nbox = RegionNumRects(pRegion);
325             pbox = RegionRects(pRegion);
326 
327             while (nbox--) {
328                 hostx_paint_rect(screen,
329                                  pbox->x1, pbox->y1,
330                                  pbox->x1, pbox->y1,
331                                  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
332                 pbox++;
333             }
334         }
335         DamageEmpty(scrpriv->pDamage);
336     }
337 }
338 
339 static void
340 ephyrXcbProcessEvents(Bool queued_only);
341 
342 static Bool
ephyrEventWorkProc(ClientPtr client,void * closure)343 ephyrEventWorkProc(ClientPtr client, void *closure)
344 {
345     ephyrXcbProcessEvents(TRUE);
346     return TRUE;
347 }
348 
349 static void
ephyrScreenBlockHandler(ScreenPtr pScreen,void * timeout)350 ephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout)
351 {
352     KdScreenPriv(pScreen);
353     KdScreenInfo *screen = pScreenPriv->screen;
354     EphyrScrPriv *scrpriv = screen->driver;
355 
356     pScreen->BlockHandler = scrpriv->BlockHandler;
357     (*pScreen->BlockHandler)(pScreen, timeout);
358     scrpriv->BlockHandler = pScreen->BlockHandler;
359     pScreen->BlockHandler = ephyrScreenBlockHandler;
360 
361     if (scrpriv->pDamage)
362         ephyrInternalDamageRedisplay(pScreen);
363 
364     if (hostx_has_queued_event()) {
365         if (!QueueWorkProc(ephyrEventWorkProc, NULL, NULL))
366             FatalError("cannot queue event processing in ephyr block handler");
367         AdjustWaitForDelay(timeout, 0);
368     }
369 }
370 
371 Bool
ephyrSetInternalDamage(ScreenPtr pScreen)372 ephyrSetInternalDamage(ScreenPtr pScreen)
373 {
374     KdScreenPriv(pScreen);
375     KdScreenInfo *screen = pScreenPriv->screen;
376     EphyrScrPriv *scrpriv = screen->driver;
377     PixmapPtr pPixmap = NULL;
378 
379     scrpriv->pDamage = DamageCreate((DamageReportFunc) 0,
380                                     (DamageDestroyFunc) 0,
381                                     DamageReportNone, TRUE, pScreen, pScreen);
382 
383     pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
384 
385     DamageRegister(&pPixmap->drawable, scrpriv->pDamage);
386 
387     return TRUE;
388 }
389 
390 void
ephyrUnsetInternalDamage(ScreenPtr pScreen)391 ephyrUnsetInternalDamage(ScreenPtr pScreen)
392 {
393     KdScreenPriv(pScreen);
394     KdScreenInfo *screen = pScreenPriv->screen;
395     EphyrScrPriv *scrpriv = screen->driver;
396 
397     DamageDestroy(scrpriv->pDamage);
398     scrpriv->pDamage = NULL;
399 }
400 
401 #ifdef RANDR
402 Bool
ephyrRandRGetInfo(ScreenPtr pScreen,Rotation * rotations)403 ephyrRandRGetInfo(ScreenPtr pScreen, Rotation * rotations)
404 {
405     KdScreenPriv(pScreen);
406     KdScreenInfo *screen = pScreenPriv->screen;
407     EphyrScrPriv *scrpriv = screen->driver;
408     RRScreenSizePtr pSize;
409     Rotation randr;
410     int n = 0;
411 
412     struct {
413         int width, height;
414     } sizes[] = {
415         {1600, 1200},
416         {1400, 1050},
417         {1280, 960},
418         {1280, 1024},
419         {1152, 864},
420         {1024, 768},
421         {832, 624},
422         {800, 600},
423         {720, 400},
424         {480, 640},
425         {640, 480},
426         {640, 400},
427         {320, 240},
428         {240, 320},
429         {160, 160},
430         {0, 0}
431     };
432 
433     EPHYR_LOG("mark");
434 
435     *rotations = RR_Rotate_All | RR_Reflect_All;
436 
437     if (!hostx_want_preexisting_window(screen)
438         && !hostx_want_fullscreen()) {  /* only if no -parent switch */
439         while (sizes[n].width != 0 && sizes[n].height != 0) {
440             RRRegisterSize(pScreen,
441                            sizes[n].width,
442                            sizes[n].height,
443                            (sizes[n].width * screen->width_mm) / screen->width,
444                            (sizes[n].height * screen->height_mm) /
445                            screen->height);
446             n++;
447         }
448     }
449 
450     pSize = RRRegisterSize(pScreen,
451                            screen->width,
452                            screen->height, screen->width_mm, screen->height_mm);
453 
454     randr = KdSubRotation(scrpriv->randr, screen->randr);
455 
456     RRSetCurrentConfig(pScreen, randr, 0, pSize);
457 
458     return TRUE;
459 }
460 
461 Bool
ephyrRandRSetConfig(ScreenPtr pScreen,Rotation randr,int rate,RRScreenSizePtr pSize)462 ephyrRandRSetConfig(ScreenPtr pScreen,
463                     Rotation randr, int rate, RRScreenSizePtr pSize)
464 {
465     KdScreenPriv(pScreen);
466     KdScreenInfo *screen = pScreenPriv->screen;
467     EphyrScrPriv *scrpriv = screen->driver;
468     Bool wasEnabled = pScreenPriv->enabled;
469     EphyrScrPriv oldscr;
470     int oldwidth, oldheight, oldmmwidth, oldmmheight;
471     Bool oldshadow;
472     int newwidth, newheight;
473 
474     if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) {
475         newwidth = pSize->width;
476         newheight = pSize->height;
477     }
478     else {
479         newwidth = pSize->height;
480         newheight = pSize->width;
481     }
482 
483     if (wasEnabled)
484         KdDisableScreen(pScreen);
485 
486     oldscr = *scrpriv;
487 
488     oldwidth = screen->width;
489     oldheight = screen->height;
490     oldmmwidth = pScreen->mmWidth;
491     oldmmheight = pScreen->mmHeight;
492     oldshadow = scrpriv->shadow;
493 
494     /*
495      * Set new configuration
496      */
497 
498     /*
499      * We need to store the rotation value for pointer coords transformation;
500      * though initially the pointer and fb rotation are identical, when we map
501      * the fb, the screen will be reinitialized and return into an unrotated
502      * state (presumably the HW is taking care of the rotation of the fb), but the
503      * pointer still needs to be transformed.
504      */
505     ephyrRandr = KdAddRotation(screen->randr, randr);
506     scrpriv->randr = ephyrRandr;
507 
508     ephyrUnmapFramebuffer(screen);
509 
510     screen->width = newwidth;
511     screen->height = newheight;
512 
513     scrpriv->win_width = screen->width;
514     scrpriv->win_height = screen->height;
515 #ifdef GLAMOR
516     ephyr_glamor_set_window_size(scrpriv->glamor,
517                                  scrpriv->win_width,
518                                  scrpriv->win_height);
519 #endif
520 
521     if (!ephyrMapFramebuffer(screen))
522         goto bail4;
523 
524     /* FIXME below should go in own call */
525 
526     if (oldshadow)
527         KdShadowUnset(screen->pScreen);
528     else
529         ephyrUnsetInternalDamage(screen->pScreen);
530 
531     ephyrSetScreenSizes(screen->pScreen);
532 
533     if (scrpriv->shadow) {
534         if (!KdShadowSet(screen->pScreen,
535                          scrpriv->randr, ephyrShadowUpdate, ephyrWindowLinear))
536             goto bail4;
537     }
538     else {
539 #ifdef GLAMOR
540         if (ephyr_glamor)
541             ephyr_glamor_create_screen_resources(pScreen);
542 #endif
543         /* Without shadow fb ( non rotated ) we need
544          * to use damage to efficiently update display
545          * via signal regions what to copy from 'fb'.
546          */
547         if (!ephyrSetInternalDamage(screen->pScreen))
548             goto bail4;
549     }
550 
551     /*
552      * Set frame buffer mapping
553      */
554     (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap(pScreen),
555                                     pScreen->width,
556                                     pScreen->height,
557                                     screen->fb.depth,
558                                     screen->fb.bitsPerPixel,
559                                     screen->fb.byteStride,
560                                     screen->fb.frameBuffer);
561 
562     /* set the subpixel order */
563 
564     KdSetSubpixelOrder(pScreen, scrpriv->randr);
565 
566     if (wasEnabled)
567         KdEnableScreen(pScreen);
568 
569     RRScreenSizeNotify(pScreen);
570 
571     return TRUE;
572 
573  bail4:
574     EPHYR_LOG("bailed");
575 
576     ephyrUnmapFramebuffer(screen);
577     *scrpriv = oldscr;
578     (void) ephyrMapFramebuffer(screen);
579 
580     pScreen->width = oldwidth;
581     pScreen->height = oldheight;
582     pScreen->mmWidth = oldmmwidth;
583     pScreen->mmHeight = oldmmheight;
584 
585     if (wasEnabled)
586         KdEnableScreen(pScreen);
587     return FALSE;
588 }
589 
590 Bool
ephyrRandRInit(ScreenPtr pScreen)591 ephyrRandRInit(ScreenPtr pScreen)
592 {
593     rrScrPrivPtr pScrPriv;
594 
595     if (!RRScreenInit(pScreen))
596         return FALSE;
597 
598     pScrPriv = rrGetScrPriv(pScreen);
599     pScrPriv->rrGetInfo = ephyrRandRGetInfo;
600     pScrPriv->rrSetConfig = ephyrRandRSetConfig;
601     return TRUE;
602 }
603 
604 static Bool
ephyrResizeScreen(ScreenPtr pScreen,int newwidth,int newheight)605 ephyrResizeScreen (ScreenPtr           pScreen,
606                   int                  newwidth,
607                   int                  newheight)
608 {
609     KdScreenPriv(pScreen);
610     KdScreenInfo *screen = pScreenPriv->screen;
611     RRScreenSize size = {0};
612     Bool ret;
613     int t;
614 
615     if (screen->randr & (RR_Rotate_90|RR_Rotate_270)) {
616         t = newwidth;
617         newwidth = newheight;
618         newheight = t;
619     }
620 
621     if (newwidth == screen->width && newheight == screen->height) {
622         return FALSE;
623     }
624 
625     size.width = newwidth;
626     size.height = newheight;
627 
628     hostx_size_set_from_configure(TRUE);
629     ret = ephyrRandRSetConfig (pScreen, screen->randr, 0, &size);
630     hostx_size_set_from_configure(FALSE);
631     if (ret) {
632         RROutputPtr output;
633 
634         output = RRFirstOutput(pScreen);
635         if (!output)
636             return FALSE;
637         RROutputSetModes(output, NULL, 0, 0);
638     }
639 
640     return ret;
641 }
642 #endif
643 
644 Bool
ephyrCreateColormap(ColormapPtr pmap)645 ephyrCreateColormap(ColormapPtr pmap)
646 {
647     return fbInitializeColormap(pmap);
648 }
649 
650 Bool
ephyrInitScreen(ScreenPtr pScreen)651 ephyrInitScreen(ScreenPtr pScreen)
652 {
653     KdScreenPriv(pScreen);
654     KdScreenInfo *screen = pScreenPriv->screen;
655 
656     EPHYR_LOG("pScreen->myNum:%d\n", pScreen->myNum);
657     hostx_set_screen_number(screen, pScreen->myNum);
658     if (EphyrWantNoHostGrab) {
659         hostx_set_win_title(screen, "xephyr");
660     } else {
661         hostx_set_win_title(screen, "(ctrl+shift grabs mouse and keyboard)");
662     }
663     pScreen->CreateColormap = ephyrCreateColormap;
664 
665 #ifdef XV
666     if (!ephyrNoXV) {
667         if (ephyr_glamor)
668             ephyr_glamor_xv_init(pScreen);
669         else if (!ephyrInitVideo(pScreen)) {
670             EPHYR_LOG_ERROR("failed to initialize xvideo\n");
671         }
672         else {
673             EPHYR_LOG("initialized xvideo okay\n");
674         }
675     }
676 #endif /*XV*/
677 
678     return TRUE;
679 }
680 
681 
682 Bool
ephyrFinishInitScreen(ScreenPtr pScreen)683 ephyrFinishInitScreen(ScreenPtr pScreen)
684 {
685     KdScreenPriv(pScreen);
686     KdScreenInfo *screen = pScreenPriv->screen;
687     EphyrScrPriv *scrpriv = screen->driver;
688 
689     /* FIXME: Calling this even if not using shadow.
690      * Seems harmless enough. But may be safer elsewhere.
691      */
692     if (!shadowSetup(pScreen))
693         return FALSE;
694 
695 #ifdef RANDR
696     if (!ephyrRandRInit(pScreen))
697         return FALSE;
698 #endif
699 
700     scrpriv->BlockHandler = pScreen->BlockHandler;
701     pScreen->BlockHandler = ephyrScreenBlockHandler;
702 
703     return TRUE;
704 }
705 
706 /**
707  * Called by kdrive after calling down the
708  * pScreen->CreateScreenResources() chain, this gives us a chance to
709  * make any pixmaps after the screen and all extensions have been
710  * initialized.
711  */
712 Bool
ephyrCreateResources(ScreenPtr pScreen)713 ephyrCreateResources(ScreenPtr pScreen)
714 {
715     KdScreenPriv(pScreen);
716     KdScreenInfo *screen = pScreenPriv->screen;
717     EphyrScrPriv *scrpriv = screen->driver;
718 
719     EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d",
720               pScreen, pScreen->myNum, scrpriv->shadow);
721 
722     if (scrpriv->shadow)
723         return KdShadowSet(pScreen,
724                            scrpriv->randr,
725                            ephyrShadowUpdate, ephyrWindowLinear);
726     else {
727 #ifdef GLAMOR
728         if (ephyr_glamor) {
729             if (!ephyr_glamor_create_screen_resources(pScreen))
730                 return FALSE;
731         }
732 #endif
733         return ephyrSetInternalDamage(pScreen);
734     }
735 }
736 
737 void
ephyrScreenFini(KdScreenInfo * screen)738 ephyrScreenFini(KdScreenInfo * screen)
739 {
740     EphyrScrPriv *scrpriv = screen->driver;
741 
742     if (scrpriv->shadow) {
743         KdShadowFbFree(screen);
744     }
745     scrpriv->BlockHandler = NULL;
746 }
747 
748 void
ephyrCloseScreen(ScreenPtr pScreen)749 ephyrCloseScreen(ScreenPtr pScreen)
750 {
751     ephyrUnsetInternalDamage(pScreen);
752 }
753 
754 /*
755  * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
756  * See https://bugs.freedesktop.org/show_bug.cgi?id=3030
757  */
758 void
ephyrUpdateModifierState(unsigned int state)759 ephyrUpdateModifierState(unsigned int state)
760 {
761 
762     DeviceIntPtr pDev = inputInfo.keyboard;
763     KeyClassPtr keyc = pDev->key;
764     int i;
765     CARD8 mask;
766     int xkb_state;
767 
768     if (!pDev)
769         return;
770 
771     xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
772     state = state & 0xff;
773 
774     if (xkb_state == state)
775         return;
776 
777     for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
778         int key;
779 
780         /* Modifier is down, but shouldn't be
781          */
782         if ((xkb_state & mask) && !(state & mask)) {
783             int count = keyc->modifierKeyCount[i];
784 
785             for (key = 0; key < MAP_LENGTH; key++)
786                 if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
787                     if (mask == XCB_MOD_MASK_LOCK) {
788                         KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE);
789                         KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE);
790                     }
791                     else if (key_is_down(pDev, key, KEY_PROCESSED))
792                         KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE);
793 
794                     if (--count == 0)
795                         break;
796                 }
797         }
798 
799         /* Modifier shoud be down, but isn't
800          */
801         if (!(xkb_state & mask) && (state & mask))
802             for (key = 0; key < MAP_LENGTH; key++)
803                 if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
804                     KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE);
805                     if (mask == XCB_MOD_MASK_LOCK)
806                         KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE);
807                     break;
808                 }
809     }
810 }
811 
812 static Bool
ephyrCursorOffScreen(ScreenPtr * ppScreen,int * x,int * y)813 ephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
814 {
815     return FALSE;
816 }
817 
818 static void
ephyrCrossScreen(ScreenPtr pScreen,Bool entering)819 ephyrCrossScreen(ScreenPtr pScreen, Bool entering)
820 {
821 }
822 
823 ScreenPtr ephyrCursorScreen; /* screen containing the cursor */
824 
825 static void
ephyrWarpCursor(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y)826 ephyrWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
827 {
828     input_lock();
829     ephyrCursorScreen = pScreen;
830     miPointerWarpCursor(inputInfo.pointer, pScreen, x, y);
831 
832     input_unlock();
833 }
834 
835 miPointerScreenFuncRec ephyrPointerScreenFuncs = {
836     ephyrCursorOffScreen,
837     ephyrCrossScreen,
838     ephyrWarpCursor,
839 };
840 
841 static KdScreenInfo *
screen_from_window(Window w)842 screen_from_window(Window w)
843 {
844     int i = 0;
845 
846     for (i = 0; i < screenInfo.numScreens; i++) {
847         ScreenPtr pScreen = screenInfo.screens[i];
848         KdPrivScreenPtr kdscrpriv = KdGetScreenPriv(pScreen);
849         KdScreenInfo *screen = kdscrpriv->screen;
850         EphyrScrPriv *scrpriv = screen->driver;
851 
852         if (scrpriv->win == w
853             || scrpriv->peer_win == w
854             || scrpriv->win_pre_existing == w) {
855             return screen;
856         }
857     }
858 
859     return NULL;
860 }
861 
862 static void
ephyrProcessErrorEvent(xcb_generic_event_t * xev)863 ephyrProcessErrorEvent(xcb_generic_event_t *xev)
864 {
865     xcb_generic_error_t *e = (xcb_generic_error_t *)xev;
866 
867     FatalError("X11 error\n"
868                "Error code: %hhu\n"
869                "Sequence number: %hu\n"
870                "Major code: %hhu\tMinor code: %hu\n"
871                "Error value: %u\n",
872                e->error_code,
873                e->sequence,
874                e->major_code, e->minor_code,
875                e->resource_id);
876 }
877 
878 static void
ephyrProcessExpose(xcb_generic_event_t * xev)879 ephyrProcessExpose(xcb_generic_event_t *xev)
880 {
881     xcb_expose_event_t *expose = (xcb_expose_event_t *)xev;
882     KdScreenInfo *screen = screen_from_window(expose->window);
883     EphyrScrPriv *scrpriv = screen->driver;
884 
885     /* Wait for the last expose event in a series of cliprects
886      * to actually paint our screen.
887      */
888     if (expose->count != 0)
889         return;
890 
891     if (scrpriv) {
892         hostx_paint_rect(scrpriv->screen, 0, 0, 0, 0,
893                          scrpriv->win_width,
894                          scrpriv->win_height);
895     } else {
896         EPHYR_LOG_ERROR("failed to get host screen\n");
897     }
898 }
899 
900 static void
ephyrProcessMouseMotion(xcb_generic_event_t * xev)901 ephyrProcessMouseMotion(xcb_generic_event_t *xev)
902 {
903     xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)xev;
904     KdScreenInfo *screen = screen_from_window(motion->event);
905 
906     if (!ephyrMouse ||
907         !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
908         EPHYR_LOG("skipping mouse motion:%d\n", screen->pScreen->myNum);
909         return;
910     }
911 
912     if (ephyrCursorScreen != screen->pScreen) {
913         EPHYR_LOG("warping mouse cursor. "
914                   "cur_screen:%d, motion_screen:%d\n",
915                   ephyrCursorScreen->myNum, screen->pScreen->myNum);
916         ephyrWarpCursor(inputInfo.pointer, screen->pScreen,
917                         motion->event_x, motion->event_y);
918     }
919     else {
920         int x = 0, y = 0;
921 
922         EPHYR_LOG("enqueuing mouse motion:%d\n", screen->pScreen->myNum);
923         x = motion->event_x;
924         y = motion->event_y;
925         EPHYR_LOG("initial (x,y):(%d,%d)\n", x, y);
926 
927         /* convert coords into desktop-wide coordinates.
928          * fill_pointer_events will convert that back to
929          * per-screen coordinates where needed */
930         x += screen->pScreen->x;
931         y += screen->pScreen->y;
932 
933         KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_POINTER_DESKTOP, x, y, 0);
934     }
935 }
936 
937 static void
ephyrProcessButtonPress(xcb_generic_event_t * xev)938 ephyrProcessButtonPress(xcb_generic_event_t *xev)
939 {
940     xcb_button_press_event_t *button = (xcb_button_press_event_t *)xev;
941 
942     if (!ephyrMouse ||
943         !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
944         EPHYR_LOG("skipping mouse press:%d\n", screen_from_window(button->event)->pScreen->myNum);
945         return;
946     }
947 
948     ephyrUpdateModifierState(button->state);
949     /* This is a bit hacky. will break for button 5 ( defined as 0x10 )
950      * Check KD_BUTTON defines in kdrive.h
951      */
952     mouseState |= 1 << (button->detail - 1);
953 
954     EPHYR_LOG("enqueuing mouse press:%d\n", screen_from_window(button->event)->pScreen->myNum);
955     KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_MOUSE_DELTA, 0, 0, 0);
956 }
957 
958 static void
ephyrProcessButtonRelease(xcb_generic_event_t * xev)959 ephyrProcessButtonRelease(xcb_generic_event_t *xev)
960 {
961     xcb_button_press_event_t *button = (xcb_button_press_event_t *)xev;
962 
963     if (!ephyrMouse ||
964         !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) {
965         return;
966     }
967 
968     ephyrUpdateModifierState(button->state);
969     mouseState &= ~(1 << (button->detail - 1));
970 
971     EPHYR_LOG("enqueuing mouse release:%d\n", screen_from_window(button->event)->pScreen->myNum);
972     KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_MOUSE_DELTA, 0, 0, 0);
973 }
974 
975 /* Xephyr wants ctrl+shift to grab the window, but that conflicts with
976    ctrl+alt+shift key combos. Remember the modifier state on key presses and
977    releases, if mod1 is pressed, we need ctrl, shift and mod1 released
978    before we allow a shift-ctrl grab activation.
979 
980    note: a key event contains the mask _before_ the current key takes
981    effect, so mod1_was_down will be reset on the first key press after all
982    three were released, not on the last release. That'd require some more
983    effort.
984  */
985 static int
ephyrUpdateGrabModifierState(int state)986 ephyrUpdateGrabModifierState(int state)
987 {
988     static int mod1_was_down = 0;
989 
990     if ((state & (XCB_MOD_MASK_CONTROL|XCB_MOD_MASK_SHIFT|XCB_MOD_MASK_1)) == 0)
991         mod1_was_down = 0;
992     else if (state & XCB_MOD_MASK_1)
993         mod1_was_down = 1;
994 
995     return mod1_was_down;
996 }
997 
998 static void
ephyrProcessKeyPress(xcb_generic_event_t * xev)999 ephyrProcessKeyPress(xcb_generic_event_t *xev)
1000 {
1001     xcb_key_press_event_t *key = (xcb_key_press_event_t *)xev;
1002 
1003     if (!ephyrKbd ||
1004         !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) {
1005         return;
1006     }
1007 
1008     ephyrUpdateGrabModifierState(key->state);
1009     ephyrUpdateModifierState(key->state);
1010     KdEnqueueKeyboardEvent(ephyrKbd, key->detail, FALSE);
1011 }
1012 
1013 static void
ephyrProcessKeyRelease(xcb_generic_event_t * xev)1014 ephyrProcessKeyRelease(xcb_generic_event_t *xev)
1015 {
1016     xcb_connection_t *conn = hostx_get_xcbconn();
1017     xcb_key_release_event_t *key = (xcb_key_release_event_t *)xev;
1018     static xcb_key_symbols_t *keysyms;
1019     static int grabbed_screen = -1;
1020     int mod1_down = ephyrUpdateGrabModifierState(key->state);
1021 
1022     if (!keysyms)
1023         keysyms = xcb_key_symbols_alloc(conn);
1024 
1025     if (!EphyrWantNoHostGrab &&
1026         (((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_L
1027           || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_R)
1028          && (key->state & XCB_MOD_MASK_CONTROL)) ||
1029         ((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_L
1030           || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_R)
1031          && (key->state & XCB_MOD_MASK_SHIFT)))) {
1032         KdScreenInfo *screen = screen_from_window(key->event);
1033         EphyrScrPriv *scrpriv = screen->driver;
1034 
1035         if (grabbed_screen != -1) {
1036             xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME);
1037             xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME);
1038             grabbed_screen = -1;
1039             hostx_set_win_title(screen,
1040                                 "(ctrl+shift grabs mouse and keyboard)");
1041         }
1042         else if (!mod1_down) {
1043             /* Attempt grab */
1044             xcb_grab_keyboard_cookie_t kbgrabc =
1045                 xcb_grab_keyboard(conn,
1046                                   TRUE,
1047                                   scrpriv->win,
1048                                   XCB_TIME_CURRENT_TIME,
1049                                   XCB_GRAB_MODE_ASYNC,
1050                                   XCB_GRAB_MODE_ASYNC);
1051             xcb_grab_keyboard_reply_t *kbgrabr;
1052             xcb_grab_pointer_cookie_t pgrabc =
1053                 xcb_grab_pointer(conn,
1054                                  TRUE,
1055                                  scrpriv->win,
1056                                  0,
1057                                  XCB_GRAB_MODE_ASYNC,
1058                                  XCB_GRAB_MODE_ASYNC,
1059                                  scrpriv->win,
1060                                  XCB_NONE,
1061                                  XCB_TIME_CURRENT_TIME);
1062             xcb_grab_pointer_reply_t *pgrabr;
1063             kbgrabr = xcb_grab_keyboard_reply(conn, kbgrabc, NULL);
1064             if (!kbgrabr || kbgrabr->status != XCB_GRAB_STATUS_SUCCESS) {
1065                 xcb_discard_reply(conn, pgrabc.sequence);
1066                 xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME);
1067             } else {
1068                 pgrabr = xcb_grab_pointer_reply(conn, pgrabc, NULL);
1069                 if (!pgrabr || pgrabr->status != XCB_GRAB_STATUS_SUCCESS)
1070                     {
1071                         xcb_ungrab_keyboard(conn,
1072                                             XCB_TIME_CURRENT_TIME);
1073                     } else {
1074                     grabbed_screen = scrpriv->mynum;
1075                     hostx_set_win_title
1076                         (screen,
1077                          "(ctrl+shift releases mouse and keyboard)");
1078                 }
1079             }
1080         }
1081     }
1082 
1083     if (!ephyrKbd ||
1084         !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) {
1085         return;
1086     }
1087 
1088     /* Still send the release event even if above has happened server
1089      * will get confused with just an up event.  Maybe it would be
1090      * better to just block shift+ctrls getting to kdrive all
1091      * together.
1092      */
1093     ephyrUpdateModifierState(key->state);
1094     KdEnqueueKeyboardEvent(ephyrKbd, key->detail, TRUE);
1095 }
1096 
1097 static void
ephyrProcessConfigureNotify(xcb_generic_event_t * xev)1098 ephyrProcessConfigureNotify(xcb_generic_event_t *xev)
1099 {
1100     xcb_configure_notify_event_t *configure =
1101         (xcb_configure_notify_event_t *)xev;
1102     KdScreenInfo *screen = screen_from_window(configure->window);
1103     EphyrScrPriv *scrpriv = screen->driver;
1104 
1105     if (!scrpriv ||
1106         (scrpriv->win_pre_existing == None && !EphyrWantResize)) {
1107         return;
1108     }
1109 
1110 #ifdef RANDR
1111     ephyrResizeScreen(screen->pScreen, configure->width, configure->height);
1112 #endif /* RANDR */
1113 }
1114 
1115 static void
ephyrXcbProcessEvents(Bool queued_only)1116 ephyrXcbProcessEvents(Bool queued_only)
1117 {
1118     xcb_connection_t *conn = hostx_get_xcbconn();
1119     xcb_generic_event_t *expose = NULL, *configure = NULL;
1120 
1121     while (TRUE) {
1122         xcb_generic_event_t *xev = hostx_get_event(queued_only);
1123 
1124         if (!xev) {
1125             /* If our XCB connection has died (for example, our window was
1126              * closed), exit now.
1127              */
1128             if (xcb_connection_has_error(conn)) {
1129                 CloseWellKnownConnections();
1130                 OsCleanup(1);
1131                 exit(1);
1132             }
1133 
1134             break;
1135         }
1136 
1137         switch (xev->response_type & 0x7f) {
1138         case 0:
1139             ephyrProcessErrorEvent(xev);
1140             break;
1141 
1142         case XCB_EXPOSE:
1143             free(expose);
1144             expose = xev;
1145             xev = NULL;
1146             break;
1147 
1148         case XCB_MOTION_NOTIFY:
1149             ephyrProcessMouseMotion(xev);
1150             break;
1151 
1152         case XCB_KEY_PRESS:
1153             ephyrProcessKeyPress(xev);
1154             break;
1155 
1156         case XCB_KEY_RELEASE:
1157             ephyrProcessKeyRelease(xev);
1158             break;
1159 
1160         case XCB_BUTTON_PRESS:
1161             ephyrProcessButtonPress(xev);
1162             break;
1163 
1164         case XCB_BUTTON_RELEASE:
1165             ephyrProcessButtonRelease(xev);
1166             break;
1167 
1168         case XCB_CONFIGURE_NOTIFY:
1169             free(configure);
1170             configure = xev;
1171             xev = NULL;
1172             break;
1173         }
1174 
1175         if (xev) {
1176             if (ephyr_glamor)
1177                 ephyr_glamor_process_event(xev);
1178 
1179             free(xev);
1180         }
1181     }
1182 
1183     if (configure) {
1184         ephyrProcessConfigureNotify(configure);
1185         free(configure);
1186     }
1187 
1188     if (expose) {
1189         ephyrProcessExpose(expose);
1190         free(expose);
1191     }
1192 }
1193 
1194 static void
ephyrXcbNotify(int fd,int ready,void * data)1195 ephyrXcbNotify(int fd, int ready, void *data)
1196 {
1197     ephyrXcbProcessEvents(FALSE);
1198 }
1199 
1200 void
ephyrCardFini(KdCardInfo * card)1201 ephyrCardFini(KdCardInfo * card)
1202 {
1203     EphyrPriv *priv = card->driver;
1204 
1205     free(priv);
1206 }
1207 
1208 void
ephyrGetColors(ScreenPtr pScreen,int n,xColorItem * pdefs)1209 ephyrGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
1210 {
1211     /* XXX Not sure if this is right */
1212 
1213     EPHYR_LOG("mark");
1214 
1215     while (n--) {
1216         pdefs->red = 0;
1217         pdefs->green = 0;
1218         pdefs->blue = 0;
1219         pdefs++;
1220     }
1221 
1222 }
1223 
1224 void
ephyrPutColors(ScreenPtr pScreen,int n,xColorItem * pdefs)1225 ephyrPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
1226 {
1227     KdScreenPriv(pScreen);
1228     KdScreenInfo *screen = pScreenPriv->screen;
1229     EphyrScrPriv *scrpriv = screen->driver;
1230     int min, max, p;
1231 
1232     /* XXX Not sure if this is right */
1233 
1234     min = 256;
1235     max = 0;
1236 
1237     while (n--) {
1238         p = pdefs->pixel;
1239         if (p < min)
1240             min = p;
1241         if (p > max)
1242             max = p;
1243 
1244         hostx_set_cmap_entry(pScreen, p,
1245                              pdefs->red >> 8,
1246                              pdefs->green >> 8, pdefs->blue >> 8);
1247         pdefs++;
1248     }
1249     if (scrpriv->pDamage) {
1250         BoxRec box;
1251         RegionRec region;
1252 
1253         box.x1 = 0;
1254         box.y1 = 0;
1255         box.x2 = pScreen->width;
1256         box.y2 = pScreen->height;
1257         RegionInit(&region, &box, 1);
1258         DamageReportDamage(scrpriv->pDamage, &region);
1259         RegionUninit(&region);
1260     }
1261 }
1262 
1263 /* Mouse calls */
1264 
1265 static Status
MouseInit(KdPointerInfo * pi)1266 MouseInit(KdPointerInfo * pi)
1267 {
1268     pi->driverPrivate = (EphyrPointerPrivate *)
1269         calloc(sizeof(EphyrPointerPrivate), 1);
1270     ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE;
1271     pi->nAxes = 3;
1272     pi->nButtons = 32;
1273     free(pi->name);
1274     pi->name = strdup("Xephyr virtual mouse");
1275 
1276     /*
1277      * Must transform pointer coords since the pointer position
1278      * relative to the Xephyr window is controlled by the host server and
1279      * remains constant regardless of any rotation applied to the Xephyr screen.
1280      */
1281     pi->transformCoordinates = TRUE;
1282 
1283     ephyrMouse = pi;
1284     return Success;
1285 }
1286 
1287 static Status
MouseEnable(KdPointerInfo * pi)1288 MouseEnable(KdPointerInfo * pi)
1289 {
1290     ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = TRUE;
1291     SetNotifyFd(hostx_get_fd(), ephyrXcbNotify, X_NOTIFY_READ, NULL);
1292     return Success;
1293 }
1294 
1295 static void
MouseDisable(KdPointerInfo * pi)1296 MouseDisable(KdPointerInfo * pi)
1297 {
1298     ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE;
1299     RemoveNotifyFd(hostx_get_fd());
1300     return;
1301 }
1302 
1303 static void
MouseFini(KdPointerInfo * pi)1304 MouseFini(KdPointerInfo * pi)
1305 {
1306     free(pi->driverPrivate);
1307     ephyrMouse = NULL;
1308     return;
1309 }
1310 
1311 KdPointerDriver EphyrMouseDriver = {
1312     "ephyr",
1313     MouseInit,
1314     MouseEnable,
1315     MouseDisable,
1316     MouseFini,
1317     NULL,
1318 };
1319 
1320 /* Keyboard */
1321 
1322 static Status
EphyrKeyboardInit(KdKeyboardInfo * ki)1323 EphyrKeyboardInit(KdKeyboardInfo * ki)
1324 {
1325     KeySymsRec keySyms;
1326     CARD8 modmap[MAP_LENGTH];
1327     XkbControlsRec controls;
1328 
1329     ki->driverPrivate = (EphyrKbdPrivate *)
1330         calloc(sizeof(EphyrKbdPrivate), 1);
1331 
1332     if (hostx_load_keymap(&keySyms, modmap, &controls)) {
1333         XkbApplyMappingChange(ki->dixdev, &keySyms,
1334                               keySyms.minKeyCode,
1335                               keySyms.maxKeyCode - keySyms.minKeyCode + 1,
1336                               modmap, serverClient);
1337         XkbDDXChangeControls(ki->dixdev, &controls, &controls);
1338         free(keySyms.map);
1339     }
1340 
1341     ki->minScanCode = keySyms.minKeyCode;
1342     ki->maxScanCode = keySyms.maxKeyCode;
1343 
1344     if (ki->name != NULL) {
1345         free(ki->name);
1346     }
1347 
1348     ki->name = strdup("Xephyr virtual keyboard");
1349     ephyrKbd = ki;
1350     return Success;
1351 }
1352 
1353 static Status
EphyrKeyboardEnable(KdKeyboardInfo * ki)1354 EphyrKeyboardEnable(KdKeyboardInfo * ki)
1355 {
1356     ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = TRUE;
1357 
1358     return Success;
1359 }
1360 
1361 static void
EphyrKeyboardDisable(KdKeyboardInfo * ki)1362 EphyrKeyboardDisable(KdKeyboardInfo * ki)
1363 {
1364     ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = FALSE;
1365 }
1366 
1367 static void
EphyrKeyboardFini(KdKeyboardInfo * ki)1368 EphyrKeyboardFini(KdKeyboardInfo * ki)
1369 {
1370     free(ki->driverPrivate);
1371     ephyrKbd = NULL;
1372     return;
1373 }
1374 
1375 static void
EphyrKeyboardLeds(KdKeyboardInfo * ki,int leds)1376 EphyrKeyboardLeds(KdKeyboardInfo * ki, int leds)
1377 {
1378 }
1379 
1380 static void
EphyrKeyboardBell(KdKeyboardInfo * ki,int volume,int frequency,int duration)1381 EphyrKeyboardBell(KdKeyboardInfo * ki, int volume, int frequency, int duration)
1382 {
1383 }
1384 
1385 KdKeyboardDriver EphyrKeyboardDriver = {
1386     "ephyr",
1387     EphyrKeyboardInit,
1388     EphyrKeyboardEnable,
1389     EphyrKeyboardLeds,
1390     EphyrKeyboardBell,
1391     EphyrKeyboardDisable,
1392     EphyrKeyboardFini,
1393     NULL,
1394 };
1395