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