d695579848
same width/height for front-buffer drawing. The fakexa code then uses this extra space for offscreen pixmaps. Note that this tones down the absurdity of fakexa's offscreen pixmap alignment requirements (odd alignment is too weird, so stick with "24", which is still strange but exists out there). It also fixes a couple of bugs in the fakexa implementation revealed by using offscreen pixmaps.
884 lines
18 KiB
C
884 lines
18 KiB
C
/*
|
|
* Xephyr - A kdrive X server thats runs in a host X window.
|
|
* Authored by Matthew Allum <mallum@openedhand.com>
|
|
*
|
|
* Copyright © 2004 Nokia
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Nokia not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Nokia makes no
|
|
* representations about the suitability of this software for any purpose. It
|
|
* is provided "as is" without express or implied warranty.
|
|
*
|
|
* NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
/* TODO:
|
|
*
|
|
* o Support multiple screens, shouldn't be hard just alot of rejigging.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <kdrive-config.h>
|
|
#endif
|
|
#include "ephyr.h"
|
|
|
|
#include "inputstr.h"
|
|
|
|
extern int KdTsPhyScreen;
|
|
extern DeviceIntPtr pKdKeyboard;
|
|
|
|
static int mouseState = 0;
|
|
|
|
Bool
|
|
ephyrInitialize (KdCardInfo *card, EphyrPriv *priv)
|
|
{
|
|
OsSignal(SIGUSR1, hostx_handle_signal);
|
|
|
|
priv->base = 0;
|
|
priv->bytes_per_line = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ephyrCardInit (KdCardInfo *card)
|
|
{
|
|
EphyrPriv *priv;
|
|
|
|
priv = (EphyrPriv *) xalloc (sizeof (EphyrPriv));
|
|
if (!priv)
|
|
return FALSE;
|
|
|
|
if (!ephyrInitialize (card, priv))
|
|
{
|
|
xfree (priv);
|
|
return FALSE;
|
|
}
|
|
card->driver = priv;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv)
|
|
{
|
|
int width = 640, height = 480;
|
|
|
|
if (hostx_want_screen_size(&width, &height)
|
|
|| !screen->width || !screen->height)
|
|
{
|
|
screen->width = width;
|
|
screen->height = height;
|
|
}
|
|
|
|
if (screen->fb[0].depth && screen->fb[0].depth != hostx_get_depth())
|
|
{
|
|
if (screen->fb[0].depth < hostx_get_depth()
|
|
&& (screen->fb[0].depth == 24 || screen->fb[0].depth == 16
|
|
|| screen->fb[0].depth == 8))
|
|
{
|
|
hostx_set_server_depth(screen->fb[0].depth);
|
|
}
|
|
else
|
|
ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n");
|
|
}
|
|
|
|
screen->fb[0].depth = hostx_get_server_depth();
|
|
screen->rate = 72;
|
|
|
|
if (screen->fb[0].depth <= 8)
|
|
{
|
|
screen->fb[0].visuals = ((1 << StaticGray) |
|
|
(1 << GrayScale) |
|
|
(1 << StaticColor) |
|
|
(1 << PseudoColor) |
|
|
(1 << TrueColor) |
|
|
(1 << DirectColor));
|
|
|
|
screen->fb[0].redMask = 0x00;
|
|
screen->fb[0].greenMask = 0x00;
|
|
screen->fb[0].blueMask = 0x00;
|
|
screen->fb[0].depth = 8;
|
|
screen->fb[0].bitsPerPixel = 8;
|
|
}
|
|
else
|
|
{
|
|
screen->fb[0].visuals = (1 << TrueColor);
|
|
|
|
if (screen->fb[0].depth <= 15)
|
|
{
|
|
screen->fb[0].depth = 15;
|
|
screen->fb[0].bitsPerPixel = 16;
|
|
|
|
hostx_get_visual_masks (&screen->fb[0].redMask,
|
|
&screen->fb[0].greenMask,
|
|
&screen->fb[0].blueMask);
|
|
|
|
}
|
|
else if (screen->fb[0].depth <= 16)
|
|
{
|
|
screen->fb[0].depth = 16;
|
|
screen->fb[0].bitsPerPixel = 16;
|
|
|
|
hostx_get_visual_masks (&screen->fb[0].redMask,
|
|
&screen->fb[0].greenMask,
|
|
&screen->fb[0].blueMask);
|
|
}
|
|
else
|
|
{
|
|
screen->fb[0].depth = 24;
|
|
screen->fb[0].bitsPerPixel = 32;
|
|
|
|
hostx_get_visual_masks (&screen->fb[0].redMask,
|
|
&screen->fb[0].greenMask,
|
|
&screen->fb[0].blueMask);
|
|
}
|
|
}
|
|
|
|
scrpriv->randr = screen->randr;
|
|
|
|
return ephyrMapFramebuffer (screen);
|
|
}
|
|
|
|
Bool
|
|
ephyrScreenInit (KdScreenInfo *screen)
|
|
{
|
|
EphyrScrPriv *scrpriv;
|
|
|
|
scrpriv = xalloc (sizeof (EphyrScrPriv));
|
|
|
|
if (!scrpriv)
|
|
return FALSE;
|
|
|
|
memset (scrpriv, 0, sizeof (EphyrScrPriv));
|
|
screen->driver = scrpriv;
|
|
|
|
if (!ephyrScreenInitialize (screen, scrpriv))
|
|
{
|
|
screen->driver = 0;
|
|
xfree (scrpriv);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void*
|
|
ephyrWindowLinear (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size,
|
|
void *closure)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
EphyrPriv *priv = pScreenPriv->card->driver;
|
|
|
|
if (!pScreenPriv->enabled)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
*size = priv->bytes_per_line;
|
|
return priv->base + row * priv->bytes_per_line + offset;
|
|
}
|
|
|
|
Bool
|
|
ephyrMapFramebuffer (KdScreenInfo *screen)
|
|
{
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
EphyrPriv *priv = screen->card->driver;
|
|
KdMouseMatrix m;
|
|
int buffer_height;
|
|
|
|
EPHYR_DBG(" screen->width: %d, screen->height: %d",
|
|
screen->width, screen->height);
|
|
|
|
KdComputeMouseMatrix (&m, scrpriv->randr, screen->width, screen->height);
|
|
|
|
KdSetMouseMatrix (&m);
|
|
|
|
priv->bytes_per_line = ((screen->width * screen->fb[0].bitsPerPixel + 31) >> 5) << 2;
|
|
|
|
/* point the framebuffer to the data in an XImage */
|
|
/* If fakexa is enabled, allocate a larger buffer so that fakexa has space to
|
|
* put offscreen pixmaps.
|
|
*/
|
|
if (ephyrFuncs.initAccel == NULL)
|
|
buffer_height = screen->height;
|
|
else
|
|
buffer_height = 3 * screen->height;
|
|
|
|
priv->base = hostx_screen_init (screen->width, screen->height, buffer_height);
|
|
|
|
screen->memory_base = (CARD8 *) (priv->base);
|
|
screen->memory_size = priv->bytes_per_line * buffer_height;
|
|
screen->off_screen_base = priv->bytes_per_line * screen->height;
|
|
|
|
if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All))
|
|
{
|
|
scrpriv->shadow = FALSE;
|
|
|
|
screen->fb[0].byteStride = priv->bytes_per_line;
|
|
screen->fb[0].pixelStride = screen->width;
|
|
screen->fb[0].frameBuffer = (CARD8 *) (priv->base);
|
|
}
|
|
else
|
|
{
|
|
/* Rotated/Reflected so we need to use shadow fb */
|
|
scrpriv->shadow = TRUE;
|
|
|
|
EPHYR_DBG("allocing shadow");
|
|
|
|
KdShadowFbAlloc (screen, 0,
|
|
scrpriv->randr & (RR_Rotate_90|RR_Rotate_270));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
ephyrSetScreenSizes (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
|
|
if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180))
|
|
{
|
|
pScreen->width = screen->width;
|
|
pScreen->height = screen->height;
|
|
pScreen->mmWidth = screen->width_mm;
|
|
pScreen->mmHeight = screen->height_mm;
|
|
}
|
|
else
|
|
{
|
|
pScreen->width = screen->height;
|
|
pScreen->height = screen->width;
|
|
pScreen->mmWidth = screen->height_mm;
|
|
pScreen->mmHeight = screen->width_mm;
|
|
}
|
|
}
|
|
|
|
Bool
|
|
ephyrUnmapFramebuffer (KdScreenInfo *screen)
|
|
{
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
|
|
if (scrpriv->shadow)
|
|
KdShadowFbFree (screen, 0);
|
|
|
|
/* Note, priv->base will get freed when XImage recreated */
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
|
|
EPHYR_DBG("slow paint");
|
|
|
|
/* FIXME: Slow Rotated/Reflected updates could be much
|
|
* much faster efficiently updating via tranforming
|
|
* pBuf->pDamage regions
|
|
*/
|
|
shadowUpdateRotatePacked(pScreen, pBuf);
|
|
hostx_paint_rect(0,0,0,0, screen->width, screen->height);
|
|
}
|
|
|
|
static void
|
|
ephyrInternalDamageRedisplay (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
RegionPtr pRegion;
|
|
|
|
if (!scrpriv || !scrpriv->pDamage)
|
|
return;
|
|
|
|
pRegion = DamageRegion (scrpriv->pDamage);
|
|
|
|
if (REGION_NOTEMPTY (pScreen, pRegion))
|
|
{
|
|
int nbox;
|
|
BoxPtr pbox;
|
|
|
|
nbox = REGION_NUM_RECTS (pRegion);
|
|
pbox = REGION_RECTS (pRegion);
|
|
|
|
while (nbox--)
|
|
{
|
|
hostx_paint_rect(pbox->x1, pbox->y1,
|
|
pbox->x1, pbox->y1,
|
|
pbox->x2 - pbox->x1,
|
|
pbox->y2 - pbox->y1);
|
|
pbox++;
|
|
}
|
|
|
|
DamageEmpty (scrpriv->pDamage);
|
|
}
|
|
}
|
|
|
|
static void
|
|
ephyrInternalDamageBlockHandler (pointer data,
|
|
OSTimePtr pTimeout,
|
|
pointer pRead)
|
|
{
|
|
ScreenPtr pScreen = (ScreenPtr) data;
|
|
|
|
ephyrInternalDamageRedisplay (pScreen);
|
|
}
|
|
|
|
static void
|
|
ephyrInternalDamageWakeupHandler (pointer data, int i, pointer LastSelectMask)
|
|
{
|
|
/* FIXME: Not needed ? */
|
|
}
|
|
|
|
Bool
|
|
ephyrSetInternalDamage (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
PixmapPtr pPixmap = NULL;
|
|
|
|
scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0,
|
|
(DamageDestroyFunc) 0,
|
|
DamageReportNone,
|
|
TRUE,
|
|
pScreen,
|
|
pScreen);
|
|
|
|
if (!RegisterBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler,
|
|
ephyrInternalDamageWakeupHandler,
|
|
(pointer) pScreen))
|
|
return FALSE;
|
|
|
|
pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
|
|
|
|
DamageRegister (&pPixmap->drawable, scrpriv->pDamage);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
ephyrUnsetInternalDamage (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
PixmapPtr pPixmap = NULL;
|
|
|
|
pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
|
|
DamageUnregister (&pPixmap->drawable, scrpriv->pDamage);
|
|
|
|
RemoveBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler,
|
|
ephyrInternalDamageWakeupHandler,
|
|
(pointer) pScreen);
|
|
}
|
|
|
|
#ifdef RANDR
|
|
Bool
|
|
ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
RRScreenSizePtr pSize;
|
|
Rotation randr;
|
|
int n = 0;
|
|
|
|
EPHYR_DBG("mark");
|
|
|
|
struct { int width, height; } sizes[] =
|
|
{
|
|
{ 1600, 1200 },
|
|
{ 1400, 1050 },
|
|
{ 1280, 960 },
|
|
{ 1280, 1024 },
|
|
{ 1152, 864 },
|
|
{ 1024, 768 },
|
|
{ 832, 624 },
|
|
{ 800, 600 },
|
|
{ 720, 400 },
|
|
{ 480, 640 },
|
|
{ 640, 480 },
|
|
{ 640, 400 },
|
|
{ 320, 240 },
|
|
{ 240, 320 },
|
|
{ 160, 160 },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
*rotations = RR_Rotate_All|RR_Reflect_All;
|
|
|
|
if (!hostx_want_preexisting_window()
|
|
&& !hostx_want_fullscreen()) /* only if no -parent switch */
|
|
{
|
|
while (sizes[n].width != 0 && sizes[n].height != 0)
|
|
{
|
|
RRRegisterSize (pScreen,
|
|
sizes[n].width,
|
|
sizes[n].height,
|
|
(sizes[n].width * screen->width_mm)/screen->width,
|
|
(sizes[n].height *screen->height_mm)/screen->height
|
|
);
|
|
n++;
|
|
}
|
|
}
|
|
|
|
pSize = RRRegisterSize (pScreen,
|
|
screen->width,
|
|
screen->height,
|
|
screen->width_mm,
|
|
screen->height_mm);
|
|
|
|
randr = KdSubRotation (scrpriv->randr, screen->randr);
|
|
|
|
RRSetCurrentConfig (pScreen, randr, 0, pSize);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ephyrRandRSetConfig (ScreenPtr pScreen,
|
|
Rotation randr,
|
|
int rate,
|
|
RRScreenSizePtr pSize)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
Bool wasEnabled = pScreenPriv->enabled;
|
|
EphyrScrPriv oldscr;
|
|
int oldwidth, oldheight, oldmmwidth, oldmmheight;
|
|
Bool oldshadow;
|
|
int newwidth, newheight;
|
|
|
|
if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
|
|
{
|
|
newwidth = pSize->width;
|
|
newheight = pSize->height;
|
|
}
|
|
else
|
|
{
|
|
newwidth = pSize->height;
|
|
newheight = pSize->width;
|
|
}
|
|
|
|
if (wasEnabled)
|
|
KdDisableScreen (pScreen);
|
|
|
|
oldscr = *scrpriv;
|
|
|
|
oldwidth = screen->width;
|
|
oldheight = screen->height;
|
|
oldmmwidth = pScreen->mmWidth;
|
|
oldmmheight = pScreen->mmHeight;
|
|
oldshadow = scrpriv->shadow;
|
|
|
|
/*
|
|
* Set new configuration
|
|
*/
|
|
|
|
scrpriv->randr = KdAddRotation (screen->randr, randr);
|
|
|
|
KdOffscreenSwapOut (screen->pScreen);
|
|
|
|
ephyrUnmapFramebuffer (screen);
|
|
|
|
screen->width = newwidth;
|
|
screen->height = newheight;
|
|
|
|
if (!ephyrMapFramebuffer (screen))
|
|
goto bail4;
|
|
|
|
/* FIXME below should go in own call */
|
|
|
|
if (oldshadow)
|
|
KdShadowUnset (screen->pScreen);
|
|
else
|
|
ephyrUnsetInternalDamage(screen->pScreen);
|
|
|
|
if (scrpriv->shadow)
|
|
{
|
|
if (!KdShadowSet (screen->pScreen,
|
|
scrpriv->randr,
|
|
ephyrShadowUpdate,
|
|
ephyrWindowLinear))
|
|
goto bail4;
|
|
}
|
|
else
|
|
{
|
|
/* Without shadow fb ( non rotated ) we need
|
|
* to use damage to efficiently update display
|
|
* via signal regions what to copy from 'fb'.
|
|
*/
|
|
if (!ephyrSetInternalDamage(screen->pScreen))
|
|
goto bail4;
|
|
}
|
|
|
|
ephyrSetScreenSizes (screen->pScreen);
|
|
|
|
/*
|
|
* Set frame buffer mapping
|
|
*/
|
|
(*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
|
|
pScreen->width,
|
|
pScreen->height,
|
|
screen->fb[0].depth,
|
|
screen->fb[0].bitsPerPixel,
|
|
screen->fb[0].byteStride,
|
|
screen->fb[0].frameBuffer);
|
|
|
|
/* set the subpixel order */
|
|
|
|
KdSetSubpixelOrder (pScreen, scrpriv->randr);
|
|
|
|
if (wasEnabled)
|
|
KdEnableScreen (pScreen);
|
|
|
|
return TRUE;
|
|
|
|
bail4:
|
|
EPHYR_DBG("bailed");
|
|
|
|
ephyrUnmapFramebuffer (screen);
|
|
*scrpriv = oldscr;
|
|
(void) ephyrMapFramebuffer (screen);
|
|
|
|
pScreen->width = oldwidth;
|
|
pScreen->height = oldheight;
|
|
pScreen->mmWidth = oldmmwidth;
|
|
pScreen->mmHeight = oldmmheight;
|
|
|
|
if (wasEnabled)
|
|
KdEnableScreen (pScreen);
|
|
return FALSE;
|
|
}
|
|
|
|
Bool
|
|
ephyrRandRInit (ScreenPtr pScreen)
|
|
{
|
|
rrScrPrivPtr pScrPriv;
|
|
|
|
if (!RRScreenInit (pScreen))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pScrPriv = rrGetScrPriv(pScreen);
|
|
pScrPriv->rrGetInfo = ephyrRandRGetInfo;
|
|
pScrPriv->rrSetConfig = ephyrRandRSetConfig;
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
Bool
|
|
ephyrCreateColormap (ColormapPtr pmap)
|
|
{
|
|
return fbInitializeColormap (pmap);
|
|
}
|
|
|
|
Bool
|
|
ephyrInitScreen (ScreenPtr pScreen)
|
|
{
|
|
pScreen->CreateColormap = ephyrCreateColormap;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ephyrFinishInitScreen (ScreenPtr pScreen)
|
|
{
|
|
/* FIXME: Calling this even if not using shadow.
|
|
* Seems harmless enough. But may be safer elsewhere.
|
|
*/
|
|
if (!shadowSetup (pScreen))
|
|
return FALSE;
|
|
|
|
#ifdef RANDR
|
|
if (!ephyrRandRInit (pScreen))
|
|
return FALSE;
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ephyrCreateResources (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
EphyrScrPriv *scrpriv = screen->driver;
|
|
|
|
EPHYR_DBG("mark");
|
|
|
|
if (scrpriv->shadow)
|
|
return KdShadowSet (pScreen,
|
|
scrpriv->randr,
|
|
ephyrShadowUpdate,
|
|
ephyrWindowLinear);
|
|
else
|
|
return ephyrSetInternalDamage(pScreen);
|
|
}
|
|
|
|
void
|
|
ephyrPreserve (KdCardInfo *card)
|
|
{
|
|
}
|
|
|
|
Bool
|
|
ephyrEnable (ScreenPtr pScreen)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ephyrDPMS (ScreenPtr pScreen, int mode)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
ephyrDisable (ScreenPtr pScreen)
|
|
{
|
|
}
|
|
|
|
void
|
|
ephyrRestore (KdCardInfo *card)
|
|
{
|
|
}
|
|
|
|
void
|
|
ephyrScreenFini (KdScreenInfo *screen)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
|
|
* See https://bugs.freedesktop.org/show_bug.cgi?id=3030
|
|
*/
|
|
void
|
|
ephyrUpdateModifierState(unsigned int state)
|
|
{
|
|
DeviceIntPtr pkeydev;
|
|
KeyClassPtr keyc;
|
|
int i;
|
|
CARD8 mask;
|
|
|
|
pkeydev = (DeviceIntPtr)LookupKeyboardDevice();
|
|
|
|
if (!pkeydev)
|
|
return;
|
|
|
|
keyc = pkeydev->key;
|
|
|
|
state = state & 0xff;
|
|
|
|
if (keyc->state == state)
|
|
return;
|
|
|
|
for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
|
|
{
|
|
int key;
|
|
|
|
/* Modifier is down, but shouldn't be */
|
|
if ((keyc->state & mask) && !(state & mask))
|
|
{
|
|
int count = keyc->modifierKeyCount[i];
|
|
|
|
for (key = 0; key < MAP_LENGTH; key++)
|
|
if (keyc->modifierMap[key] & mask)
|
|
{
|
|
int bit;
|
|
BYTE *kptr;
|
|
|
|
kptr = &keyc->down[key >> 3];
|
|
bit = 1 << (key & 7);
|
|
|
|
if (*kptr & bit)
|
|
KdEnqueueKeyboardEvent(key, TRUE); /* release */
|
|
|
|
if (--count == 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Modifier shoud be down, but isn't */
|
|
if (!(keyc->state & mask) && (state & mask))
|
|
for (key = 0; key < MAP_LENGTH; key++)
|
|
if (keyc->modifierMap[key] & mask)
|
|
{
|
|
KdEnqueueKeyboardEvent(key, FALSE); /* press */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ephyrPoll(void)
|
|
{
|
|
EphyrHostXEvent ev;
|
|
|
|
while (hostx_get_event(&ev))
|
|
{
|
|
switch (ev.type)
|
|
{
|
|
case EPHYR_EV_MOUSE_MOTION:
|
|
KdEnqueueMouseEvent(kdMouseInfo, mouseState,
|
|
ev.data.mouse_motion.x,
|
|
ev.data.mouse_motion.y);
|
|
break;
|
|
|
|
case EPHYR_EV_MOUSE_PRESS:
|
|
ephyrUpdateModifierState(ev.key_state);
|
|
mouseState |= ev.data.mouse_down.button_num;
|
|
KdEnqueueMouseEvent(kdMouseInfo, mouseState|KD_MOUSE_DELTA, 0, 0);
|
|
break;
|
|
|
|
case EPHYR_EV_MOUSE_RELEASE:
|
|
ephyrUpdateModifierState(ev.key_state);
|
|
mouseState &= ~ev.data.mouse_up.button_num;
|
|
KdEnqueueMouseEvent(kdMouseInfo, mouseState|KD_MOUSE_DELTA, 0, 0);
|
|
break;
|
|
|
|
case EPHYR_EV_KEY_PRESS:
|
|
ephyrUpdateModifierState(ev.key_state);
|
|
KdEnqueueKeyboardEvent (ev.data.key_down.scancode, FALSE);
|
|
break;
|
|
|
|
case EPHYR_EV_KEY_RELEASE:
|
|
ephyrUpdateModifierState(ev.key_state);
|
|
KdEnqueueKeyboardEvent (ev.data.key_up.scancode, TRUE);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ephyrCardFini (KdCardInfo *card)
|
|
{
|
|
EphyrPriv *priv = card->driver;
|
|
xfree (priv);
|
|
}
|
|
|
|
void
|
|
ephyrGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
|
|
{
|
|
/* XXX Not sure if this is right */
|
|
|
|
EPHYR_DBG("mark");
|
|
|
|
while (n--)
|
|
{
|
|
pdefs->red = 0;
|
|
pdefs->green = 0;
|
|
pdefs->blue = 0;
|
|
pdefs++;
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
ephyrPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
|
|
{
|
|
int min, max, p;
|
|
|
|
/* XXX Not sure if this is right */
|
|
|
|
min = 256;
|
|
max = 0;
|
|
|
|
while (n--)
|
|
{
|
|
p = pdefs->pixel;
|
|
if (p < min)
|
|
min = p;
|
|
if (p > max)
|
|
max = p;
|
|
|
|
hostx_set_cmap_entry(p,
|
|
pdefs->red >> 8,
|
|
pdefs->green >> 8,
|
|
pdefs->blue >> 8);
|
|
pdefs++;
|
|
}
|
|
}
|
|
|
|
/* Mouse calls */
|
|
|
|
static Bool
|
|
MouseInit (void)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
MouseFini (void)
|
|
{
|
|
;
|
|
}
|
|
|
|
KdMouseFuncs EphyrMouseFuncs = {
|
|
MouseInit,
|
|
MouseFini,
|
|
};
|
|
|
|
/* Keyboard */
|
|
|
|
static void
|
|
EphyrKeyboardLoad (void)
|
|
{
|
|
EPHYR_DBG("mark");
|
|
|
|
hostx_load_keymap();
|
|
}
|
|
|
|
static int
|
|
EphyrKeyboardInit (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
EphyrKeyboardFini (void)
|
|
{
|
|
}
|
|
|
|
static void
|
|
EphyrKeyboardLeds (int leds)
|
|
{
|
|
}
|
|
|
|
static void
|
|
EphyrKeyboardBell (int volume, int frequency, int duration)
|
|
{
|
|
}
|
|
|
|
KdKeyboardFuncs EphyrKeyboardFuncs = {
|
|
EphyrKeyboardLoad,
|
|
EphyrKeyboardInit,
|
|
EphyrKeyboardLeds,
|
|
EphyrKeyboardBell,
|
|
EphyrKeyboardFini,
|
|
0,
|
|
};
|