xserver-multidpi/hw/xgl/glx/xglx.c
Eric Anholt e4d11e58ce Remove the PaintWindow optimization.
This was an attempt to avoid scratch gc creation and validation for paintwin
because that was expensive.  This is not the case in current servers, and the
danger of failure to implement it correctly (as seen in all previous
implementations) is high enough to justify removing it.  No performance
difference detected with x11perf -create -move -resize -circulate on Xvfb.
Leave the screen hooks for PaintWindow* in for now to avoid ABI change.
2007-09-13 00:08:53 +00:00

1455 lines
32 KiB
C

/*
* 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;
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);
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 != 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 <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