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(®ion, &box, 1);
1258*4882a593Smuzhiyun DamageReportDamage(scrpriv->pDamage, ®ion);
1259*4882a593Smuzhiyun RegionUninit(®ion);
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