xserver/hw/dmx/dmxscrinit.c

1363 lines
35 KiB
C
Raw Normal View History

/*
* Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Authors:
* Kevin E. Martin <kem@redhat.com>
* David H. Dawes <dawes@xfree86.org>
*
*/
/** \file
* This file provides support for screen initialization. */
#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#include "dmx.h"
2008-06-03 18:18:04 -04:00
#include "dmxextension.h"
#include "dmxsync.h"
#include "dmxshadow.h"
#include "dmxscrinit.h"
#include "dmxcursor.h"
#include "dmxgc.h"
#include "dmxgcops.h"
#include "dmxwindow.h"
#include "dmxpixmap.h"
#include "dmxfont.h"
#include "dmxcmap.h"
#include "dmxprop.h"
#include "dmxdpms.h"
2008-06-03 18:18:04 -04:00
#include "dmxlog.h"
2008-06-02 22:54:14 -04:00
#include "dmxcb.h"
#include "dmxinit.h"
2008-07-26 02:44:37 -04:00
#include "dmxgrab.h"
2008-08-02 11:07:58 -04:00
#include "dmxatom.h"
2008-08-04 17:39:48 -04:00
#include "dmxshm.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#ifdef RENDER
#include "dmxpict.h"
#endif
2008-07-26 02:44:37 -04:00
#ifdef COMPOSITE
#include "dmxcomp.h"
#endif
2008-06-03 18:18:04 -04:00
#ifdef RANDR
#include "dmxrandr.h"
2008-06-03 18:18:04 -04:00
#endif
2008-07-25 14:23:38 -04:00
#ifdef XV
#include "dmxxv.h"
#endif
#include "fb.h"
#include "mipointer.h"
#include "micmap.h"
2008-06-10 16:06:38 -04:00
#include "mivalidate.h"
extern Bool dmxCloseScreen(int idx, ScreenPtr pScreen);
static Bool dmxSaveScreen(ScreenPtr pScreen, int what);
static unsigned long dmxGeneration;
static unsigned long *dmxCursorGeneration;
static int dmxGCPrivateKeyIndex;
DevPrivateKey dmxGCPrivateKey = &dmxGCPrivateKey; /**< Private index for GCs */
static int dmxWinPrivateKeyIndex;
DevPrivateKey dmxWinPrivateKey = &dmxWinPrivateKeyIndex; /**< Private index for Windows */
static int dmxPixPrivateKeyIndex;
DevPrivateKey dmxPixPrivateKey = &dmxPixPrivateKeyIndex; /**< Private index for Pixmaps */
int dmxFontPrivateIndex; /**< Private index for Fonts */
static int dmxScreenPrivateKeyIndex;
DevPrivateKey dmxScreenPrivateKey = &dmxScreenPrivateKeyIndex; /**< Private index for Screens */
static int dmxColormapPrivateKeyIndex;
DevPrivateKey dmxColormapPrivateKey = &dmxColormapPrivateKeyIndex; /**< Private index for Colormaps */
static int dmxDevicePrivateKeyIndex;
DevPrivateKey dmxDevicePrivateKey = &dmxDevicePrivateKeyIndex; /**< Private index for Devices */
#ifdef RENDER
static int dmxPictPrivateKeyIndex;
DevPrivateKey dmxPictPrivateKey = &dmxPictPrivateKeyIndex; /**< Private index for Picts */
static int dmxGlyphSetPrivateKeyIndex;
DevPrivateKey dmxGlyphSetPrivateKey = &dmxGlyphSetPrivateKeyIndex; /**< Private index for GlyphSets */
static int dmxGlyphPrivateKeyIndex;
DevPrivateKey dmxGlyphPrivateKey = &dmxGlyphPrivateKeyIndex; /**< Private index for Glyphs */
#endif
/** Initialize the parts of screen \a idx that require access to the
* back-end server. */
void dmxBEScreenInit(int idx, ScreenPtr pScreen)
{
DMXScreenInfo *dmxScreen = &dmxScreens[idx];
XSetWindowAttributes attribs;
XGCValues gcvals;
unsigned long mask;
int i, j;
/* FIXME: The dmxScreenInit() code currently assumes that it will
* not be called if the Xdmx server is started with this screen
* detached -- i.e., it assumes that dmxScreen->beDisplay is always
* valid. This is not necessarily a valid assumption when full
* addition/removal of screens is implemented, but when this code is
* broken out for screen reattachment, then we will reevaluate this
* assumption.
*/
pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay,
DefaultScreen(dmxScreen->beDisplay));
pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay,
DefaultScreen(dmxScreen->beDisplay));
pScreen->whitePixel = dmxScreen->beWhitePixel;
pScreen->blackPixel = dmxScreen->beBlackPixel;
/* Handle screen savers and DPMS on the backend */
dmxDPMSInit(dmxScreen);
/* Create root window for screen */
mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
attribs.background_pixel = dmxScreen->beBlackPixel;
attribs.event_mask = StructureNotifyMask | SubstructureRedirectMask;
attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex];
attribs.override_redirect = True;
2008-06-03 18:18:04 -04:00
if (!dmxScreen->beUseRoot)
{
dmxScreen->scrnWin =
XCreateWindow(dmxScreen->beDisplay,
DefaultRootWindow(dmxScreen->beDisplay),
dmxScreen->scrnX,
dmxScreen->scrnY,
dmxScreen->scrnWidth,
dmxScreen->scrnHeight,
0,
pScreen->rootDepth,
InputOutput,
dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
mask,
&attribs);
}
else
{
dmxScreen->scrnWin = DefaultRootWindow (dmxScreen->beDisplay);
XSetWindowBackground (dmxScreen->beDisplay, dmxScreen->scrnWin,
attribs.background_pixel);
XSelectInput (dmxScreen->beDisplay, dmxScreen->scrnWin,
attribs.event_mask);
}
dmxPropertyWindow(dmxScreen);
/*
* This turns off the cursor by defining a cursor with no visible
* components.
*/
2008-06-03 18:18:04 -04:00
if (1) {
char noCursorData[] = {0, 0, 0, 0,
0, 0, 0, 0};
Pixmap pixmap;
XColor color, tmp;
pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin,
noCursorData, 8, 8);
XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0],
"black", &color, &tmp);
dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay,
pixmap, pixmap,
&color, &color, 0, 0);
XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
dmxScreen->noCursor);
XFreePixmap(dmxScreen->beDisplay, pixmap);
}
2008-06-03 18:18:04 -04:00
#ifdef RANDR
dmxBERRScreenInit (pScreen);
2008-06-03 18:18:04 -04:00
#endif
2008-07-25 14:23:38 -04:00
#ifdef XV
dmxBEXvScreenInit (pScreen);
#endif
if (!dmxScreen->beUseRoot)
XMapWindow (dmxScreen->beDisplay, dmxScreen->scrnWin);
if (dmxShadowFB) {
mask = (GCFunction
| GCPlaneMask
| GCClipMask);
gcvals.function = GXcopy;
gcvals.plane_mask = AllPlanes;
gcvals.clip_mask = None;
dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay,
dmxScreen->scrnWin,
mask, &gcvals);
dmxScreen->shadowFBImage =
XCreateImage(dmxScreen->beDisplay,
dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
dmxScreen->beDepth,
ZPixmap,
0,
(char *)dmxScreen->shadow,
dmxScreen->scrnWidth, dmxScreen->scrnHeight,
dmxScreen->beBPP,
PixmapBytePad(dmxScreen->scrnWidth,
dmxScreen->beBPP));
} else {
/* Create default drawables (used during GC creation) */
for (i = 0; i < dmxScreen->beNumPixmapFormats; i++)
for (j = 0; j < dmxScreen->beNumDepths; j++)
if ((dmxScreen->bePixmapFormats[i].depth == 1) ||
(dmxScreen->bePixmapFormats[i].depth ==
dmxScreen->beDepths[j])) {
dmxScreen->scrnDefDrawables[i] = (Drawable)
XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
1, 1, dmxScreen->bePixmapFormats[i].depth);
break;
}
}
}
2008-06-03 18:18:04 -04:00
static void
dmxSetWindowPixmap (WindowPtr pWin, PixmapPtr pPixmap)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
if (pPixmap != pOld)
{
dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWin);
2008-06-07 09:00:34 -04:00
if (pPixmap && (*pScreen->GetWindowPixmap) (pWin->parent) != pPixmap)
pWinPriv->redirected = TRUE;
else
2008-06-03 18:18:04 -04:00
pWinPriv->redirected = FALSE;
}
DMX_UNWRAP(SetWindowPixmap, dmxScreen, pScreen);
if (pScreen->SetWindowPixmap)
(*pScreen->SetWindowPixmap) (pWin, pPixmap);
DMX_WRAP(SetWindowPixmap, dmxSetWindowPixmap, dmxScreen, pScreen);
}
static void
dmxDiscardIgnore (DMXScreenInfo *dmxScreen,
unsigned long sequence)
{
while (dmxScreen->ignore.head)
{
if ((long) (sequence - dmxScreen->ignore.head->sequence) > 0)
{
DMXSequence *next = dmxScreen->ignore.head->next;
free (dmxScreen->ignore.head);
dmxScreen->ignore.head = next;
if (!dmxScreen->ignore.head)
dmxScreen->ignore.tail = &dmxScreen->ignore.head;
}
else
break;
}
}
static Bool
dmxShouldIgnore (DMXScreenInfo *dmxScreen,
unsigned long sequence)
{
dmxDiscardIgnore (dmxScreen, sequence);
if (!dmxScreen->ignore.head)
return FALSE;
return dmxScreen->ignore.head->sequence == sequence;
}
2008-07-31 15:00:31 -04:00
static Bool
dmxScreenEventCheckExpose (ScreenPtr pScreen,
xcb_generic_event_t *event)
{
2008-07-31 15:00:31 -04:00
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
xcb_expose_event_t *xexpose = (xcb_expose_event_t *) event;
WindowPtr pChild0, pChildN;
2008-07-31 15:00:31 -04:00
if ((event->response_type & ~0x80) != XCB_EXPOSE)
return FALSE;
2008-07-31 15:00:31 -04:00
if (dmxShouldIgnore (dmxScreen, xexpose->sequence))
return TRUE;
2008-07-31 15:00:31 -04:00
pChild0 = WindowTable[0];
pChildN = WindowTable[pScreen->myNum];
2008-07-31 15:00:31 -04:00
for (;;)
{
dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pChildN);
2008-07-31 15:00:31 -04:00
if (pWinPriv->window == xexpose->window)
break;
2008-07-31 15:00:31 -04:00
if (pChild0->firstChild)
{
assert (pChildN->firstChild);
pChild0 = pChild0->firstChild;
pChildN = pChildN->firstChild;
continue;
}
2008-07-31 15:00:31 -04:00
while (!pChild0->nextSib && (pChild0 != WindowTable[0]))
{
assert (!pChildN->nextSib &&
(pChildN != WindowTable[pScreen->myNum]));
pChild0 = pChild0->parent;
pChildN = pChildN->parent;
}
2008-07-31 15:00:31 -04:00
if (pChild0 == WindowTable[0])
{
assert (pChildN == WindowTable[pScreen->myNum]);
break;
}
2008-07-31 15:00:31 -04:00
pChild0 = pChild0->nextSib;
pChildN = pChildN->nextSib;
}
2008-07-31 15:00:31 -04:00
if (pChild0)
{
RegionRec region;
BoxRec box;
2008-07-31 15:00:31 -04:00
box.x1 = pChild0->drawable.x + xexpose->x;
box.y1 = pChild0->drawable.y + xexpose->y;
box.x2 = box.x1 + xexpose->width;
box.y2 = box.y1 + xexpose->height;
2008-07-31 15:00:31 -04:00
REGION_INIT (screenInfo.screens[0], &region, &box, 1);
(*pScreen->WindowExposures) (pChild0, &region, NullRegion);
REGION_UNINIT (screenInfo.screens[0], &region);
}
2008-07-31 15:00:31 -04:00
return TRUE;
}
static Bool
2008-07-31 15:00:31 -04:00
dmxScreenEventCheckManageWindow (ScreenPtr pScreen,
xcb_generic_event_t *event)
{
2008-07-31 15:00:31 -04:00
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
WindowPtr pChild = WindowTable[pScreen->myNum];
Window xWindow;
#ifdef PANORAMIX
PanoramiXRes *win = NULL;
WindowPtr pWin;
#endif
2008-07-31 15:00:31 -04:00
xcb_circulate_request_event_t *xcirculaterequest =
(xcb_circulate_request_event_t *) event;
xcb_configure_request_event_t *xconfigurerequest =
(xcb_configure_request_event_t *) event;
xcb_map_request_event_t *xmaprequest =
(xcb_map_request_event_t *) event;
xcb_client_message_event_t *xclient =
(xcb_client_message_event_t *) event;
switch (event->response_type & ~0x80) {
case XCB_CIRCULATE_REQUEST:
xWindow = xcirculaterequest->window;
break;
2008-07-31 15:00:31 -04:00
case XCB_CONFIGURE_REQUEST:
xWindow = xconfigurerequest->window;
break;
2008-07-31 15:00:31 -04:00
case XCB_MAP_REQUEST:
xWindow = xmaprequest->window;
break;
2008-07-31 15:00:31 -04:00
case XCB_CLIENT_MESSAGE:
xWindow = xclient->window;
break;
default:
return FALSE;
}
2008-07-31 15:00:31 -04:00
for (;;)
2008-07-10 04:59:24 -04:00
{
2008-07-31 15:00:31 -04:00
dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pChild);
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
if (pWinPriv->window == xWindow)
2008-07-10 04:59:24 -04:00
{
#ifdef PANORAMIX
2008-07-31 15:00:31 -04:00
if (!noPanoramiXExtension)
win = PanoramiXFindIDByScrnum (XRT_WINDOW,
pChild->drawable.id,
pScreen->myNum);
#endif
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
break;
}
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
while (!pChild->nextSib &&
(pChild != WindowTable[pScreen->myNum]))
pChild = pChild->parent;
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
if (pChild == WindowTable[pScreen->myNum])
break;
2008-07-31 15:00:31 -04:00
pChild = pChild->nextSib;
}
if (pChild
#ifdef PANORAMIX
2008-07-31 15:00:31 -04:00
&& win
#endif
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
)
{
XID vlist[8];
Atom type;
int mask, i = 0;
int status = Success;
xEvent x;
switch (event->response_type & ~0x80) {
case XCB_CIRCULATE_REQUEST:
vlist[0] = None;
if (xcirculaterequest->place == XCB_PLACE_ON_TOP)
vlist[1] = Above;
else
vlist[1] = Below;
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
int j;
FOR_NSCREENS_FORWARD(j) {
if (dixLookupWindow (&pWin,
win->info[j].id,
serverClient,
DixReadAccess) == Success)
status |= ConfigureWindow (pWin,
CWSibling |
CWStackMode,
vlist,
serverClient);
2008-07-10 04:59:24 -04:00
}
2008-07-31 15:00:31 -04:00
}
else
#endif
status = ConfigureWindow (pChild,
CWSibling | CWStackMode,
vlist,
serverClient);
break;
case XCB_CONFIGURE_REQUEST:
mask = xconfigurerequest->value_mask;
if (mask & (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y))
{
vlist[i++] = xconfigurerequest->x;
vlist[i++] = xconfigurerequest->y;
}
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
if (mask & (XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT))
{
vlist[i++] = xconfigurerequest->width;
vlist[i++] = xconfigurerequest->height;
}
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
if (mask & XCB_CONFIG_WINDOW_BORDER_WIDTH)
vlist[i++] = xconfigurerequest->border_width;
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
if (mask & XCB_CONFIG_WINDOW_SIBLING)
{
/* ignore stacking requests with sibling */
if (xconfigurerequest->sibling == None)
vlist[i++] = None;
else
mask &= ~(XCB_CONFIG_WINDOW_SIBLING |
XCB_CONFIG_WINDOW_STACK_MODE);
2008-07-10 04:59:24 -04:00
}
2008-07-31 15:00:31 -04:00
if (mask & XCB_CONFIG_WINDOW_STACK_MODE)
vlist[i++] = xconfigurerequest->stack_mode;
#ifdef PANORAMIX
2008-07-31 15:00:31 -04:00
if (!noPanoramiXExtension)
{
int j;
FOR_NSCREENS_FORWARD(j) {
if (dixLookupWindow (&pWin,
win->info[j].id,
serverClient,
DixReadAccess) == Success)
status |= ConfigureWindow (pWin,
mask,
vlist,
serverClient);
}
}
else
#endif
2008-07-31 15:00:31 -04:00
status = ConfigureWindow (pChild,
mask,
vlist,
serverClient);
break;
case XCB_MAP_REQUEST:
2008-07-10 04:59:24 -04:00
#ifdef PANORAMIX
2008-07-31 15:00:31 -04:00
if (!noPanoramiXExtension)
{
int j;
FOR_NSCREENS_FORWARD(j) {
if (dixLookupWindow (&pWin,
win->info[j].id,
serverClient,
DixReadAccess) == Success)
status |= MapWindow (pWin, serverClient);
}
}
else
#endif
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
status = MapWindow (pChild, serverClient);
break;
case XCB_CLIENT_MESSAGE:
x.u.u.type = ClientMessage | 0x80;
x.u.u.detail = xclient->format;
x.u.clientMessage.window = pChild->drawable.id;
2008-08-02 11:07:58 -04:00
type = dmxAtom (dmxScreen, xclient->type);
2008-07-31 15:00:31 -04:00
switch (xclient->format) {
case 8:
x.u.clientMessage.u.b.type = type;
for (i = 0; i < 20; i++)
x.u.clientMessage.u.b.bytes[i] = xclient->data.data8[i];
break;
case 16:
x.u.clientMessage.u.s.type = type;
x.u.clientMessage.u.s.shorts0 = xclient->data.data16[0];
x.u.clientMessage.u.s.shorts1 = xclient->data.data16[1];
x.u.clientMessage.u.s.shorts2 = xclient->data.data16[2];
x.u.clientMessage.u.s.shorts3 = xclient->data.data16[3];
x.u.clientMessage.u.s.shorts4 = xclient->data.data16[4];
x.u.clientMessage.u.s.shorts5 = xclient->data.data16[5];
x.u.clientMessage.u.s.shorts6 = xclient->data.data16[6];
x.u.clientMessage.u.s.shorts7 = xclient->data.data16[7];
x.u.clientMessage.u.s.shorts8 = xclient->data.data16[8];
x.u.clientMessage.u.s.shorts9 = xclient->data.data16[9];
break;
case 32:
x.u.clientMessage.u.l.type = type;
x.u.clientMessage.u.l.longs0 = xclient->data.data32[0];
x.u.clientMessage.u.l.longs1 = xclient->data.data32[1];
x.u.clientMessage.u.l.longs2 = xclient->data.data32[2];
x.u.clientMessage.u.l.longs3 = xclient->data.data32[3];
x.u.clientMessage.u.l.longs4 = xclient->data.data32[4];
break;
}
/* client messages are always forwarded to the root
window as there's no way for us to know which
windows they were originally intended for */
pWin = WindowTable[pScreen->myNum];
#ifdef PANORAMIX
2008-07-31 15:00:31 -04:00
if (!noPanoramiXExtension)
{
x.u.clientMessage.window = win->info[0].id;
pWin = WindowTable[0];
}
#endif
2008-07-31 15:00:31 -04:00
DeliverEventsToWindow (PickPointer (serverClient),
pWin,
&x,
1,
SubstructureRedirectMask |
SubstructureNotifyMask,
NullGrab, 0);
break;
}
2008-07-10 04:59:24 -04:00
2008-07-31 15:00:31 -04:00
if (status != Success)
dmxLog (dmxWarning,
"dmxScreenManage: failed to handle "
"request type %d\n",
event->response_type & ~0x80);
}
else
{
XWindowChanges xwc;
switch (event->response_type & ~0x80) {
case XCB_CIRCULATE_REQUEST:
XLIB_PROLOGUE (dmxScreen);
if (xcirculaterequest->place == XCB_PLACE_ON_TOP)
XRaiseWindow (dmxScreen->beDisplay,
xcirculaterequest->window);
2008-07-10 04:59:24 -04:00
else
2008-07-31 15:00:31 -04:00
XLowerWindow (dmxScreen->beDisplay,
xcirculaterequest->window);
XLIB_EPILOGUE (dmxScreen);
break;
case XCB_CONFIGURE_REQUEST:
xwc.x = xconfigurerequest->x;
xwc.y = xconfigurerequest->y;
xwc.width = xconfigurerequest->width;
xwc.height = xconfigurerequest->height;
xwc.border_width = xconfigurerequest->border_width;
xwc.sibling = xconfigurerequest->sibling;
xwc.stack_mode = xconfigurerequest->stack_mode;
XLIB_PROLOGUE (dmxScreen);
XConfigureWindow (dmxScreen->beDisplay,
xconfigurerequest->window,
xconfigurerequest->value_mask,
&xwc);
XLIB_EPILOGUE (dmxScreen);
break;
case XCB_MAP_REQUEST:
XLIB_PROLOGUE (dmxScreen);
XMapWindow (dmxScreen->beDisplay, xmaprequest->window);
XLIB_EPILOGUE (dmxScreen);
break;
case XCB_CLIENT_MESSAGE:
break;
2008-07-10 04:59:24 -04:00
}
}
2008-07-31 15:00:31 -04:00
return TRUE;
}
static Bool
dmxScreenEventCheckIgnore (ScreenPtr pScreen,
xcb_generic_event_t *event)
{
switch (event->response_type & ~0x80) {
case XCB_MAPPING_NOTIFY:
return TRUE;
default:
break;
}
return FALSE;
}
static void
dmxScreenCheckForIOError (ScreenPtr pScreen)
2008-07-31 15:00:31 -04:00
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
if (xcb_connection_has_error (dmxScreen->connection))
{
int i;
dmxScreen->alive = FALSE;
dmxLogOutput (dmxScreen, "Detected broken connection\n");
2008-07-31 15:00:31 -04:00
dmxDetachScreen (pScreen->myNum);
for (i = 0; i < dmxNumScreens; i++)
if (i != pScreen->myNum && dmxScreens[i].beDisplay)
break;
if (i == dmxNumScreens)
dmxLog (dmxFatal, "No back-end server connection, "
"giving up\n");
}
2008-07-10 04:59:24 -04:00
}
void
dmxBEDispatch (ScreenPtr pScreen)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
xcb_generic_event_t *event;
xcb_generic_error_t *error;
void *reply;
2008-08-02 08:39:11 -04:00
dmxScreen->inDispatch++;
while ((event = xcb_poll_for_event (dmxScreen->connection)))
{
if (!dmxScreenEventCheckInput (pScreen, event) &&
!dmxScreenEventCheckManageWindow (pScreen, event) &&
!dmxScreenEventCheckExpose (pScreen, event) &&
#ifdef RANDR
!dmxScreenEventCheckRR (pScreen, event) &&
#endif
!dmxScreenEventCheckIgnore (pScreen, event))
{
dmxLogOutput (dmxScreen, "unhandled event type %d\n",
event->response_type);
}
free (event);
}
while (dmxScreen->request.head &&
xcb_poll_for_reply (dmxScreen->connection,
dmxScreen->request.head->sequence,
(void **) &reply,
&error))
{
static xcb_generic_reply_t _default_rep = { 1 };
DMXSequence *head = dmxScreen->request.head;
xcb_generic_reply_t *rep = &_default_rep;
if (error)
rep = (xcb_generic_reply_t *) error;
if (reply)
rep = (xcb_generic_reply_t *) reply;
2008-08-02 08:39:11 -04:00
dmxScreen->request.head = head->next;
if (!dmxScreen->request.head)
dmxScreen->request.tail = &dmxScreen->request.head;
2008-08-01 21:53:25 -04:00
if (!dmxScreenReplyCheckSync (pScreen, head->sequence, rep) &&
!dmxScreenReplyCheckInput (pScreen, head->sequence, rep))
{
/* error response */
if (rep->response_type == 0)
dmxLogOutput (dmxScreen, "error %d sequence %d\n",
((xcb_generic_error_t *) rep)->error_code,
head->sequence);
}
if (reply)
free (reply);
if (error)
free (error);
free (head);
}
2008-08-02 08:39:11 -04:00
dmxScreen->inDispatch--;
}
static void
dmxScreenBlockHandler (pointer blockData,
OSTimePtr pTimeout,
pointer pReadMask)
{
2008-07-31 15:00:31 -04:00
ScreenPtr pScreen = (ScreenPtr) blockData;
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
2008-07-31 15:00:31 -04:00
if (dmxScreen->beDisplay)
{
xcb_flush (dmxScreen->connection);
dmxScreenCheckForIOError (pScreen);
2008-07-31 15:00:31 -04:00
}
}
static void
dmxScreenWakeupHandler (pointer blockData,
int result,
pointer pReadMask)
{
2008-07-31 15:00:31 -04:00
ScreenPtr pScreen = (ScreenPtr) blockData;
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
if (dmxScreen->beDisplay)
dmxBEDispatch (pScreen);
}
2008-06-10 16:06:38 -04:00
static void
dmxHandleExposures (WindowPtr pWin)
{
WindowPtr pChild;
ValidatePtr val;
ScreenPtr pScreen;
WindowExposuresProcPtr WindowExposures;
pScreen = pWin->drawable.pScreen;
pChild = pWin;
WindowExposures = pChild->drawable.pScreen->WindowExposures;
while (1)
{
if ( (val = pChild->valdata) )
{
REGION_UNINIT(pScreen, &val->after.borderExposed);
(*WindowExposures)(pChild, &val->after.exposed, NullRegion);
REGION_UNINIT(pScreen, &val->after.exposed);
xfree(val);
pChild->valdata = (ValidatePtr)NULL;
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pWin))
pChild = pChild->parent;
if (pChild == pWin)
break;
pChild = pChild->nextSib;
}
}
/** Initialize screen number \a idx. */
Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[])
{
DMXScreenInfo *dmxScreen = &dmxScreens[idx];
int i, j;
if (dmxGeneration != serverGeneration) {
/* Allocate font private index */
dmxFontPrivateIndex = AllocateFontPrivateIndex();
if (dmxFontPrivateIndex == -1)
return FALSE;
dmxGeneration = serverGeneration;
}
dmxScreen->ignore.head = NULL;
dmxScreen->ignore.tail = &dmxScreen->ignore.head;
dmxScreen->request.head = NULL;
dmxScreen->request.tail = &dmxScreen->request.head;
2008-06-03 18:18:04 -04:00
#ifdef RANDR
dmxScreen->beRandr = FALSE;
dmxScreen->beRandrPending = FALSE;
#endif
if (dmxShadowFB) {
dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth,
dmxScreen->scrnHeight,
dmxScreen->beBPP);
} else {
if (!dmxInitGC(pScreen)) return FALSE;
if (!dmxInitWindow(pScreen)) return FALSE;
if (!dmxInitPixmap(pScreen)) return FALSE;
if (!dmxInitCursor(pScreen)) return FALSE;
}
/*
* Initalise the visual types. miSetVisualTypesAndMasks() requires
* that all of the types for each depth be collected together. It's
* intended for slightly different usage to what we would like here.
* Maybe a miAddVisualTypeAndMask() function will be added to make
* things easier here.
*/
2008-06-03 18:18:04 -04:00
if (dmxScreen->beDisplay)
{
for (i = 0; i < dmxScreen->beNumDepths; i++) {
int depth;
int visuals = 0;
int bitsPerRgb = 0;
int preferredClass = -1;
Pixel redMask = 0;
Pixel greenMask = 0;
Pixel blueMask = 0;
depth = dmxScreen->beDepths[i];
for (j = 0; j < dmxScreen->beNumVisuals; j++) {
XVisualInfo *vi;
vi = &dmxScreen->beVisuals[j];
if (vi->depth == depth) {
/* Assume the masks are all the same. */
visuals |= (1 << vi->class);
bitsPerRgb = vi->bits_per_rgb;
redMask = vi->red_mask;
greenMask = vi->green_mask;
blueMask = vi->blue_mask;
if (j == dmxScreen->beDefVisualIndex) {
preferredClass = vi->class;
}
}
}
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
/* avoid additional DirectColor visuals for better
back-end server support */
if (preferredClass != DirectColor)
visuals &= ~(1 << DirectColor);
}
#endif
2008-06-03 18:18:04 -04:00
miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb,
preferredClass,
redMask, greenMask, blueMask);
}
}
else
{
for (i = 0; i < dmxScreens[0].beNumDepths; i++) {
int depth;
int visuals = 0;
int bitsPerRgb = 0;
int preferredClass = -1;
Pixel redMask = 0;
Pixel greenMask = 0;
Pixel blueMask = 0;
depth = dmxScreens[0].beDepths[i];
for (j = 0; j < dmxScreens[0].beNumVisuals; j++) {
XVisualInfo *vi;
vi = &dmxScreens[0].beVisuals[j];
if (vi->depth == depth) {
/* Assume the masks are all the same. */
visuals |= (1 << vi->class);
bitsPerRgb = vi->bits_per_rgb;
redMask = vi->red_mask;
greenMask = vi->green_mask;
blueMask = vi->blue_mask;
if (j == dmxScreens[0].beDefVisualIndex) {
preferredClass = vi->class;
}
}
}
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
/* avoid additional DirectColor visuals for better
back-end server support */
if (preferredClass != DirectColor)
visuals &= ~(1 << DirectColor);
}
#endif
2008-06-03 18:18:04 -04:00
miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb,
preferredClass,
redMask, greenMask, blueMask);
}
}
fbScreenInit(pScreen,
dmxShadowFB ? dmxScreen->shadow : NULL,
dmxScreen->scrnWidth,
dmxScreen->scrnHeight,
dmxScreen->beXDPI,
2008-06-03 18:18:04 -04:00
dmxScreen->beYDPI,
dmxScreen->scrnWidth,
dmxScreen->beBPP);
#ifdef MITSHM
2008-08-04 17:39:48 -04:00
ShmRegisterDmxFuncs (pScreen);
#endif
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
for (i = 0; i < pScreen->numVisuals; i++)
if (pScreen->visuals[i].ColormapEntries > 256)
pScreen->visuals[i].ColormapEntries = 256;
}
#endif
#ifdef RENDER
(void)dmxPictureInit(pScreen, 0, 0);
#endif
2008-06-03 18:18:04 -04:00
#ifdef RANDR
2008-06-04 13:11:33 -04:00
if (dmxScreen->beDisplay)
{
int major, minor, status = 0;
XLIB_PROLOGUE (dmxScreen);
status = XRRQueryVersion (dmxScreen->beDisplay, &major, &minor);
XLIB_EPILOGUE (dmxScreen);
if (status)
{
if (major > 1 || (major == 1 && minor >= 2))
{
int ignore;
XLIB_PROLOGUE (dmxScreen);
dmxScreen->beRandr =
XRRQueryExtension (dmxScreen->beDisplay,
&dmxScreen->beRandrEventBase,
&ignore);
XLIB_EPILOGUE (dmxScreen);
}
}
}
if (!dmxRRScreenInit (pScreen))
2008-06-03 18:18:04 -04:00
return FALSE;
#endif
2008-07-25 14:23:38 -04:00
#ifdef XV
if (!dmxXvScreenInit (pScreen))
return FALSE;
#endif
if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL))
return FALSE;
miInitializeBackingStore(pScreen);
if (dmxShadowFB) {
miDCInitialize(pScreen, &dmxPointerCursorFuncs);
} else {
MAXSCREENSALLOC(dmxCursorGeneration);
if (dmxCursorGeneration[idx] != serverGeneration) {
if (!(miPointerInitialize(pScreen,
&dmxPointerSpriteFuncs,
&dmxPointerCursorFuncs,
FALSE)))
return FALSE;
dmxCursorGeneration[idx] = serverGeneration;
}
}
DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen);
DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen);
2008-06-03 18:18:04 -04:00
if (dmxScreen->beDisplay)
dmxBEScreenInit(idx, pScreen);
if (!dmxShadowFB) {
/* Wrap GC functions */
DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
/* Wrap Window functions */
DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
pScreen);
DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
2008-06-10 16:06:38 -04:00
DMX_WRAP(HandleExposures, dmxHandleExposures, dmxScreen, pScreen);
DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
DMX_WRAP(ModifyPixmapHeader, dmxModifyPixmapHeader, dmxScreen, pScreen);
2008-06-03 18:18:04 -04:00
DMX_WRAP(SetWindowPixmap, dmxSetWindowPixmap, dmxScreen, pScreen);
/* Wrap Image functions */
DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen);
2008-06-03 18:27:49 -04:00
DMX_WRAP(GetSpans, NULL, dmxScreen, pScreen);
/* Wrap Pixmap functions */
DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen);
/* Wrap Font functions */
DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen);
DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen);
/* Wrap Colormap functions */
DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
/* Wrap Shape functions */
DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
}
if (!dmxCreateDefColormap(pScreen))
return FALSE;
RegisterBlockAndWakeupHandlers (dmxScreenBlockHandler,
dmxScreenWakeupHandler,
pScreen);
return TRUE;
}
/** Close the \a pScreen resources on the back-end server. */
void dmxBECloseScreen(ScreenPtr pScreen)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
int i;
/* Restore the back-end screen-saver and DPMS state. */
dmxDPMSTerm(dmxScreen);
/* Free the screen resources */
2008-06-03 18:18:04 -04:00
XLIB_PROLOGUE (dmxScreen);
XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor);
2008-06-03 18:18:04 -04:00
XLIB_EPILOGUE (dmxScreen);
dmxScreen->noCursor = (Cursor)0;
if (!dmxScreen->beUseRoot)
{
XLIB_PROLOGUE (dmxScreen);
XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
XLIB_EPILOGUE (dmxScreen);
}
dmxScreen->scrnWin = (Window)0;
if (dmxShadowFB) {
/* Free the shadow GC and image assocated with the back-end server */
2008-06-03 18:18:04 -04:00
XLIB_PROLOGUE (dmxScreen);
XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC);
2008-06-03 18:18:04 -04:00
XLIB_EPILOGUE (dmxScreen);
dmxScreen->shadowGC = NULL;
XFree(dmxScreen->shadowFBImage);
dmxScreen->shadowFBImage = NULL;
} else {
/* Free the default drawables */
for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
2008-06-03 18:18:04 -04:00
XLIB_PROLOGUE (dmxScreen);
XFreePixmap(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i]);
2008-06-03 18:18:04 -04:00
XLIB_EPILOGUE (dmxScreen);
dmxScreen->scrnDefDrawables[i] = (Drawable)0;
}
}
/* Free resources allocated during initialization (in dmxinit.c) */
for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
2008-06-03 18:18:04 -04:00
{
XLIB_PROLOGUE (dmxScreen);
XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]);
2008-06-03 18:18:04 -04:00
XLIB_EPILOGUE (dmxScreen);
}
xfree(dmxScreen->beDefColormaps);
dmxScreen->beDefColormaps = NULL;
#if 0
/* Do not free visuals, depths and pixmap formats here. Free them
* in dmxCloseScreen() instead -- see comment below. */
XFree(dmxScreen->beVisuals);
dmxScreen->beVisuals = NULL;
XFree(dmxScreen->beDepths);
dmxScreen->beDepths = NULL;
XFree(dmxScreen->bePixmapFormats);
dmxScreen->bePixmapFormats = NULL;
#endif
#ifdef GLXEXT
if (dmxScreen->glxVisuals) {
XFree(dmxScreen->glxVisuals);
dmxScreen->glxVisuals = NULL;
dmxScreen->numGlxVisuals = 0;
}
#endif
/* Close display */
dmxCloseDisplay (dmxScreen);
dmxScreen->beDisplay = NULL;
dmxClearQueue (&dmxScreen->request);
dmxClearQueue (&dmxScreen->ignore);
}
/** Close screen number \a idx. */
Bool dmxCloseScreen(int idx, ScreenPtr pScreen)
{
DMXScreenInfo *dmxScreen = &dmxScreens[idx];
/* Reset the proc vectors */
if (idx == 0) {
2008-07-26 02:44:37 -04:00
#ifdef COMPOSITE
if (!noCompositeExtension)
dmxResetComposite();
#endif
#ifdef RENDER
2008-07-26 02:44:37 -04:00
if (!noRenderExtension)
dmxResetRender();
2008-08-04 17:29:21 -04:00
#endif
#ifdef MITSHM
dmxResetShm();
#endif
2008-07-26 02:44:37 -04:00
dmxResetGrabs();
dmxResetProps();
dmxResetFonts();
}
if (dmxShadowFB) {
/* Free the shadow framebuffer */
xfree(dmxScreen->shadow);
} else {
/* Unwrap Shape functions */
DMX_UNWRAP(SetShape, dmxScreen, pScreen);
/* Unwrap the pScreen functions */
DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
2008-06-10 16:06:38 -04:00
DMX_UNWRAP(HandleExposures, dmxScreen, pScreen);
DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
DMX_UNWRAP(ModifyPixmapHeader, dmxScreen, pScreen);
DMX_UNWRAP(SetWindowPixmap, dmxScreen, pScreen);
DMX_UNWRAP(GetImage, dmxScreen, pScreen);
DMX_UNWRAP(GetSpans, dmxScreen, pScreen);
DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen);
DMX_UNWRAP(RealizeFont, dmxScreen, pScreen);
DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen);
DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
}
DMX_UNWRAP(SaveScreen, dmxScreen, pScreen);
if (dmxScreen->beDisplay) {
dmxBECloseScreen(pScreen);
#if 1
/* Free visuals, depths and pixmap formats here so that they
* won't be freed when a screen is detached, thereby allowing
* the screen to be reattached to be compared to the one
* previously removed.
*/
XFree(dmxScreen->beVisuals);
dmxScreen->beVisuals = NULL;
XFree(dmxScreen->beDepths);
dmxScreen->beDepths = NULL;
XFree(dmxScreen->bePixmapFormats);
dmxScreen->bePixmapFormats = NULL;
#endif
}
DMX_UNWRAP(CloseScreen, dmxScreen, pScreen);
return pScreen->CloseScreen(idx, pScreen);
}
static Bool dmxSaveScreen(ScreenPtr pScreen, int what)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
if (dmxScreen->beDisplay) {
switch (what) {
case SCREEN_SAVER_OFF:
case SCREEN_SAVER_FORCER:
2008-06-03 18:18:04 -04:00
XLIB_PROLOGUE (dmxScreen);
XResetScreenSaver(dmxScreen->beDisplay);
2008-06-03 18:18:04 -04:00
XLIB_EPILOGUE (dmxScreen);
dmxSync(dmxScreen, FALSE);
break;
case SCREEN_SAVER_ON:
case SCREEN_SAVER_CYCLE:
2008-06-03 18:18:04 -04:00
XLIB_PROLOGUE (dmxScreen);
XActivateScreenSaver(dmxScreen->beDisplay);
2008-06-03 18:18:04 -04:00
XLIB_EPILOGUE (dmxScreen);
dmxSync(dmxScreen, FALSE);
break;
}
}
return TRUE;
}
Bool
dmxAddSequence (DMXQueue *q,
unsigned long sequence)
{
DMXSequence *s;
s = malloc (sizeof (DMXSequence));
if (!s)
return FALSE;
s->sequence = sequence;
s->next = 0;
*(q->tail) = s;
q->tail = &s->next;
return TRUE;
}
void
dmxClearQueue (DMXQueue *q)
{
while (q->head)
{
DMXSequence *head = q->head;
q->head = head->next;
free (head);
}
q->tail = &q->head;
}