2 * Xephyr - A kdrive X server thats runs in a host X window.
3 * Authored by Matthew Allum <mallum@openedhand.com>
5 * Copyright © 2004 Nokia
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Nokia not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Nokia makes no
14 * representations about the suitability of this software for any purpose. It
15 * is provided "as is" without express or implied warranty.
17 * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
27 #include <kdrive-config.h>
30 #include <xcb/xcb_keysyms.h>
31 #include <X11/keysym.h>
36 #include "scrnintstr.h"
40 #include <xcb/xf86dri.h>
42 #include "ephyrdriext.h"
43 #include "ephyrglxext.h"
48 extern int KdTsPhyScreen
;
50 KdKeyboardInfo
*ephyrKbd
;
51 KdPointerInfo
*ephyrMouse
;
52 EphyrKeySyms ephyrKeySyms
;
53 Bool ephyrNoDRI
= FALSE
;
54 Bool ephyrNoXV
= FALSE
;
56 static int mouseState
= 0;
57 static Rotation ephyrRandr
= RR_Rotate_0
;
59 typedef struct _EphyrInputPrivate
{
61 } EphyrKbdPrivate
, EphyrPointerPrivate
;
63 Bool EphyrWantGrayScale
= 0;
64 Bool EphyrWantResize
= 0;
67 host_has_extension(xcb_extension_t
*extension
)
69 const xcb_query_extension_reply_t
*rep
;
71 rep
= xcb_get_extension_data(hostx_get_xcbconn(), extension
);
73 return rep
&& rep
->present
;
77 ephyrInitialize(KdCardInfo
* card
, EphyrPriv
* priv
)
79 OsSignal(SIGUSR1
, hostx_handle_signal
);
82 priv
->bytes_per_line
= 0;
87 ephyrCardInit(KdCardInfo
* card
)
91 priv
= (EphyrPriv
*) malloc(sizeof(EphyrPriv
));
95 if (!ephyrInitialize(card
, priv
)) {
105 ephyrScreenInitialize(KdScreenInfo
*screen
)
107 EphyrScrPriv
*scrpriv
= screen
->driver
;
108 int width
= 640, height
= 480;
109 CARD32 redMask
, greenMask
, blueMask
;
111 if (hostx_want_screen_size(screen
, &width
, &height
)
112 || !screen
->width
|| !screen
->height
) {
113 screen
->width
= width
;
114 screen
->height
= height
;
117 if (EphyrWantGrayScale
)
118 screen
->fb
.depth
= 8;
120 if (screen
->fb
.depth
&& screen
->fb
.depth
!= hostx_get_depth()) {
121 if (screen
->fb
.depth
< hostx_get_depth()
122 && (screen
->fb
.depth
== 24 || screen
->fb
.depth
== 16
123 || screen
->fb
.depth
== 8)) {
124 scrpriv
->server_depth
= screen
->fb
.depth
;
128 ("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
131 screen
->fb
.depth
= hostx_get_server_depth(screen
);
134 if (screen
->fb
.depth
<= 8) {
135 if (EphyrWantGrayScale
)
136 screen
->fb
.visuals
= ((1 << StaticGray
) | (1 << GrayScale
));
138 screen
->fb
.visuals
= ((1 << StaticGray
) |
142 (1 << TrueColor
) | (1 << DirectColor
));
144 screen
->fb
.redMask
= 0x00;
145 screen
->fb
.greenMask
= 0x00;
146 screen
->fb
.blueMask
= 0x00;
147 screen
->fb
.depth
= 8;
148 screen
->fb
.bitsPerPixel
= 8;
151 screen
->fb
.visuals
= (1 << TrueColor
);
153 if (screen
->fb
.depth
<= 15) {
154 screen
->fb
.depth
= 15;
155 screen
->fb
.bitsPerPixel
= 16;
157 else if (screen
->fb
.depth
<= 16) {
158 screen
->fb
.depth
= 16;
159 screen
->fb
.bitsPerPixel
= 16;
161 else if (screen
->fb
.depth
<= 24) {
162 screen
->fb
.depth
= 24;
163 screen
->fb
.bitsPerPixel
= 32;
165 else if (screen
->fb
.depth
<= 30) {
166 screen
->fb
.depth
= 30;
167 screen
->fb
.bitsPerPixel
= 32;
170 ErrorF("\nXephyr: Unsupported screen depth %d\n", screen
->fb
.depth
);
174 hostx_get_visual_masks(screen
, &redMask
, &greenMask
, &blueMask
);
176 screen
->fb
.redMask
= (Pixel
) redMask
;
177 screen
->fb
.greenMask
= (Pixel
) greenMask
;
178 screen
->fb
.blueMask
= (Pixel
) blueMask
;
182 scrpriv
->randr
= screen
->randr
;
184 return ephyrMapFramebuffer(screen
);
188 ephyrWindowLinear(ScreenPtr pScreen
,
190 CARD32 offset
, int mode
, CARD32
*size
, void *closure
)
192 KdScreenPriv(pScreen
);
193 EphyrPriv
*priv
= pScreenPriv
->card
->driver
;
195 if (!pScreenPriv
->enabled
)
198 *size
= priv
->bytes_per_line
;
199 return priv
->base
+ row
* priv
->bytes_per_line
+ offset
;
203 * Figure out display buffer size. If fakexa is enabled, allocate a larger
204 * buffer so that fakexa has space to put offscreen pixmaps.
207 ephyrBufferHeight(KdScreenInfo
* screen
)
211 if (ephyrFuncs
.initAccel
== NULL
)
212 buffer_height
= screen
->height
;
214 buffer_height
= 3 * screen
->height
;
215 return buffer_height
;
219 ephyrMapFramebuffer(KdScreenInfo
* screen
)
221 EphyrScrPriv
*scrpriv
= screen
->driver
;
222 EphyrPriv
*priv
= screen
->card
->driver
;
226 EPHYR_LOG("screen->width: %d, screen->height: %d index=%d",
227 screen
->width
, screen
->height
, screen
->mynum
);
230 * Use the rotation last applied to ourselves (in the Xephyr case the fb
231 * coordinate system moves independently of the pointer coordiante system).
233 KdComputePointerMatrix(&m
, ephyrRandr
, screen
->width
, screen
->height
);
234 KdSetPointerMatrix(&m
);
236 buffer_height
= ephyrBufferHeight(screen
);
239 hostx_screen_init(screen
, screen
->width
, screen
->height
, buffer_height
,
240 &priv
->bytes_per_line
, &screen
->fb
.bitsPerPixel
);
242 if ((scrpriv
->randr
& RR_Rotate_0
) && !(scrpriv
->randr
& RR_Reflect_All
)) {
243 scrpriv
->shadow
= FALSE
;
245 screen
->fb
.byteStride
= priv
->bytes_per_line
;
246 screen
->fb
.pixelStride
= screen
->width
;
247 screen
->fb
.frameBuffer
= (CARD8
*) (priv
->base
);
250 /* Rotated/Reflected so we need to use shadow fb */
251 scrpriv
->shadow
= TRUE
;
253 EPHYR_LOG("allocing shadow");
255 KdShadowFbAlloc(screen
,
256 scrpriv
->randr
& (RR_Rotate_90
| RR_Rotate_270
));
263 ephyrSetScreenSizes(ScreenPtr pScreen
)
265 KdScreenPriv(pScreen
);
266 KdScreenInfo
*screen
= pScreenPriv
->screen
;
267 EphyrScrPriv
*scrpriv
= screen
->driver
;
269 if (scrpriv
->randr
& (RR_Rotate_0
| RR_Rotate_180
)) {
270 pScreen
->width
= screen
->width
;
271 pScreen
->height
= screen
->height
;
272 pScreen
->mmWidth
= screen
->width_mm
;
273 pScreen
->mmHeight
= screen
->height_mm
;
276 pScreen
->width
= screen
->height
;
277 pScreen
->height
= screen
->width
;
278 pScreen
->mmWidth
= screen
->height_mm
;
279 pScreen
->mmHeight
= screen
->width_mm
;
284 ephyrUnmapFramebuffer(KdScreenInfo
* screen
)
286 EphyrScrPriv
*scrpriv
= screen
->driver
;
289 KdShadowFbFree(screen
);
291 /* Note, priv->base will get freed when XImage recreated */
297 ephyrShadowUpdate(ScreenPtr pScreen
, shadowBufPtr pBuf
)
299 KdScreenPriv(pScreen
);
300 KdScreenInfo
*screen
= pScreenPriv
->screen
;
302 EPHYR_LOG("slow paint");
304 /* FIXME: Slow Rotated/Reflected updates could be much
305 * much faster efficiently updating via tranforming
306 * pBuf->pDamage regions
308 shadowUpdateRotatePacked(pScreen
, pBuf
);
309 hostx_paint_rect(screen
, 0, 0, 0, 0, screen
->width
, screen
->height
);
313 ephyrInternalDamageRedisplay(ScreenPtr pScreen
)
315 KdScreenPriv(pScreen
);
316 KdScreenInfo
*screen
= pScreenPriv
->screen
;
317 EphyrScrPriv
*scrpriv
= screen
->driver
;
320 if (!scrpriv
|| !scrpriv
->pDamage
)
323 pRegion
= DamageRegion(scrpriv
->pDamage
);
325 if (RegionNotEmpty(pRegion
)) {
329 nbox
= RegionNumRects(pRegion
);
330 pbox
= RegionRects(pRegion
);
333 hostx_paint_rect(screen
,
336 pbox
->x2
- pbox
->x1
, pbox
->y2
- pbox
->y1
);
339 DamageEmpty(scrpriv
->pDamage
);
344 ephyrInternalDamageBlockHandler(pointer data
, OSTimePtr pTimeout
, pointer pRead
)
346 ScreenPtr pScreen
= (ScreenPtr
) data
;
348 ephyrInternalDamageRedisplay(pScreen
);
352 ephyrInternalDamageWakeupHandler(pointer data
, int i
, pointer LastSelectMask
)
354 /* FIXME: Not needed ? */
358 ephyrSetInternalDamage(ScreenPtr pScreen
)
360 KdScreenPriv(pScreen
);
361 KdScreenInfo
*screen
= pScreenPriv
->screen
;
362 EphyrScrPriv
*scrpriv
= screen
->driver
;
363 PixmapPtr pPixmap
= NULL
;
365 scrpriv
->pDamage
= DamageCreate((DamageReportFunc
) 0,
366 (DamageDestroyFunc
) 0,
367 DamageReportNone
, TRUE
, pScreen
, pScreen
);
369 if (!RegisterBlockAndWakeupHandlers(ephyrInternalDamageBlockHandler
,
370 ephyrInternalDamageWakeupHandler
,
374 pPixmap
= (*pScreen
->GetScreenPixmap
) (pScreen
);
376 DamageRegister(&pPixmap
->drawable
, scrpriv
->pDamage
);
382 ephyrUnsetInternalDamage(ScreenPtr pScreen
)
384 KdScreenPriv(pScreen
);
385 KdScreenInfo
*screen
= pScreenPriv
->screen
;
386 EphyrScrPriv
*scrpriv
= screen
->driver
;
388 DamageDestroy(scrpriv
->pDamage
);
390 RemoveBlockAndWakeupHandlers(ephyrInternalDamageBlockHandler
,
391 ephyrInternalDamageWakeupHandler
,
397 ephyrRandRGetInfo(ScreenPtr pScreen
, Rotation
* rotations
)
399 KdScreenPriv(pScreen
);
400 KdScreenInfo
*screen
= pScreenPriv
->screen
;
401 EphyrScrPriv
*scrpriv
= screen
->driver
;
402 RRScreenSizePtr pSize
;
429 *rotations
= RR_Rotate_All
| RR_Reflect_All
;
431 if (!hostx_want_preexisting_window(screen
)
432 && !hostx_want_fullscreen()) { /* only if no -parent switch */
433 while (sizes
[n
].width
!= 0 && sizes
[n
].height
!= 0) {
434 RRRegisterSize(pScreen
,
437 (sizes
[n
].width
* screen
->width_mm
) / screen
->width
,
438 (sizes
[n
].height
* screen
->height_mm
) /
444 pSize
= RRRegisterSize(pScreen
,
446 screen
->height
, screen
->width_mm
, screen
->height_mm
);
448 randr
= KdSubRotation(scrpriv
->randr
, screen
->randr
);
450 RRSetCurrentConfig(pScreen
, randr
, 0, pSize
);
456 ephyrRandRSetConfig(ScreenPtr pScreen
,
457 Rotation randr
, int rate
, RRScreenSizePtr pSize
)
459 KdScreenPriv(pScreen
);
460 KdScreenInfo
*screen
= pScreenPriv
->screen
;
461 EphyrScrPriv
*scrpriv
= screen
->driver
;
462 Bool wasEnabled
= pScreenPriv
->enabled
;
464 int oldwidth
, oldheight
, oldmmwidth
, oldmmheight
;
466 int newwidth
, newheight
;
468 if (screen
->randr
& (RR_Rotate_0
| RR_Rotate_180
)) {
469 newwidth
= pSize
->width
;
470 newheight
= pSize
->height
;
473 newwidth
= pSize
->height
;
474 newheight
= pSize
->width
;
478 KdDisableScreen(pScreen
);
482 oldwidth
= screen
->width
;
483 oldheight
= screen
->height
;
484 oldmmwidth
= pScreen
->mmWidth
;
485 oldmmheight
= pScreen
->mmHeight
;
486 oldshadow
= scrpriv
->shadow
;
489 * Set new configuration
493 * We need to store the rotation value for pointer coords transformation;
494 * though initially the pointer and fb rotation are identical, when we map
495 * the fb, the screen will be reinitialized and return into an unrotated
496 * state (presumably the HW is taking care of the rotation of the fb), but the
497 * pointer still needs to be transformed.
499 ephyrRandr
= KdAddRotation(screen
->randr
, randr
);
500 scrpriv
->randr
= ephyrRandr
;
502 ephyrUnmapFramebuffer(screen
);
504 screen
->width
= newwidth
;
505 screen
->height
= newheight
;
507 if (!ephyrMapFramebuffer(screen
))
510 /* FIXME below should go in own call */
513 KdShadowUnset(screen
->pScreen
);
515 ephyrUnsetInternalDamage(screen
->pScreen
);
517 if (scrpriv
->shadow
) {
518 if (!KdShadowSet(screen
->pScreen
,
519 scrpriv
->randr
, ephyrShadowUpdate
, ephyrWindowLinear
))
523 /* Without shadow fb ( non rotated ) we need
524 * to use damage to efficiently update display
525 * via signal regions what to copy from 'fb'.
527 if (!ephyrSetInternalDamage(screen
->pScreen
))
531 ephyrSetScreenSizes(screen
->pScreen
);
534 * Set frame buffer mapping
536 (*pScreen
->ModifyPixmapHeader
) (fbGetScreenPixmap(pScreen
),
540 screen
->fb
.bitsPerPixel
,
541 screen
->fb
.byteStride
,
542 screen
->fb
.frameBuffer
);
544 /* set the subpixel order */
546 KdSetSubpixelOrder(pScreen
, scrpriv
->randr
);
549 KdEnableScreen(pScreen
);
551 RRScreenSizeNotify(pScreen
);
558 ephyrUnmapFramebuffer(screen
);
560 (void) ephyrMapFramebuffer(screen
);
562 pScreen
->width
= oldwidth
;
563 pScreen
->height
= oldheight
;
564 pScreen
->mmWidth
= oldmmwidth
;
565 pScreen
->mmHeight
= oldmmheight
;
568 KdEnableScreen(pScreen
);
573 ephyrRandRInit(ScreenPtr pScreen
)
575 rrScrPrivPtr pScrPriv
;
577 if (!RRScreenInit(pScreen
))
580 pScrPriv
= rrGetScrPriv(pScreen
);
581 pScrPriv
->rrGetInfo
= ephyrRandRGetInfo
;
582 pScrPriv
->rrSetConfig
= ephyrRandRSetConfig
;
587 ephyrResizeScreen (ScreenPtr pScreen
,
591 KdScreenPriv(pScreen
);
592 KdScreenInfo
*screen
= pScreenPriv
->screen
;
593 RRScreenSize size
= {0};
597 if (screen
->randr
& (RR_Rotate_90
|RR_Rotate_270
)) {
599 newwidth
= newheight
;
603 if (newwidth
== screen
->width
&& newheight
== screen
->height
) {
607 size
.width
= newwidth
;
608 size
.height
= newheight
;
610 ret
= ephyrRandRSetConfig (pScreen
, screen
->randr
, 0, &size
);
614 output
= RRFirstOutput(pScreen
);
617 RROutputSetModes(output
, NULL
, 0, 0);
625 ephyrCreateColormap(ColormapPtr pmap
)
627 return fbInitializeColormap(pmap
);
631 ephyrInitScreen(ScreenPtr pScreen
)
633 KdScreenPriv(pScreen
);
634 KdScreenInfo
*screen
= pScreenPriv
->screen
;
636 EPHYR_LOG("pScreen->myNum:%d\n", pScreen
->myNum
);
637 hostx_set_screen_number(screen
, pScreen
->myNum
);
638 hostx_set_win_title(screen
, "(ctrl+shift grabs mouse and keyboard)");
639 pScreen
->CreateColormap
= ephyrCreateColormap
;
643 if (!ephyrInitVideo(pScreen
)) {
644 EPHYR_LOG_ERROR("failed to initialize xvideo\n");
647 EPHYR_LOG("initialized xvideo okay\n");
652 if (!ephyrNoDRI
&& !host_has_extension(&xcb_xf86dri_id
)) {
653 EPHYR_LOG("host x does not support DRI. Disabling DRI forwarding\n");
657 ephyrDRIExtensionInit(pScreen
);
658 ephyrHijackGLXExtension();
666 ephyrFinishInitScreen(ScreenPtr pScreen
)
668 /* FIXME: Calling this even if not using shadow.
669 * Seems harmless enough. But may be safer elsewhere.
671 if (!shadowSetup(pScreen
))
675 if (!ephyrRandRInit(pScreen
))
683 ephyrCreateResources(ScreenPtr pScreen
)
685 KdScreenPriv(pScreen
);
686 KdScreenInfo
*screen
= pScreenPriv
->screen
;
687 EphyrScrPriv
*scrpriv
= screen
->driver
;
689 EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d",
690 pScreen
, pScreen
->myNum
, scrpriv
->shadow
);
693 return KdShadowSet(pScreen
,
695 ephyrShadowUpdate
, ephyrWindowLinear
);
697 return ephyrSetInternalDamage(pScreen
);
701 ephyrPreserve(KdCardInfo
* card
)
706 ephyrEnable(ScreenPtr pScreen
)
712 ephyrDPMS(ScreenPtr pScreen
, int mode
)
718 ephyrDisable(ScreenPtr pScreen
)
723 ephyrRestore(KdCardInfo
* card
)
728 ephyrScreenFini(KdScreenInfo
* screen
)
730 EphyrScrPriv
*scrpriv
= screen
->driver
;
732 if (scrpriv
->shadow
) {
733 KdShadowFbFree(screen
);
738 * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
739 * See https://bugs.freedesktop.org/show_bug.cgi?id=3030
742 ephyrUpdateModifierState(unsigned int state
)
745 DeviceIntPtr pDev
= inputInfo
.keyboard
;
746 KeyClassPtr keyc
= pDev
->key
;
754 xkb_state
= XkbStateFieldFromRec(&pDev
->key
->xkbInfo
->state
);
755 state
= state
& 0xff;
757 if (xkb_state
== state
)
760 for (i
= 0, mask
= 1; i
< 8; i
++, mask
<<= 1) {
763 /* Modifier is down, but shouldn't be
765 if ((xkb_state
& mask
) && !(state
& mask
)) {
766 int count
= keyc
->modifierKeyCount
[i
];
768 for (key
= 0; key
< MAP_LENGTH
; key
++)
769 if (keyc
->xkbInfo
->desc
->map
->modmap
[key
] & mask
) {
770 if (key_is_down(pDev
, key
, KEY_PROCESSED
))
771 KdEnqueueKeyboardEvent(ephyrKbd
, key
, TRUE
);
778 /* Modifier shoud be down, but isn't
780 if (!(xkb_state
& mask
) && (state
& mask
))
781 for (key
= 0; key
< MAP_LENGTH
; key
++)
782 if (keyc
->xkbInfo
->desc
->map
->modmap
[key
] & mask
) {
783 KdEnqueueKeyboardEvent(ephyrKbd
, key
, FALSE
);
790 ephyrCursorOffScreen(ScreenPtr
*ppScreen
, int *x
, int *y
)
796 ephyrCrossScreen(ScreenPtr pScreen
, Bool entering
)
800 ScreenPtr ephyrCursorScreen
; /* screen containing the cursor */
803 ephyrWarpCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, int x
, int y
)
806 ephyrCursorScreen
= pScreen
;
807 miPointerWarpCursor(inputInfo
.pointer
, pScreen
, x
, y
);
812 miPointerScreenFuncRec ephyrPointerScreenFuncs
= {
813 ephyrCursorOffScreen
,
820 * find if the remote window denoted by a_remote
821 * is paired with an internal Window within the Xephyr server.
822 * If the remove window is paired with an internal window, send an
823 * expose event to the client insterested in the internal window expose event.
825 * Pairing happens when a drawable inside Xephyr is associated with
826 * a GL surface in a DRI environment.
827 * Look at the function ProcXF86DRICreateDrawable in ephyrdriext.c to
828 * know a paired window is created.
830 * This is useful to make GL drawables (only windows for now) handle
831 * expose events and send those events to clients.
834 ephyrExposePairedWindow(int a_remote
)
836 EphyrWindowPair
*pair
= NULL
;
840 if (!findWindowPairFromRemote(a_remote
, &pair
)) {
841 EPHYR_LOG("did not find a pair for this window\n");
844 screen
= pair
->local
->drawable
.pScreen
;
846 RegionCopy(®
, &pair
->local
->clipList
);
847 screen
->WindowExposures(pair
->local
, ®
, NullRegion
);
852 static KdScreenInfo
*
853 screen_from_window(Window w
)
857 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
858 ScreenPtr pScreen
= screenInfo
.screens
[i
];
859 KdPrivScreenPtr kdscrpriv
= KdGetScreenPriv(pScreen
);
860 KdScreenInfo
*screen
= kdscrpriv
->screen
;
861 EphyrScrPriv
*scrpriv
= screen
->driver
;
863 if (scrpriv
->win
== w
864 || scrpriv
->peer_win
== w
865 || scrpriv
->win_pre_existing
== w
) {
874 ephyrProcessErrorEvent(xcb_generic_event_t
*xev
)
876 xcb_generic_error_t
*e
= (xcb_generic_error_t
*)xev
;
878 FatalError("X11 error\n"
880 "Sequence number: %hu\n"
881 "Major code: %hhu\tMinor code: %hu\n"
885 e
->major_code
, e
->minor_code
,
890 ephyrProcessExpose(xcb_generic_event_t
*xev
)
892 xcb_expose_event_t
*expose
= (xcb_expose_event_t
*)xev
;
893 KdScreenInfo
*screen
= screen_from_window(expose
->window
);
894 EphyrScrPriv
*scrpriv
= screen
->driver
;
896 /* Wait for the last expose event in a series of cliprects
897 * to actually paint our screen.
899 if (expose
->count
!= 0)
903 hostx_paint_rect(scrpriv
->screen
, 0, 0, 0, 0,
905 scrpriv
->win_height
);
907 EPHYR_LOG_ERROR("failed to get host screen\n");
910 * We only receive expose events when the expose event
911 * have be generated for a drawable that is a host X
912 * window managed by Xephyr. Host X windows managed by
913 * Xephyr exists for instance when Xephyr is asked to
914 * create a GL drawable in a DRI environment.
916 ephyrExposePairedWindow(expose
->window
);
922 ephyrProcessMouseMotion(xcb_generic_event_t
*xev
)
924 xcb_motion_notify_event_t
*motion
= (xcb_motion_notify_event_t
*)xev
;
925 KdScreenInfo
*screen
= screen_from_window(motion
->event
);
928 !((EphyrPointerPrivate
*) ephyrMouse
->driverPrivate
)->enabled
) {
929 EPHYR_LOG("skipping mouse motion:%d\n", screen
->pScreen
->myNum
);
933 if (ephyrCursorScreen
!= screen
->pScreen
) {
934 EPHYR_LOG("warping mouse cursor. "
935 "cur_screen%d, motion_screen:%d\n",
936 ephyrCursorScreen
, screen
->pScreen
->myNum
);
937 ephyrWarpCursor(inputInfo
.pointer
, screen
->pScreen
,
938 motion
->event_x
, motion
->event_y
);
944 EphyrWindowPair
*pair
= NULL
;
946 EPHYR_LOG("enqueuing mouse motion:%d\n", screen
->pScreen
->myNum
);
949 EPHYR_LOG("initial (x,y):(%d,%d)\n", x
, y
);
951 EPHYR_LOG("is this window peered by a gl drawable ?\n");
952 if (findWindowPairFromRemote(motion
->event
, &pair
)) {
953 EPHYR_LOG("yes, it is peered\n");
954 x
+= pair
->local
->drawable
.x
;
955 y
+= pair
->local
->drawable
.y
;
958 EPHYR_LOG("no, it is not peered\n");
960 EPHYR_LOG("final (x,y):(%d,%d)\n", x
, y
);
963 /* convert coords into desktop-wide coordinates.
964 * fill_pointer_events will convert that back to
965 * per-screen coordinates where needed */
966 x
+= screen
->pScreen
->x
;
967 y
+= screen
->pScreen
->y
;
969 KdEnqueuePointerEvent(ephyrMouse
, mouseState
| KD_POINTER_DESKTOP
, x
, y
, 0);
974 ephyrProcessButtonPress(xcb_generic_event_t
*xev
)
976 xcb_button_press_event_t
*button
= (xcb_button_press_event_t
*)xev
;
979 !((EphyrPointerPrivate
*) ephyrMouse
->driverPrivate
)->enabled
) {
980 EPHYR_LOG("skipping mouse press:%d\n", screen_from_window(button
->event
)->pScreen
->myNum
);
984 ephyrUpdateModifierState(button
->state
);
985 /* This is a bit hacky. will break for button 5 ( defined as 0x10 )
986 * Check KD_BUTTON defines in kdrive.h
988 mouseState
|= 1 << (button
->detail
- 1);
990 EPHYR_LOG("enqueuing mouse press:%d\n", screen_from_window(button
->event
)->pScreen
->myNum
);
991 KdEnqueuePointerEvent(ephyrMouse
, mouseState
| KD_MOUSE_DELTA
, 0, 0, 0);
995 ephyrProcessButtonRelease(xcb_generic_event_t
*xev
)
997 xcb_button_press_event_t
*button
= (xcb_button_press_event_t
*)xev
;
1000 !((EphyrPointerPrivate
*) ephyrMouse
->driverPrivate
)->enabled
) {
1004 ephyrUpdateModifierState(button
->state
);
1005 mouseState
&= ~(1 << (button
->detail
- 1));
1007 EPHYR_LOG("enqueuing mouse release:%d\n", screen_from_window(button
->event
)->pScreen
->myNum
);
1008 KdEnqueuePointerEvent(ephyrMouse
, mouseState
| KD_MOUSE_DELTA
, 0, 0, 0);
1012 ephyrProcessKeyPress(xcb_generic_event_t
*xev
)
1014 xcb_key_press_event_t
*key
= (xcb_key_press_event_t
*)xev
;
1017 !((EphyrKbdPrivate
*) ephyrKbd
->driverPrivate
)->enabled
) {
1021 ephyrUpdateModifierState(key
->state
);
1022 KdEnqueueKeyboardEvent(ephyrKbd
, key
->detail
, FALSE
);
1026 ephyrProcessKeyRelease(xcb_generic_event_t
*xev
)
1028 xcb_connection_t
*conn
= hostx_get_xcbconn();
1029 xcb_key_release_event_t
*key
= (xcb_key_release_event_t
*)xev
;
1030 static xcb_key_symbols_t
*keysyms
;
1031 static int grabbed_screen
= -1;
1034 keysyms
= xcb_key_symbols_alloc(conn
);
1036 if (((xcb_key_symbols_get_keysym(keysyms
, key
->detail
, 0) == XK_Shift_L
1037 || xcb_key_symbols_get_keysym(keysyms
, key
->detail
, 0) == XK_Shift_R
)
1038 && (key
->state
& XCB_MOD_MASK_CONTROL
)) ||
1039 ((xcb_key_symbols_get_keysym(keysyms
, key
->detail
, 0) == XK_Control_L
1040 || xcb_key_symbols_get_keysym(keysyms
, key
->detail
, 0) == XK_Control_R
)
1041 && (key
->state
& XCB_MOD_MASK_SHIFT
))) {
1042 KdScreenInfo
*screen
= screen_from_window(key
->event
);
1043 EphyrScrPriv
*scrpriv
= screen
->driver
;
1045 if (grabbed_screen
!= -1) {
1046 xcb_ungrab_keyboard(conn
, XCB_TIME_CURRENT_TIME
);
1047 xcb_ungrab_pointer(conn
, XCB_TIME_CURRENT_TIME
);
1048 grabbed_screen
= -1;
1049 hostx_set_win_title(screen
,
1050 "(ctrl+shift grabs mouse and keyboard)");
1054 xcb_grab_keyboard_cookie_t kbgrabc
=
1055 xcb_grab_keyboard(conn
,
1058 XCB_TIME_CURRENT_TIME
,
1059 XCB_GRAB_MODE_ASYNC
,
1060 XCB_GRAB_MODE_ASYNC
);
1061 xcb_grab_keyboard_reply_t
*kbgrabr
;
1062 xcb_grab_pointer_cookie_t pgrabc
=
1063 xcb_grab_pointer(conn
,
1067 XCB_GRAB_MODE_ASYNC
,
1068 XCB_GRAB_MODE_ASYNC
,
1071 XCB_TIME_CURRENT_TIME
);
1072 xcb_grab_pointer_reply_t
*pgrabr
;
1073 kbgrabr
= xcb_grab_keyboard_reply(conn
, kbgrabc
, NULL
);
1074 if (!kbgrabr
|| kbgrabr
->status
!= XCB_GRAB_STATUS_SUCCESS
) {
1075 xcb_discard_reply(conn
, pgrabc
.sequence
);
1076 xcb_ungrab_pointer(conn
, XCB_TIME_CURRENT_TIME
);
1078 pgrabr
= xcb_grab_pointer_reply(conn
, pgrabc
, NULL
);
1079 if (!pgrabr
|| pgrabr
->status
!= XCB_GRAB_STATUS_SUCCESS
)
1081 xcb_ungrab_keyboard(conn
,
1082 XCB_TIME_CURRENT_TIME
);
1084 grabbed_screen
= scrpriv
->mynum
;
1087 "(ctrl+shift releases mouse and keyboard)");
1094 !((EphyrKbdPrivate
*) ephyrKbd
->driverPrivate
)->enabled
) {
1098 /* Still send the release event even if above has happened server
1099 * will get confused with just an up event. Maybe it would be
1100 * better to just block shift+ctrls getting to kdrive all
1103 ephyrUpdateModifierState(key
->state
);
1104 KdEnqueueKeyboardEvent(ephyrKbd
, key
->detail
, TRUE
);
1108 ephyrProcessConfigureNotify(xcb_generic_event_t
*xev
)
1110 xcb_configure_notify_event_t
*configure
=
1111 (xcb_configure_notify_event_t
*)xev
;
1112 KdScreenInfo
*screen
= screen_from_window(configure
->window
);
1113 EphyrScrPriv
*scrpriv
= screen
->driver
;
1116 (scrpriv
->win_pre_existing
== None
&& !EphyrWantResize
)) {
1121 ephyrResizeScreen(screen
->pScreen
, configure
->width
, configure
->height
);
1128 xcb_connection_t
*conn
= hostx_get_xcbconn();
1131 xcb_generic_event_t
*xev
= xcb_poll_for_event(conn
);
1133 /* If our XCB connection has died (for example, our window was
1134 * closed), exit now.
1136 if (xcb_connection_has_error(conn
)) {
1137 CloseWellKnownConnections();
1145 switch (xev
->response_type
& 0x7f) {
1147 ephyrProcessErrorEvent(xev
);
1151 ephyrProcessExpose(xev
);
1154 case XCB_MOTION_NOTIFY
:
1155 ephyrProcessMouseMotion(xev
);
1159 ephyrProcessKeyPress(xev
);
1162 case XCB_KEY_RELEASE
:
1163 ephyrProcessKeyRelease(xev
);
1166 case XCB_BUTTON_PRESS
:
1167 ephyrProcessButtonPress(xev
);
1170 case XCB_BUTTON_RELEASE
:
1171 ephyrProcessButtonRelease(xev
);
1174 case XCB_CONFIGURE_NOTIFY
:
1175 ephyrProcessConfigureNotify(xev
);
1184 ephyrCardFini(KdCardInfo
* card
)
1186 EphyrPriv
*priv
= card
->driver
;
1192 ephyrGetColors(ScreenPtr pScreen
, int n
, xColorItem
* pdefs
)
1194 /* XXX Not sure if this is right */
1208 ephyrPutColors(ScreenPtr pScreen
, int n
, xColorItem
* pdefs
)
1212 /* XXX Not sure if this is right */
1224 hostx_set_cmap_entry(p
,
1226 pdefs
->green
>> 8, pdefs
->blue
>> 8);
1234 MouseInit(KdPointerInfo
* pi
)
1236 pi
->driverPrivate
= (EphyrPointerPrivate
*)
1237 calloc(sizeof(EphyrPointerPrivate
), 1);
1238 ((EphyrPointerPrivate
*) pi
->driverPrivate
)->enabled
= FALSE
;
1242 pi
->name
= strdup("Xephyr virtual mouse");
1245 * Must transform pointer coords since the pointer position
1246 * relative to the Xephyr window is controlled by the host server and
1247 * remains constant regardless of any rotation applied to the Xephyr screen.
1249 pi
->transformCoordinates
= TRUE
;
1256 MouseEnable(KdPointerInfo
* pi
)
1258 ((EphyrPointerPrivate
*) pi
->driverPrivate
)->enabled
= TRUE
;
1263 MouseDisable(KdPointerInfo
* pi
)
1265 ((EphyrPointerPrivate
*) pi
->driverPrivate
)->enabled
= FALSE
;
1270 MouseFini(KdPointerInfo
* pi
)
1276 KdPointerDriver EphyrMouseDriver
= {
1288 EphyrKeyboardInit(KdKeyboardInfo
* ki
)
1290 ki
->driverPrivate
= (EphyrKbdPrivate
*)
1291 calloc(sizeof(EphyrKbdPrivate
), 1);
1292 hostx_load_keymap();
1293 if (!ephyrKeySyms
.minKeyCode
) {
1294 ErrorF("Couldn't load keymap from host\n");
1297 ki
->minScanCode
= ephyrKeySyms
.minKeyCode
;
1298 ki
->maxScanCode
= ephyrKeySyms
.maxKeyCode
;
1300 ki
->name
= strdup("Xephyr virtual keyboard");
1306 EphyrKeyboardEnable(KdKeyboardInfo
* ki
)
1308 ((EphyrKbdPrivate
*) ki
->driverPrivate
)->enabled
= TRUE
;
1314 EphyrKeyboardDisable(KdKeyboardInfo
* ki
)
1316 ((EphyrKbdPrivate
*) ki
->driverPrivate
)->enabled
= FALSE
;
1320 EphyrKeyboardFini(KdKeyboardInfo
* ki
)
1327 EphyrKeyboardLeds(KdKeyboardInfo
* ki
, int leds
)
1332 EphyrKeyboardBell(KdKeyboardInfo
* ki
, int volume
, int frequency
, int duration
)
1336 KdKeyboardDriver EphyrKeyboardDriver
= {
1339 EphyrKeyboardEnable
,
1342 EphyrKeyboardDisable
,