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.
28 * o Support multiple screens, shouldn't be hard just alot of rejigging.
32 #include <kdrive-config.h>
38 extern int KdTsPhyScreen
;
39 KdKeyboardInfo
*ephyrKbd
;
40 KdPointerInfo
*ephyrMouse
;
41 EphyrKeySyms ephyrKeySyms
;
43 static int mouseState
= 0;
45 typedef struct _EphyrInputPrivate
{
47 } EphyrKbdPrivate
, EphyrPointerPrivate
;
49 Bool EphyrWantGrayScale
= 0;
52 ephyrInitialize (KdCardInfo
*card
, EphyrPriv
*priv
)
54 OsSignal(SIGUSR1
, hostx_handle_signal
);
57 priv
->bytes_per_line
= 0;
62 ephyrCardInit (KdCardInfo
*card
)
66 priv
= (EphyrPriv
*) xalloc (sizeof (EphyrPriv
));
70 if (!ephyrInitialize (card
, priv
))
81 ephyrScreenInitialize (KdScreenInfo
*screen
, EphyrScrPriv
*scrpriv
)
83 int width
= 640, height
= 480;
84 unsigned long redMask
, greenMask
, blueMask
;
86 if (hostx_want_screen_size(&width
, &height
)
87 || !screen
->width
|| !screen
->height
)
89 screen
->width
= width
;
90 screen
->height
= height
;
93 if (EphyrWantGrayScale
)
94 screen
->fb
[0].depth
= 8;
96 if (screen
->fb
[0].depth
&& screen
->fb
[0].depth
!= hostx_get_depth())
98 if (screen
->fb
[0].depth
< hostx_get_depth()
99 && (screen
->fb
[0].depth
== 24 || screen
->fb
[0].depth
== 16
100 || screen
->fb
[0].depth
== 8))
102 hostx_set_server_depth(screen
->fb
[0].depth
);
105 ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
108 screen
->fb
[0].depth
= hostx_get_server_depth();
111 if (screen
->fb
[0].depth
<= 8)
113 if (EphyrWantGrayScale
)
114 screen
->fb
[0].visuals
= ((1 << StaticGray
) | (1 << GrayScale
));
116 screen
->fb
[0].visuals
= ((1 << StaticGray
) |
123 screen
->fb
[0].redMask
= 0x00;
124 screen
->fb
[0].greenMask
= 0x00;
125 screen
->fb
[0].blueMask
= 0x00;
126 screen
->fb
[0].depth
= 8;
127 screen
->fb
[0].bitsPerPixel
= 8;
131 screen
->fb
[0].visuals
= (1 << TrueColor
);
133 if (screen
->fb
[0].depth
<= 15)
135 screen
->fb
[0].depth
= 15;
136 screen
->fb
[0].bitsPerPixel
= 16;
138 else if (screen
->fb
[0].depth
<= 16)
140 screen
->fb
[0].depth
= 16;
141 screen
->fb
[0].bitsPerPixel
= 16;
145 screen
->fb
[0].depth
= 24;
146 screen
->fb
[0].bitsPerPixel
= 32;
149 hostx_get_visual_masks (&redMask
, &greenMask
, &blueMask
);
151 screen
->fb
[0].redMask
= (Pixel
) redMask
;
152 screen
->fb
[0].greenMask
= (Pixel
) greenMask
;
153 screen
->fb
[0].blueMask
= (Pixel
) blueMask
;
157 scrpriv
->randr
= screen
->randr
;
159 return ephyrMapFramebuffer (screen
);
163 ephyrScreenInit (KdScreenInfo
*screen
)
165 EphyrScrPriv
*scrpriv
;
167 scrpriv
= xalloc (sizeof (EphyrScrPriv
));
172 memset (scrpriv
, 0, sizeof (EphyrScrPriv
));
173 screen
->driver
= scrpriv
;
175 if (!ephyrScreenInitialize (screen
, scrpriv
))
186 ephyrWindowLinear (ScreenPtr pScreen
,
193 KdScreenPriv(pScreen
);
194 EphyrPriv
*priv
= pScreenPriv
->card
->driver
;
196 if (!pScreenPriv
->enabled
)
201 *size
= priv
->bytes_per_line
;
202 return priv
->base
+ row
* priv
->bytes_per_line
+ offset
;
206 ephyrMapFramebuffer (KdScreenInfo
*screen
)
208 EphyrScrPriv
*scrpriv
= screen
->driver
;
209 EphyrPriv
*priv
= screen
->card
->driver
;
213 EPHYR_DBG(" screen->width: %d, screen->height: %d",
214 screen
->width
, screen
->height
);
216 KdComputePointerMatrix (&m
, scrpriv
->randr
, screen
->width
, screen
->height
);
217 KdSetPointerMatrix (&m
);
219 priv
->bytes_per_line
= ((screen
->width
* screen
->fb
[0].bitsPerPixel
+ 31) >> 5) << 2;
221 /* point the framebuffer to the data in an XImage */
222 /* If fakexa is enabled, allocate a larger buffer so that fakexa has space to
223 * put offscreen pixmaps.
225 if (ephyrFuncs
.initAccel
== NULL
)
226 buffer_height
= screen
->height
;
228 buffer_height
= 3 * screen
->height
;
230 priv
->base
= hostx_screen_init (screen
->width
, screen
->height
, buffer_height
);
232 screen
->memory_base
= (CARD8
*) (priv
->base
);
233 screen
->memory_size
= priv
->bytes_per_line
* buffer_height
;
234 screen
->off_screen_base
= priv
->bytes_per_line
* screen
->height
;
236 if ((scrpriv
->randr
& RR_Rotate_0
) && !(scrpriv
->randr
& RR_Reflect_All
))
238 scrpriv
->shadow
= FALSE
;
240 screen
->fb
[0].byteStride
= priv
->bytes_per_line
;
241 screen
->fb
[0].pixelStride
= screen
->width
;
242 screen
->fb
[0].frameBuffer
= (CARD8
*) (priv
->base
);
246 /* Rotated/Reflected so we need to use shadow fb */
247 scrpriv
->shadow
= TRUE
;
249 EPHYR_DBG("allocing shadow");
251 KdShadowFbAlloc (screen
, 0,
252 scrpriv
->randr
& (RR_Rotate_90
|RR_Rotate_270
));
259 ephyrSetScreenSizes (ScreenPtr pScreen
)
261 KdScreenPriv(pScreen
);
262 KdScreenInfo
*screen
= pScreenPriv
->screen
;
263 EphyrScrPriv
*scrpriv
= screen
->driver
;
265 if (scrpriv
->randr
& (RR_Rotate_0
|RR_Rotate_180
))
267 pScreen
->width
= screen
->width
;
268 pScreen
->height
= screen
->height
;
269 pScreen
->mmWidth
= screen
->width_mm
;
270 pScreen
->mmHeight
= screen
->height_mm
;
274 pScreen
->width
= screen
->height
;
275 pScreen
->height
= screen
->width
;
276 pScreen
->mmWidth
= screen
->height_mm
;
277 pScreen
->mmHeight
= screen
->width_mm
;
282 ephyrUnmapFramebuffer (KdScreenInfo
*screen
)
284 EphyrScrPriv
*scrpriv
= screen
->driver
;
287 KdShadowFbFree (screen
, 0);
289 /* Note, priv->base will get freed when XImage recreated */
295 ephyrShadowUpdate (ScreenPtr pScreen
, shadowBufPtr pBuf
)
297 KdScreenPriv(pScreen
);
298 KdScreenInfo
*screen
= pScreenPriv
->screen
;
300 EPHYR_DBG("slow paint");
302 /* FIXME: Slow Rotated/Reflected updates could be much
303 * much faster efficiently updating via tranforming
304 * pBuf->pDamage regions
306 shadowUpdateRotatePacked(pScreen
, pBuf
);
307 hostx_paint_rect(0,0,0,0, screen
->width
, screen
->height
);
311 ephyrInternalDamageRedisplay (ScreenPtr pScreen
)
313 KdScreenPriv(pScreen
);
314 KdScreenInfo
*screen
= pScreenPriv
->screen
;
315 EphyrScrPriv
*scrpriv
= screen
->driver
;
318 if (!scrpriv
|| !scrpriv
->pDamage
)
321 pRegion
= DamageRegion (scrpriv
->pDamage
);
323 if (REGION_NOTEMPTY (pScreen
, pRegion
))
328 nbox
= REGION_NUM_RECTS (pRegion
);
329 pbox
= REGION_RECTS (pRegion
);
333 hostx_paint_rect(pbox
->x1
, pbox
->y1
,
336 pbox
->y2
- pbox
->y1
);
340 DamageEmpty (scrpriv
->pDamage
);
345 ephyrInternalDamageBlockHandler (pointer data
,
349 ScreenPtr pScreen
= (ScreenPtr
) data
;
351 ephyrInternalDamageRedisplay (pScreen
);
355 ephyrInternalDamageWakeupHandler (pointer data
, int i
, pointer LastSelectMask
)
357 /* FIXME: Not needed ? */
361 ephyrSetInternalDamage (ScreenPtr pScreen
)
363 KdScreenPriv(pScreen
);
364 KdScreenInfo
*screen
= pScreenPriv
->screen
;
365 EphyrScrPriv
*scrpriv
= screen
->driver
;
366 PixmapPtr pPixmap
= NULL
;
368 scrpriv
->pDamage
= DamageCreate ((DamageReportFunc
) 0,
369 (DamageDestroyFunc
) 0,
375 if (!RegisterBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler
,
376 ephyrInternalDamageWakeupHandler
,
380 pPixmap
= (*pScreen
->GetScreenPixmap
) (pScreen
);
382 DamageRegister (&pPixmap
->drawable
, scrpriv
->pDamage
);
388 ephyrUnsetInternalDamage (ScreenPtr pScreen
)
390 KdScreenPriv(pScreen
);
391 KdScreenInfo
*screen
= pScreenPriv
->screen
;
392 EphyrScrPriv
*scrpriv
= screen
->driver
;
393 PixmapPtr pPixmap
= NULL
;
395 pPixmap
= (*pScreen
->GetScreenPixmap
) (pScreen
);
396 DamageUnregister (&pPixmap
->drawable
, scrpriv
->pDamage
);
398 RemoveBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler
,
399 ephyrInternalDamageWakeupHandler
,
405 ephyrRandRGetInfo (ScreenPtr pScreen
, Rotation
*rotations
)
407 KdScreenPriv(pScreen
);
408 KdScreenInfo
*screen
= pScreenPriv
->screen
;
409 EphyrScrPriv
*scrpriv
= screen
->driver
;
410 RRScreenSizePtr pSize
;
416 struct { int width
, height
; } sizes
[] =
436 *rotations
= RR_Rotate_All
|RR_Reflect_All
;
438 if (!hostx_want_preexisting_window()
439 && !hostx_want_fullscreen()) /* only if no -parent switch */
441 while (sizes
[n
].width
!= 0 && sizes
[n
].height
!= 0)
443 RRRegisterSize (pScreen
,
446 (sizes
[n
].width
* screen
->width_mm
)/screen
->width
,
447 (sizes
[n
].height
*screen
->height_mm
)/screen
->height
453 pSize
= RRRegisterSize (pScreen
,
459 randr
= KdSubRotation (scrpriv
->randr
, screen
->randr
);
461 RRSetCurrentConfig (pScreen
, randr
, 0, pSize
);
467 ephyrRandRSetConfig (ScreenPtr pScreen
,
470 RRScreenSizePtr pSize
)
472 KdScreenPriv(pScreen
);
473 KdScreenInfo
*screen
= pScreenPriv
->screen
;
474 EphyrScrPriv
*scrpriv
= screen
->driver
;
475 Bool wasEnabled
= pScreenPriv
->enabled
;
477 int oldwidth
, oldheight
, oldmmwidth
, oldmmheight
;
479 int newwidth
, newheight
;
481 if (screen
->randr
& (RR_Rotate_0
|RR_Rotate_180
))
483 newwidth
= pSize
->width
;
484 newheight
= pSize
->height
;
488 newwidth
= pSize
->height
;
489 newheight
= pSize
->width
;
493 KdDisableScreen (pScreen
);
497 oldwidth
= screen
->width
;
498 oldheight
= screen
->height
;
499 oldmmwidth
= pScreen
->mmWidth
;
500 oldmmheight
= pScreen
->mmHeight
;
501 oldshadow
= scrpriv
->shadow
;
504 * Set new configuration
507 scrpriv
->randr
= KdAddRotation (screen
->randr
, randr
);
509 KdOffscreenSwapOut (screen
->pScreen
);
511 ephyrUnmapFramebuffer (screen
);
513 screen
->width
= newwidth
;
514 screen
->height
= newheight
;
516 if (!ephyrMapFramebuffer (screen
))
519 /* FIXME below should go in own call */
522 KdShadowUnset (screen
->pScreen
);
524 ephyrUnsetInternalDamage(screen
->pScreen
);
528 if (!KdShadowSet (screen
->pScreen
,
536 /* Without shadow fb ( non rotated ) we need
537 * to use damage to efficiently update display
538 * via signal regions what to copy from 'fb'.
540 if (!ephyrSetInternalDamage(screen
->pScreen
))
544 ephyrSetScreenSizes (screen
->pScreen
);
547 * Set frame buffer mapping
549 (*pScreen
->ModifyPixmapHeader
) (fbGetScreenPixmap (pScreen
),
553 screen
->fb
[0].bitsPerPixel
,
554 screen
->fb
[0].byteStride
,
555 screen
->fb
[0].frameBuffer
);
557 /* set the subpixel order */
559 KdSetSubpixelOrder (pScreen
, scrpriv
->randr
);
562 KdEnableScreen (pScreen
);
569 ephyrUnmapFramebuffer (screen
);
571 (void) ephyrMapFramebuffer (screen
);
573 pScreen
->width
= oldwidth
;
574 pScreen
->height
= oldheight
;
575 pScreen
->mmWidth
= oldmmwidth
;
576 pScreen
->mmHeight
= oldmmheight
;
579 KdEnableScreen (pScreen
);
584 ephyrRandRInit (ScreenPtr pScreen
)
586 rrScrPrivPtr pScrPriv
;
588 if (!RRScreenInit (pScreen
))
593 pScrPriv
= rrGetScrPriv(pScreen
);
594 pScrPriv
->rrGetInfo
= ephyrRandRGetInfo
;
595 pScrPriv
->rrSetConfig
= ephyrRandRSetConfig
;
601 ephyrCreateColormap (ColormapPtr pmap
)
603 return fbInitializeColormap (pmap
);
607 ephyrInitScreen (ScreenPtr pScreen
)
609 pScreen
->CreateColormap
= ephyrCreateColormap
;
614 ephyrFinishInitScreen (ScreenPtr pScreen
)
616 /* FIXME: Calling this even if not using shadow.
617 * Seems harmless enough. But may be safer elsewhere.
619 if (!shadowSetup (pScreen
))
623 if (!ephyrRandRInit (pScreen
))
631 ephyrCreateResources (ScreenPtr pScreen
)
633 KdScreenPriv(pScreen
);
634 KdScreenInfo
*screen
= pScreenPriv
->screen
;
635 EphyrScrPriv
*scrpriv
= screen
->driver
;
640 return KdShadowSet (pScreen
,
645 return ephyrSetInternalDamage(pScreen
);
649 ephyrPreserve (KdCardInfo
*card
)
654 ephyrEnable (ScreenPtr pScreen
)
660 ephyrDPMS (ScreenPtr pScreen
, int mode
)
666 ephyrDisable (ScreenPtr pScreen
)
671 ephyrRestore (KdCardInfo
*card
)
676 ephyrScreenFini (KdScreenInfo
*screen
)
678 xfree(screen
->driver
);
679 screen
->driver
= NULL
;
683 * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
684 * See https://bugs.freedesktop.org/show_bug.cgi?id=3030
687 ephyrUpdateModifierState(unsigned int state
)
689 DeviceIntPtr pkeydev
;
694 pkeydev
= (DeviceIntPtr
)LookupKeyboardDevice();
701 state
= state
& 0xff;
703 if (keyc
->state
== state
)
706 for (i
= 0, mask
= 1; i
< 8; i
++, mask
<<= 1)
710 /* Modifier is down, but shouldn't be */
711 if ((keyc
->state
& mask
) && !(state
& mask
))
713 int count
= keyc
->modifierKeyCount
[i
];
715 for (key
= 0; key
< MAP_LENGTH
; key
++)
716 if (keyc
->modifierMap
[key
] & mask
)
721 kptr
= &keyc
->down
[key
>> 3];
722 bit
= 1 << (key
& 7);
724 if (*kptr
& bit
&& ephyrKbd
&&
725 ((EphyrKbdPrivate
*)ephyrKbd
->driverPrivate
)->enabled
)
726 KdEnqueueKeyboardEvent(ephyrKbd
, key
, TRUE
); /* release */
733 /* Modifier shoud be down, but isn't */
734 if (!(keyc
->state
& mask
) && (state
& mask
))
735 for (key
= 0; key
< MAP_LENGTH
; key
++)
736 if (keyc
->modifierMap
[key
] & mask
)
738 if (keyc
->modifierMap
[key
] & mask
&& ephyrKbd
&&
739 ((EphyrKbdPrivate
*)ephyrKbd
->driverPrivate
)->enabled
)
740 KdEnqueueKeyboardEvent(ephyrKbd
, key
, FALSE
); /* press */
751 while (hostx_get_event(&ev
))
755 case EPHYR_EV_MOUSE_MOTION
:
757 !((EphyrPointerPrivate
*)ephyrMouse
->driverPrivate
)->enabled
)
759 KdEnqueuePointerEvent(ephyrMouse
, mouseState
,
760 ev
.data
.mouse_motion
.x
,
761 ev
.data
.mouse_motion
.y
,
765 case EPHYR_EV_MOUSE_PRESS
:
767 !((EphyrPointerPrivate
*)ephyrMouse
->driverPrivate
)->enabled
)
769 ephyrUpdateModifierState(ev
.key_state
);
770 mouseState
|= ev
.data
.mouse_down
.button_num
;
771 KdEnqueuePointerEvent(ephyrMouse
, mouseState
|KD_MOUSE_DELTA
, 0, 0, 0);
774 case EPHYR_EV_MOUSE_RELEASE
:
776 !((EphyrPointerPrivate
*)ephyrMouse
->driverPrivate
)->enabled
)
778 ephyrUpdateModifierState(ev
.key_state
);
779 mouseState
&= ~ev
.data
.mouse_up
.button_num
;
780 KdEnqueuePointerEvent(ephyrMouse
, mouseState
|KD_MOUSE_DELTA
, 0, 0, 0);
783 case EPHYR_EV_KEY_PRESS
:
785 !((EphyrKbdPrivate
*)ephyrKbd
->driverPrivate
)->enabled
)
787 ephyrUpdateModifierState(ev
.key_state
);
788 KdEnqueueKeyboardEvent (ephyrKbd
, ev
.data
.key_down
.scancode
, FALSE
);
791 case EPHYR_EV_KEY_RELEASE
:
793 !((EphyrKbdPrivate
*)ephyrKbd
->driverPrivate
)->enabled
)
795 ephyrUpdateModifierState(ev
.key_state
);
796 KdEnqueueKeyboardEvent (ephyrKbd
, ev
.data
.key_up
.scancode
, TRUE
);
806 ephyrCardFini (KdCardInfo
*card
)
808 EphyrPriv
*priv
= card
->driver
;
813 ephyrGetColors (ScreenPtr pScreen
, int fb
, int n
, xColorItem
*pdefs
)
815 /* XXX Not sure if this is right */
830 ephyrPutColors (ScreenPtr pScreen
, int fb
, int n
, xColorItem
*pdefs
)
834 /* XXX Not sure if this is right */
847 hostx_set_cmap_entry(p
,
858 MouseInit (KdPointerInfo
*pi
)
860 pi
->driverPrivate
= (EphyrPointerPrivate
*)
861 xcalloc(sizeof(EphyrPointerPrivate
), 1);
862 ((EphyrPointerPrivate
*)pi
->driverPrivate
)->enabled
= FALSE
;
865 pi
->name
= KdSaveString("Xephyr virtual mouse");
871 MouseEnable (KdPointerInfo
*pi
)
873 ((EphyrPointerPrivate
*)pi
->driverPrivate
)->enabled
= TRUE
;
878 MouseDisable (KdPointerInfo
*pi
)
880 ((EphyrPointerPrivate
*)pi
->driverPrivate
)->enabled
= FALSE
;
885 MouseFini (KdPointerInfo
*pi
)
891 KdPointerDriver EphyrMouseDriver
= {
903 EphyrKeyboardInit (KdKeyboardInfo
*ki
)
905 ki
->driverPrivate
= (EphyrKbdPrivate
*)
906 xcalloc(sizeof(EphyrKbdPrivate
), 1);
908 if (!ephyrKeySyms
.map
) {
909 ErrorF("Couldn't load keymap from host\n");
912 ki
->keySyms
.minKeyCode
= ephyrKeySyms
.minKeyCode
;
913 ki
->keySyms
.maxKeyCode
= ephyrKeySyms
.maxKeyCode
;
914 ki
->minScanCode
= ki
->keySyms
.minKeyCode
;
915 ki
->maxScanCode
= ki
->keySyms
.maxKeyCode
;
916 ki
->keySyms
.mapWidth
= ephyrKeySyms
.mapWidth
;
917 ki
->keySyms
.map
= ephyrKeySyms
.map
;
918 ki
->name
= KdSaveString("Xephyr virtual keyboard");
924 EphyrKeyboardEnable (KdKeyboardInfo
*ki
)
926 ((EphyrKbdPrivate
*)ki
->driverPrivate
)->enabled
= TRUE
;
932 EphyrKeyboardDisable (KdKeyboardInfo
*ki
)
934 ((EphyrKbdPrivate
*)ki
->driverPrivate
)->enabled
= FALSE
;
938 EphyrKeyboardFini (KdKeyboardInfo
*ki
)
940 /* not xfree: we call malloc from hostx.c. */
941 free(ki
->keySyms
.map
);
947 EphyrKeyboardLeds (KdKeyboardInfo
*ki
, int leds
)
952 EphyrKeyboardBell (KdKeyboardInfo
*ki
, int volume
, int frequency
, int duration
)
956 KdKeyboardDriver EphyrKeyboardDriver
= {
962 EphyrKeyboardDisable
,