aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xgl/glx/xglx.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xgl/glx/xglx.c')
-rw-r--r--xorg-server/hw/xgl/glx/xglx.c1444
1 files changed, 1444 insertions, 0 deletions
diff --git a/xorg-server/hw/xgl/glx/xglx.c b/xorg-server/hw/xgl/glx/xglx.c
new file mode 100644
index 000000000..33b276b74
--- /dev/null
+++ b/xorg-server/hw/xgl/glx/xglx.c
@@ -0,0 +1,1444 @@
+/*
+ * 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 <davidr@novell.com>
+ */
+
+#include "xglx.h"
+
+#include <X11/extensions/Xrandr.h>
+#include <X11/cursorfont.h>
+
+#include <glitz-glx.h>
+
+#ifdef GLXEXT
+#include "xglglxext.h"
+#endif
+
+#include "inputstr.h"
+#include "cursorstr.h"
+#include "mipointer.h"
+
+#ifdef RANDR
+#include "randrstr.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <math.h>
+
+#ifdef XKB
+#include <X11/extensions/XKB.h>
+#include <xkbsrv.h>
+#include <X11/extensions/XKBconfig.h>
+
+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;
+
+DevPrivateKey xglxScreenPrivateKey = &xglxScreenPrivateKey;
+
+#define XGLX_GET_SCREEN_PRIV(pScreen) ((xglxScreenPtr) \
+ dixLookupPrivate(&(pScreen)->devPrivates, xglxScreenPrivateKey))
+
+#define XGLX_SET_SCREEN_PRIV(pScreen, v) \
+ dixSetPrivate(&(pScreen)->devPrivates, xglxScreenPrivateKey, 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)dixLookupPrivate(&(pCursor)->devPrivates, pScreen))
+
+#define XGLX_SET_CURSOR_PRIV(pCursor, pScreen, v) \
+ dixSetPrivate(&(pCursor)->devPrivates, pScreen, 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;
+
+ 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);
+ miPaintWindow(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, &region, &box, 1);
+
+ WalkTree (pScreen, xglxWindowExposures, &region);
+
+ REGION_UNINIT (pScreen, &region);
+ }
+
+ 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 != (DevicePtr)inputInfo.keyboard)
+ 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 <X11/extensions/Xrender.h>
+
+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