/* * Copyright © 2004 David Reveman * * 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 * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN 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. * * Author: David Reveman */ #include "xglx.h" #include #include #include #ifdef GLXEXT #include "xglglxext.h" #endif #include "inputstr.h" #include "cursorstr.h" #include "mipointer.h" #ifdef RANDR #include "randrstr.h" #endif #include #include #include #include #include #ifdef XKB #include #include #include extern Bool XkbQueryExtension (Display *dpy, int *opcodeReturn, int *eventBaseReturn, int *errorBaseReturn, int *majorRtrn, int *minorRtrn); extern XkbDescPtr XkbGetKeyboard (Display *dpy, unsigned int which, unsigned int deviceSpec); extern Status XkbGetControls (Display *dpy, unsigned long which, XkbDescPtr desc); #ifndef XKB_BASE_DIRECTORY #define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb/" #endif #ifndef XKB_CONFIG_FILE #define XKB_CONFIG_FILE "X0-config.keyboard" #endif #ifndef XKB_DFLT_RULES_FILE #define XKB_DFLT_RULES_FILE "xorg" #endif #ifndef XKB_DFLT_KB_LAYOUT #define XKB_DFLT_KB_LAYOUT "us" #endif #ifndef XKB_DFLT_KB_MODEL #define XKB_DFLT_KB_MODEL "pc101" #endif #ifndef XKB_DFLT_KB_VARIANT #define XKB_DFLT_KB_VARIANT NULL #endif #ifndef XKB_DFLT_KB_OPTIONS #define XKB_DFLT_KB_OPTIONS NULL #endif #endif #define XGLX_DEFAULT_SCREEN_WIDTH 800 #define XGLX_DEFAULT_SCREEN_HEIGHT 600 typedef struct _xglxScreen { Window win, root; Colormap colormap; Bool fullscreen; CloseScreenProcPtr CloseScreen; } xglxScreenRec, *xglxScreenPtr; int xglxScreenGeneration = -1; int xglxScreenPrivateIndex; #define XGLX_GET_SCREEN_PRIV(pScreen) \ ((xglxScreenPtr) (pScreen)->devPrivates[xglxScreenPrivateIndex].ptr) #define XGLX_SET_SCREEN_PRIV(pScreen, v) \ ((pScreen)->devPrivates[xglxScreenPrivateIndex].ptr = (pointer) v) #define XGLX_SCREEN_PRIV(pScreen) \ xglxScreenPtr pScreenPriv = XGLX_GET_SCREEN_PRIV (pScreen) typedef struct _xglxCursor { Cursor cursor; } xglxCursorRec, *xglxCursorPtr; #define XGLX_GET_CURSOR_PRIV(pCursor, pScreen) \ ((xglxCursorPtr) (pCursor)->devPriv[(pScreen)->myNum]) #define XGLX_SET_CURSOR_PRIV(pCursor, pScreen, v) \ ((pCursor)->devPriv[(pScreen)->myNum] = (pointer) v) #define XGLX_CURSOR_PRIV(pCursor, pScreen) \ xglxCursorPtr pCursorPriv = XGLX_GET_CURSOR_PRIV (pCursor, pScreen) static char *xDisplayName = 0; static Display *xdisplay = 0; static int xscreen; static CARD32 lastEventTime = 0; static ScreenPtr currentScreen = 0; static Bool softCursor = FALSE; static Bool fullscreen = TRUE; static Bool randrExtension = FALSE; static int randrEvent, randrError; static glitz_drawable_format_t *xglxScreenFormat = 0; static Bool xglxAllocatePrivates (ScreenPtr pScreen) { xglxScreenPtr pScreenPriv; if (xglxScreenGeneration != serverGeneration) { xglxScreenPrivateIndex = AllocateScreenPrivateIndex (); if (xglxScreenPrivateIndex < 0) return FALSE; xglxScreenGeneration = serverGeneration; } pScreenPriv = xalloc (sizeof (xglxScreenRec)); if (!pScreenPriv) return FALSE; XGLX_SET_SCREEN_PRIV (pScreen, pScreenPriv); return TRUE; } #ifdef RANDR #define DEFAULT_REFRESH_RATE 50 static Bool xglxRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { RRScreenSizePtr pSize; *rotations = RR_Rotate_0; if (randrExtension) { XRRScreenConfiguration *xconfig; XRRScreenSize *sizes; int nSizes, currentSize = 0; short *rates, currentRate; int nRates, i, j; XGLX_SCREEN_PRIV (pScreen); xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root); sizes = XRRConfigSizes (xconfig, &nSizes); currentRate = XRRConfigCurrentRate (xconfig); if (pScreenPriv->fullscreen) { Rotation rotation; currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation); for (i = 0; i < nSizes; i++) { pSize = RRRegisterSize (pScreen, sizes[i].width, sizes[i].height, sizes[i].mwidth, sizes[i].mheight); rates = XRRConfigRates (xconfig, i, &nRates); for (j = 0; j < nRates; j++) { RRRegisterRate (pScreen, pSize, rates[j]); if (i == currentSize && rates[j] == currentRate) RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate, pSize); } } } else { pSize = RRRegisterSize (pScreen, pScreen->width, pScreen->height, pScreen->mmWidth, pScreen->mmHeight); for (i = 0; i < nSizes; i++) { rates = XRRConfigRates (xconfig, i, &nRates); for (j = 0; j < nRates; j++) { RRRegisterRate (pScreen, pSize, rates[j]); if (rates[j] == currentRate) RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate, pSize); } } } XRRFreeScreenConfigInfo (xconfig); } else { pSize = RRRegisterSize (pScreen, pScreen->width, pScreen->height, pScreen->mmWidth, pScreen->mmHeight); RRRegisterRate (pScreen, pSize, DEFAULT_REFRESH_RATE); RRSetCurrentConfig (pScreen, RR_Rotate_0, DEFAULT_REFRESH_RATE, pSize); } return TRUE; } static Bool xglxRandRSetConfig (ScreenPtr pScreen, Rotation rotations, int rate, RRScreenSizePtr pSize) { if (randrExtension) { XRRScreenConfiguration *xconfig; XRRScreenSize *sizes; int nSizes, currentSize; int i, size = -1; int status = RRSetConfigFailed; Rotation rotation; XGLX_SCREEN_PRIV (pScreen); xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root); sizes = XRRConfigSizes (xconfig, &nSizes); currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation); for (i = 0; i < nSizes; i++) { if (pScreenPriv->fullscreen) { if (sizes[i].width == pSize->width && sizes[i].height == pSize->height && sizes[i].mwidth == pSize->mmWidth && sizes[i].mheight == pSize->mmHeight) { size = i; break; } } else { short *rates; int nRates, j; rates = XRRConfigRates (xconfig, i, &nRates); for (j = 0; j < nRates; j++) { if (rates[j] == rate) { size = i; if (i >= currentSize) break; } } } } if (size >= 0) status = XRRSetScreenConfigAndRate (xdisplay, xconfig, pScreenPriv->root, size, RR_Rotate_0, rate, CurrentTime); XRRFreeScreenConfigInfo (xconfig); if (status == RRSetConfigSuccess) { PixmapPtr pPixmap; pPixmap = (*pScreen->GetScreenPixmap) (pScreen); if (pScreenPriv->fullscreen) { XGL_PIXMAP_PRIV (pPixmap); xglSetRootClip (pScreen, FALSE); XResizeWindow (xdisplay, pScreenPriv->win, pSize->width, pSize->height); glitz_drawable_update_size (pPixmapPriv->drawable, pSize->width, pSize->height); pScreen->width = pSize->width; pScreen->height = pSize->height; pScreen->mmWidth = pSize->mmWidth; pScreen->mmHeight = pSize->mmHeight; (*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width, pScreen->height, pPixmap->drawable.depth, pPixmap->drawable.bitsPerPixel, 0, 0); xglSetRootClip (pScreen, TRUE); } return TRUE; } } return FALSE; } static Bool xglxRandRInit (ScreenPtr pScreen) { rrScrPrivPtr pScrPriv; if (!RRScreenInit (pScreen)) return FALSE; pScrPriv = rrGetScrPriv (pScreen); pScrPriv->rrGetInfo = xglxRandRGetInfo; pScrPriv->rrSetConfig = xglxRandRSetConfig; return TRUE; } #endif static void xglxConstrainCursor (ScreenPtr pScreen, BoxPtr pBox) { } static void xglxCursorLimits (ScreenPtr pScreen, CursorPtr pCursor, BoxPtr pHotBox, BoxPtr pTopLeftBox) { *pTopLeftBox = *pHotBox; } static Bool xglxDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor) { XGLX_SCREEN_PRIV (pScreen); XGLX_CURSOR_PRIV (pCursor, pScreen); XDefineCursor (xdisplay, pScreenPriv->win, pCursorPriv->cursor); return TRUE; } #ifdef ARGB_CURSOR static Bool xglxARGBCursorSupport (void); static Cursor xglxCreateARGBCursor (ScreenPtr pScreen, CursorPtr pCursor); #endif static Bool xglxRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) { xglxCursorPtr pCursorPriv; XImage *ximage; Pixmap source, mask; XColor fgColor, bgColor; XlibGC xgc; unsigned long valuemask; XGCValues values; XGLX_SCREEN_PRIV (pScreen); valuemask = GCForeground | GCBackground; values.foreground = 1L; values.background = 0L; pCursorPriv = xalloc (sizeof (xglxCursorRec)); if (!pCursorPriv) return FALSE; XGLX_SET_CURSOR_PRIV (pCursor, pScreen, pCursorPriv); #ifdef ARGB_CURSOR if (pCursor->bits->argb) { pCursorPriv->cursor = xglxCreateARGBCursor (pScreen, pCursor); if (pCursorPriv->cursor) return TRUE; } #endif source = XCreatePixmap (xdisplay, pScreenPriv->win, pCursor->bits->width, pCursor->bits->height, 1); mask = XCreatePixmap (xdisplay, pScreenPriv->win, pCursor->bits->width, pCursor->bits->height, 1); xgc = XCreateGC (xdisplay, source, valuemask, &values); ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, xscreen), 1, XYBitmap, 0, (char *) pCursor->bits->source, pCursor->bits->width, pCursor->bits->height, BitmapPad (xdisplay), 0); XPutImage (xdisplay, source, xgc, ximage, 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); XFree (ximage); ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, xscreen), 1, XYBitmap, 0, (char *) pCursor->bits->mask, pCursor->bits->width, pCursor->bits->height, BitmapPad (xdisplay), 0); XPutImage (xdisplay, mask, xgc, ximage, 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); XFree (ximage); XFreeGC (xdisplay, xgc); fgColor.red = pCursor->foreRed; fgColor.green = pCursor->foreGreen; fgColor.blue = pCursor->foreBlue; bgColor.red = pCursor->backRed; bgColor.green = pCursor->backGreen; bgColor.blue = pCursor->backBlue; pCursorPriv->cursor = XCreatePixmapCursor (xdisplay, source, mask, &fgColor, &bgColor, pCursor->bits->xhot, pCursor->bits->yhot); XFreePixmap (xdisplay, mask); XFreePixmap (xdisplay, source); return TRUE; } static Bool xglxUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) { XGLX_CURSOR_PRIV (pCursor, pScreen); XFreeCursor (xdisplay, pCursorPriv->cursor); xfree (pCursorPriv); return TRUE; } static void xglxRecolorCursor (ScreenPtr pScreen, CursorPtr pCursor, Bool displayed) { XColor fgColor, bgColor; XGLX_CURSOR_PRIV (pCursor, pScreen); fgColor.red = pCursor->foreRed; fgColor.green = pCursor->foreGreen; fgColor.blue = pCursor->foreBlue; bgColor.red = pCursor->backRed; bgColor.green = pCursor->backGreen; bgColor.blue = pCursor->backBlue; XRecolorCursor (xdisplay, pCursorPriv->cursor, &fgColor, &bgColor); } static Bool xglxSetCursorPosition (ScreenPtr pScreen, int x, int y, Bool generateEvent) { XGLX_SCREEN_PRIV (pScreen); XWarpPointer (xdisplay, pScreenPriv->win, pScreenPriv->win, 0, 0, 0, 0, x, y); return TRUE; } static Bool xglxCloseScreen (int index, ScreenPtr pScreen) { glitz_drawable_t *drawable; XGLX_SCREEN_PRIV (pScreen); drawable = XGL_GET_SCREEN_PRIV (pScreen)->drawable; if (drawable) glitz_drawable_destroy (drawable); xglClearVisualTypes (); if (pScreenPriv->win) XDestroyWindow (xdisplay, pScreenPriv->win); if (pScreenPriv->colormap) XFreeColormap (xdisplay, pScreenPriv->colormap); XGL_SCREEN_UNWRAP (CloseScreen); xfree (pScreenPriv); return (*pScreen->CloseScreen) (index, pScreen); } static Bool xglxCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y) { return FALSE; } static void xglxCrossScreen (ScreenPtr pScreen, Bool entering) { } static void xglxWarpCursor (ScreenPtr pScreen, int x, int y) { miPointerWarpCursor (pScreen, x, y); } miPointerScreenFuncRec xglxPointerScreenFuncs = { xglxCursorOffScreen, xglxCrossScreen, xglxWarpCursor }; static Bool xglxScreenInit (int index, ScreenPtr pScreen, int argc, char **argv) { XSetWindowAttributes xswa; XWMHints *wmHints; XSizeHints *normalHints; XClassHint *classHint; xglxScreenPtr pScreenPriv; XVisualInfo *vinfo; XEvent xevent; glitz_drawable_format_t *format; glitz_drawable_t *drawable; format = xglxScreenFormat; if (!xglxAllocatePrivates (pScreen)) return FALSE; currentScreen = pScreen; pScreenPriv = XGLX_GET_SCREEN_PRIV (pScreen); pScreenPriv->root = RootWindow (xdisplay, xscreen); pScreenPriv->fullscreen = fullscreen; vinfo = glitz_glx_get_visual_info_from_format (xdisplay, xscreen, format); if (!vinfo) { ErrorF ("[%d] no visual info from format\n", index); return FALSE; } pScreenPriv->colormap = XCreateColormap (xdisplay, pScreenPriv->root, vinfo->visual, AllocNone); if (XRRQueryExtension (xdisplay, &randrEvent, &randrError)) randrExtension = TRUE; if (fullscreen) { xglScreenInfo.width = DisplayWidth (xdisplay, xscreen); xglScreenInfo.height = DisplayHeight (xdisplay, xscreen); xglScreenInfo.widthMm = DisplayWidthMM (xdisplay, xscreen); xglScreenInfo.heightMm = DisplayHeightMM (xdisplay, xscreen); if (randrExtension) { XRRScreenConfiguration *xconfig; Rotation rotation; XRRScreenSize *sizes; int nSizes, currentSize; xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root); currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation); sizes = XRRConfigSizes (xconfig, &nSizes); xglScreenInfo.width = sizes[currentSize].width; xglScreenInfo.height = sizes[currentSize].height; xglScreenInfo.widthMm = sizes[currentSize].mwidth; xglScreenInfo.heightMm = sizes[currentSize].mheight; XRRFreeScreenConfigInfo (xconfig); } } else if (xglScreenInfo.width == 0 || xglScreenInfo.height == 0) { xglScreenInfo.width = XGLX_DEFAULT_SCREEN_WIDTH; xglScreenInfo.height = XGLX_DEFAULT_SCREEN_HEIGHT; } xswa.colormap = pScreenPriv->colormap; pScreenPriv->win = XCreateWindow (xdisplay, pScreenPriv->root, 0, 0, xglScreenInfo.width, xglScreenInfo.height, 0, vinfo->depth, InputOutput, vinfo->visual, CWColormap, &xswa); XFree (vinfo); normalHints = XAllocSizeHints (); normalHints->flags = PMinSize | PMaxSize | PSize; normalHints->min_width = xglScreenInfo.width; normalHints->min_height = xglScreenInfo.height; normalHints->max_width = xglScreenInfo.width; normalHints->max_height = xglScreenInfo.height; if (fullscreen) { normalHints->x = 0; normalHints->y = 0; normalHints->flags |= PPosition; } classHint = XAllocClassHint (); classHint->res_name = "xglx"; classHint->res_class = "Xglx"; wmHints = XAllocWMHints (); wmHints->flags = InputHint; wmHints->input = TRUE; Xutf8SetWMProperties (xdisplay, pScreenPriv->win, "Xglx", "Xglx", 0, 0, normalHints, wmHints, classHint); XFree (wmHints); XFree (classHint); XFree (normalHints); drawable = glitz_glx_create_drawable_for_window (xdisplay, xscreen, format, pScreenPriv->win, xglScreenInfo.width, xglScreenInfo.height); if (!drawable) { ErrorF ("[%d] couldn't create glitz drawable for window\n", index); return FALSE; } XSelectInput (xdisplay, pScreenPriv->win, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | PointerMotionMask | ExposureMask); XMapWindow (xdisplay, pScreenPriv->win); if (fullscreen) { XClientMessageEvent xev; memset (&xev, 0, sizeof (xev)); xev.type = ClientMessage; xev.message_type = XInternAtom (xdisplay, "_NET_WM_STATE", FALSE); xev.display = xdisplay; xev.window = pScreenPriv->win; xev.format = 32; xev.data.l[0] = 1; xev.data.l[1] = XInternAtom (xdisplay, "_NET_WM_STATE_FULLSCREEN", FALSE); XSendEvent (xdisplay, pScreenPriv->root, FALSE, SubstructureRedirectMask, (XEvent *) &xev); } xglScreenInfo.drawable = drawable; if (!xglScreenInit (pScreen)) return FALSE; #ifdef GLXEXT if (!xglInitVisualConfigs (pScreen)) return FALSE; #endif XGL_SCREEN_WRAP (CloseScreen, xglxCloseScreen); #ifdef ARGB_CURSOR if (!xglxARGBCursorSupport ()) softCursor = TRUE; #endif if (softCursor) { static char data = 0; XColor black, dummy; Pixmap bitmap; Cursor cursor; if (!XAllocNamedColor (xdisplay, pScreenPriv->colormap, "black", &black, &dummy)) return FALSE; bitmap = XCreateBitmapFromData (xdisplay, pScreenPriv->win, &data, 1, 1); if (!bitmap) return FALSE; cursor = XCreatePixmapCursor (xdisplay, bitmap, bitmap, &black, &black, 0, 0); if (!cursor) return FALSE; XDefineCursor (xdisplay, pScreenPriv->win, cursor); XFreeCursor (xdisplay, cursor); XFreePixmap (xdisplay, bitmap); XFreeColors (xdisplay, pScreenPriv->colormap, &black.pixel, 1, 0); miDCInitialize (pScreen, &xglxPointerScreenFuncs); } else { pScreen->ConstrainCursor = xglxConstrainCursor; pScreen->CursorLimits = xglxCursorLimits; pScreen->DisplayCursor = xglxDisplayCursor; pScreen->RealizeCursor = xglxRealizeCursor; pScreen->UnrealizeCursor = xglxUnrealizeCursor; pScreen->RecolorCursor = xglxRecolorCursor; pScreen->SetCursorPosition = xglxSetCursorPosition; } if (!xglFinishScreenInit (pScreen)) return FALSE; #ifdef RANDR if (!xglxRandRInit (pScreen)) return FALSE; #endif while (XNextEvent (xdisplay, &xevent)) if (xevent.type == Expose) break; return TRUE; } void xglxInitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) { glitz_drawable_format_t *format, templ; int i; unsigned long mask; unsigned long extraMask[] = { GLITZ_FORMAT_DOUBLEBUFFER_MASK | GLITZ_FORMAT_ALPHA_SIZE_MASK, GLITZ_FORMAT_DOUBLEBUFFER_MASK, GLITZ_FORMAT_ALPHA_SIZE_MASK, 0 }; xglClearVisualTypes (); xglSetPixmapFormats (pScreenInfo); if (!xdisplay) { char *name = xDisplayName; if (!name) name = xglxInitXorg (); xdisplay = XOpenDisplay (name); if (!xdisplay) FatalError ("can't open display: %s\n", name ? name : "NULL"); xscreen = DefaultScreen (xdisplay); if (!xDisplayName) XDefineCursor (xdisplay, RootWindow (xdisplay, xscreen), XCreateFontCursor (xdisplay, XC_watch)); } templ.samples = 1; templ.doublebuffer = 1; templ.color.fourcc = GLITZ_FOURCC_RGB; templ.color.alpha_size = 8; mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK; for (i = 0; i < sizeof (extraMask) / sizeof (extraMask[0]); i++) { format = glitz_glx_find_window_format (xdisplay, xscreen, mask | extraMask[i], &templ, 0); if (format) break; } if (!format) FatalError ("no visual format found"); xglScreenInfo.depth = format->color.red_size + format->color.green_size + format->color.blue_size; xglSetVisualTypes (xglScreenInfo.depth, (1 << TrueColor), format->color.red_size, format->color.green_size, format->color.blue_size); xglxScreenFormat = format; AddScreen (xglxScreenInit, argc, argv); } static Bool xglxExposurePredicate (Display *xdisplay, XEvent *xevent, char *args) { return (xevent->type == Expose); } static Bool xglxNotExposurePredicate (Display *xdisplay, XEvent *xevent, char *args) { return (xevent->type != Expose); } static int xglxWindowExposures (WindowPtr pWin, pointer pReg) { ScreenPtr pScreen = pWin->drawable.pScreen; RegionRec ClipList; if (HasBorder (pWin)) { REGION_INIT (pScreen, &ClipList, NullBox, 0); REGION_SUBTRACT (pScreen, &ClipList, &pWin->borderClip, &pWin->winSize); REGION_INTERSECT (pScreen, &ClipList, &ClipList, (RegionPtr) pReg); (*pScreen->PaintWindowBorder) (pWin, &ClipList, PW_BORDER); REGION_UNINIT (pScreen, &ClipList); } REGION_INIT (pScreen, &ClipList, NullBox, 0); REGION_INTERSECT (pScreen, &ClipList, &pWin->clipList, (RegionPtr) pReg); (*pScreen->WindowExposures) (pWin, &ClipList, NullRegion); REGION_UNINIT (pScreen, &ClipList); return WT_WALKCHILDREN; } static void xglxBlockHandler (pointer blockData, OSTimePtr pTimeout, pointer pReadMask) { XEvent X; RegionRec region; BoxRec box; XGL_SCREEN_PRIV (currentScreen); while (XCheckIfEvent (xdisplay, &X, xglxExposurePredicate, NULL)) { ScreenPtr pScreen = currentScreen; box.x1 = X.xexpose.x; box.y1 = X.xexpose.y; box.x2 = box.x1 + X.xexpose.width; box.y2 = box.y1 + X.xexpose.height; REGION_INIT (currentScreen, ®ion, &box, 1); WalkTree (pScreen, xglxWindowExposures, ®ion); REGION_UNINIT (pScreen, ®ion); } if (!xglSyncSurface (&pScreenPriv->pScreenPixmap->drawable)) FatalError (XGL_SW_FAILURE_STRING); glitz_surface_flush (pScreenPriv->surface); glitz_drawable_flush (pScreenPriv->drawable); XFlush (xdisplay); } static void xglxWakeupHandler (pointer blockData, int result, pointer pReadMask) { ScreenPtr pScreen = currentScreen; XEvent X; xEvent x; while (XCheckIfEvent (xdisplay, &X, xglxNotExposurePredicate, NULL)) { switch (X.type) { case KeyPress: x.u.u.type = KeyPress; x.u.u.detail = X.xkey.keycode; x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis (); mieqEnqueue (&x); break; case KeyRelease: x.u.u.type = KeyRelease; x.u.u.detail = X.xkey.keycode; x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis (); mieqEnqueue (&x); break; case ButtonPress: x.u.u.type = ButtonPress; x.u.u.detail = X.xbutton.button; x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis (); mieqEnqueue (&x); break; case ButtonRelease: x.u.u.type = ButtonRelease; x.u.u.detail = X.xbutton.button; x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis (); mieqEnqueue (&x); break; case MotionNotify: x.u.u.type = MotionNotify; x.u.u.detail = 0; x.u.keyButtonPointer.rootX = X.xmotion.x; x.u.keyButtonPointer.rootY = X.xmotion.y; x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis (); miPointerAbsoluteCursor (X.xmotion.x, X.xmotion.y, lastEventTime); mieqEnqueue (&x); break; case EnterNotify: if (X.xcrossing.detail != NotifyInferior) { if (pScreen) { NewCurrentScreen (pScreen, X.xcrossing.x, X.xcrossing.y); x.u.u.type = MotionNotify; x.u.u.detail = 0; x.u.keyButtonPointer.rootX = X.xcrossing.x; x.u.keyButtonPointer.rootY = X.xcrossing.y; x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis (); mieqEnqueue (&x); } } break; default: break; } } } static void xglxBell (int volume, DeviceIntPtr pDev, pointer ctrl, int cls) { XBell (xdisplay, volume); } static void xglxKbdCtrl (DeviceIntPtr pDev, KeybdCtrl *ctrl) { unsigned long valueMask; XKeyboardControl values; int i; valueMask = KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration | KBAutoRepeatMode; values.key_click_percent = ctrl->click; values.bell_percent = ctrl->bell; values.bell_pitch = ctrl->bell_pitch; values.bell_duration = ctrl->bell_duration; values.auto_repeat_mode = (ctrl->autoRepeat) ? AutoRepeatModeOn : AutoRepeatModeOff; XChangeKeyboardControl (xdisplay, valueMask, &values); valueMask = KBLed | KBLedMode; for (i = 1; i <= 32; i++) { values.led = i; values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff; XChangeKeyboardControl (xdisplay, valueMask, &values); } } static int xglxKeybdProc (DeviceIntPtr pDevice, int onoff) { Bool ret = FALSE; DevicePtr pDev = (DevicePtr) pDevice; if (!pDev) return BadImplementation; switch (onoff) { case DEVICE_INIT: { XModifierKeymap *xmodMap; KeySym *xkeyMap; int minKeyCode, maxKeyCode, mapWidth, i, j; KeySymsRec xglxKeySyms; CARD8 xglxModMap[256]; XKeyboardState values; #ifdef _XSERVER64 KeySym64 *xkeyMap64; int len; #endif #ifdef XKB Bool xkbExtension = FALSE; int xkbOp, xkbEvent, xkbError, xkbMajor, xkbMinor; #endif if (pDev != LookupKeyboardDevice ()) return !Success; xmodMap = XGetModifierMapping (xdisplay); XDisplayKeycodes (xdisplay, &minKeyCode, &maxKeyCode); #ifdef _XSERVER64 xkeyMap64 = XGetKeyboardMapping (xdisplay, minKeyCode, maxKeyCode - minKeyCode + 1, &mapWidth); len = (maxKeyCode - minKeyCode + 1) * mapWidth; xkeyMap = (KeySym *) xalloc (len * sizeof (KeySym)); for (i = 0; i < len; ++i) xkeyMap[i] = xkeyMap64[i]; XFree (xkeyMap64); #else xkeyMap = XGetKeyboardMapping (xdisplay, minKeyCode, maxKeyCode - minKeyCode + 1, &mapWidth); #endif memset (xglxModMap, 0, 256); for (j = 0; j < 8; j++) { for (i = 0; i < xmodMap->max_keypermod; i++) { CARD8 keyCode; keyCode = xmodMap->modifiermap[j * xmodMap->max_keypermod + i]; if (keyCode) xglxModMap[keyCode] |= 1 << j; } } XFreeModifiermap (xmodMap); xglxKeySyms.minKeyCode = minKeyCode; xglxKeySyms.maxKeyCode = maxKeyCode; xglxKeySyms.mapWidth = mapWidth; xglxKeySyms.map = xkeyMap; #ifdef XKB if (!noXkbExtension) xkbExtension = XkbQueryExtension (xdisplay, &xkbOp, &xkbEvent, &xkbError, &xkbMajor, &xkbMinor); if (xkbExtension) { XkbDescPtr desc; char *rules, *model, *layout, *variants, *options; desc = XkbGetKeyboard (xdisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd); if (desc && desc->geom) { XkbComponentNamesRec names; FILE *file; rules = XKB_DFLT_RULES_FILE; model = XKB_DFLT_KB_MODEL; layout = XKB_DFLT_KB_LAYOUT; variants = XKB_DFLT_KB_VARIANT; options = XKB_DFLT_KB_OPTIONS; XkbGetControls (xdisplay, XkbAllControlsMask, desc); memset (&names, 0, sizeof (XkbComponentNamesRec)); XkbSetRulesDflts (rules, model, layout, variants, options); ret = XkbInitKeyboardDeviceStruct ((pointer) pDev, &names, &xglxKeySyms, xglxModMap, xglxBell, xglxKbdCtrl); if (ret) XkbDDXChangeControls ((pointer) pDev, desc->ctrls, desc->ctrls); XkbFreeKeyboard (desc, 0, False); } } #endif if (!ret) { XGetKeyboardControl (xdisplay, &values); memmove (defaultKeyboardControl.autoRepeats, values.auto_repeats, sizeof (values.auto_repeats)); ret = InitKeyboardDeviceStruct (pDev, &xglxKeySyms, xglxModMap, xglxBell, xglxKbdCtrl); } #ifdef _XSERVER64 xfree (xkeyMap); #else XFree (xkeyMap); #endif if (!ret) return BadImplementation; } break; case DEVICE_ON: pDev->on = TRUE; break; case DEVICE_OFF: case DEVICE_CLOSE: pDev->on = FALSE; break; } return Success; } Bool xglxLegalModifier (unsigned int key, DeviceIntPtr pDev) { return TRUE; } void xglxProcessInputEvents (void) { mieqProcessInputEvents (); miPointerUpdate (); } void xglxInitInput (int argc, char **argv) { DeviceIntPtr pKeyboard, pPointer; pPointer = AddInputDevice (xglMouseProc, TRUE); pKeyboard = AddInputDevice (xglxKeybdProc, TRUE); RegisterPointerDevice (pPointer); RegisterKeyboardDevice (pKeyboard); miRegisterPointerDevice (screenInfo.screens[0], pPointer); mieqInit (&pKeyboard->public, &pPointer->public); AddEnabledDevice (XConnectionNumber (xdisplay)); RegisterBlockAndWakeupHandlers (xglxBlockHandler, xglxWakeupHandler, NULL); } void xglxUseMsg (void) { ErrorF ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM] " "specify screen characteristics\n"); ErrorF ("-fullscreen run fullscreen\n"); ErrorF ("-display string display name of the real server\n"); ErrorF ("-softcursor force software cursor\n"); if (!xDisplayName) xglxUseXorgMsg (); } int xglxProcessArgument (int argc, char **argv, int i) { static Bool checkDisplayName = FALSE; if (!checkDisplayName) { char *display = ":0"; int j; for (j = i; j < argc; j++) { if (!strcmp (argv[j], "-display")) { if (++j < argc) xDisplayName = argv[j]; break; } else if (argv[j][0] == ':') { display = argv[j]; } } if (!xDisplayName) xDisplayName = getenv ("DISPLAY"); if (xDisplayName) { int n; n = strspn (xDisplayName, ":0123456789"); if (strncmp (xDisplayName, display, n) == 0) xDisplayName = 0; } if (xDisplayName) fullscreen = FALSE; checkDisplayName = TRUE; } if (!strcmp (argv[i], "-screen")) { if ((i + 1) < argc) { xglParseScreen (argv[i + 1]); } else return 1; return 2; } else if (!strcmp (argv[i], "-fullscreen")) { fullscreen = TRUE; return 1; } else if (!strcmp (argv[i], "-display")) { if (++i < argc) return 2; return 0; } else if (!strcmp (argv[i], "-softcursor")) { softCursor = TRUE; return 1; } else if (!xDisplayName) { return xglxProcessXorgArgument (argc, argv, i); } return 0; } void xglxAbort (void) { xglxAbortXorg (); } void xglxGiveUp (void) { AbortDDX (); } void xglxOsVendorInit (void) { } #ifdef ARGB_CURSOR #include static Bool xglxARGBCursorSupport (void) { int renderMajor, renderMinor; if (!XRenderQueryVersion (xdisplay, &renderMajor, &renderMinor)) renderMajor = renderMinor = -1; return (renderMajor > 0 || renderMinor > 4); } static Cursor xglxCreateARGBCursor (ScreenPtr pScreen, CursorPtr pCursor) { Pixmap xpixmap; XlibGC xgc; XImage *ximage; XRenderPictFormat *xformat; Picture xpicture; Cursor cursor; XGLX_SCREEN_PRIV (pScreen); xpixmap = XCreatePixmap (xdisplay, pScreenPriv->win, pCursor->bits->width, pCursor->bits->height, 32); xgc = XCreateGC (xdisplay, xpixmap, 0, NULL); ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, xscreen), 32, ZPixmap, 0, (char *) pCursor->bits->argb, pCursor->bits->width, pCursor->bits->height, 32, pCursor->bits->width * 4); XPutImage (xdisplay, xpixmap, xgc, ximage, 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); XFree (ximage); XFreeGC (xdisplay, xgc); xformat = XRenderFindStandardFormat (xdisplay, PictStandardARGB32); xpicture = XRenderCreatePicture (xdisplay, xpixmap, xformat, 0, 0); cursor = XRenderCreateCursor (xdisplay, xpicture, pCursor->bits->xhot, pCursor->bits->yhot); XRenderFreePicture (xdisplay, xpicture); XFreePixmap (xdisplay, xpixmap); return cursor; } #endif