diff options
Diffstat (limited to 'dix')
-rw-r--r-- | dix/dispatch.c | 172 | ||||
-rw-r--r-- | dix/events.c | 543 | ||||
-rw-r--r-- | dix/window.c | 181 |
3 files changed, 665 insertions, 231 deletions
diff --git a/dix/dispatch.c b/dix/dispatch.c index 08d523441..14b3df38a 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.4 2004/07/29 18:43:58 stukreit Exp $ */ +/* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.5.14.2 2005/01/16 00:09:53 deronj Exp $ */ /* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ /************************************************************ @@ -78,6 +78,138 @@ Equipment Corporation. /* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.32 2003/11/10 18:21:45 tsi Exp $ */ +#if defined(LG3D) && defined(DISPATCH_DEBUG) +int printprocs = 0; +int proc_num = 0; + +typedef char *ProcNameString; + +static ProcNameString procNames[] = { +"", +"CreateWindow", +"ChangeWindowAttributes", +"GetWindowAttributes", +"DestroyWindow", +"DestroySubwindows", +"ChangeSaveSet", +"ReparentWindow", +"MapWindow", +"MapSubwindows", +"UnmapWindow", +"UnmapSubwindows", +"ConfigureWindow", +"CirculateWindow", +"GetGeometry", +"QueryTree", +"InternAtom", +"GetAtomName", +"ChangeProperty", +"DeleteProperty", +"GetProperty", +"ListProperties", +"SetSelectionOwner", +"GetSelectionOwner", +"ConvertSelection", +"SendEvent", +"GrabPointer", +"UngrabPointer", +"GrabButton", +"UngrabButton", +"ChangeActivePointerGrab", +"GrabKeyboard", +"UngrabKeyboard", +"GrabKey", +"UngrabKey", +"AllowEvents", +"GrabServer", +"UngrabServer", +"QueryPointer", +"GetMotionEvents", +"TranslateCoords", +"WarpPointer", +"SetInputFocus", +"GetInputFocus", +"QueryKeymap", +"OpenFont", +"CloseFont", +"QueryFont", +"QueryTextExtents", +"ListFonts", +"ListFontsWithInfo", +"SetFontPath", +"GetFontPath", +"CreatePixmap", +"FreePixmap", +"CreateGC", +"ChangeGC", +"CopyGC", +"SetDashes", +"SetClipRectangles", +"FreeGC", +"ClearArea", +"CopyArea", +"CopyPlane", +"PolyPoint", +"PolyLine", +"PolySegment", +"PolyRectangle", +"PolyArc", +"FillPoly", +"PolyFillRectangle", +"PolyFillArc", +"PutImage", +"GetImage", +"PolyText8", +"PolyText16", +"ImageText8", +"ImageText16", +"CreateColormap", +"FreeColormap", +"CopyColormapAndFree", +"InstallColormap", +"UninstallColormap", +"ListInstalledColormaps", +"AllocColor", +"AllocNamedColor", +"AllocColorCells", +"AllocColorPlanes", +"FreeColors", +"StoreColors", +"StoreNamedColor", +"QueryColors", +"LookupColor", +"CreateCursor", +"CreateGlyphCursor", +"FreeCursor", +"RecolorCursor", +"QueryBestSize", +"QueryExtension", +"ListExtensions", +"ChangeKeyboardMapping", +"GetKeyboardMapping", +"ChangeKeyboardControl", +"GetKeyboardControl", +"Bell", +"ChangePointerControl", +"GetPointerControl", +"SetScreenSaver", +"GetScreenSaver", +"ChangeHosts", +"ListHosts", +"SetAccessControl", +"SetCloseDownMode", +"KillClient", +"RotateProperties", +"ForceScreenSaver", +"SetPointerMapping", +"GetPointerMapping", +"SetModifierMapping", +"GetModifierMapping" +}; + +#define NUM_PROC_NAMES (sizeof(procNames)/sizeof(char*)) +#endif /* LG3D && DISPATCH_DEBUG */ + #ifdef PANORAMIX_DEBUG #include <stdio.h> int ProcInitialConnection(); @@ -449,6 +581,20 @@ Dispatch(void) client->requestLog[client->requestLogIndex] = MAJOROP; client->requestLogIndex++; #endif + +#if defined(LG3D) && defined(DISPATCH_DEBUG) + if (printprocs) { + char *procName; + if (MAJOROP >= NUM_PROC_NAMES) { + + procName = "Unknown"; + } else { + procName = procNames[MAJOROP]; + } + ErrorF("dispatcher: %d, client = %d, op = %d (%s)\n", ++proc_num, client->index, MAJOROP, procName); + } +#endif /* LG3D && DISPATCH_DEBUG */ + if (result > (maxBigRequestSize << 2)) result = BadLength; else @@ -855,6 +1001,9 @@ ProcGetGeometry(client) return(client->noClientException); } +#ifdef LG3D +#include "../Xext/lgeint.h" +#endif /* LG3D */ int ProcQueryTree(client) @@ -878,6 +1027,27 @@ ProcQueryTree(client) reply.parent = pWin->parent->drawable.id; else reply.parent = (Window)None; + +#ifdef LG3D + /* + ** HACK ALERT: + ** Bug fix for lg3d bug 213. The emacs Optional menu displays + ** tooltips for its entries. The emacs code (or possibly the + ** Xaw3d code which provides the tooltips) cannot handle it + ** when these tooltips are reparented to the PRW; emacs takes + ** a segv. As a short-term workaround we will lie to the client + ** and say that a window is still parented off the root window + ** if it is an override redirect window that has been reparented + ** to the PRW. + ** + ** TODO: someday: it would be nice to fix the client bug and + ** get rid of this hack. + */ + if (wovRedirLieAboutRootParent(pWin)) { + reply.parent = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + } +#endif /* LG3D */ + pHead = RealChildHead(pWin); for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) numChildren++; diff --git a/dix/events.c b/dix/events.c index d75a1e062..33392af8a 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.6 2004/08/09 02:08:35 kem Exp $ */ +/* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.6.4.1.10.2 2005/01/12 00:37:52 deronj Exp $ */ /* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */ /************************************************************ @@ -151,11 +151,21 @@ xEvent *xeviexE; #include "dispatch.h" #ifdef LG3D + +/* Enable one or the other, but not both */ +#undef LG3D_EVENT_TEST_LATENCY +#undef LG3D_EVENT_TEST_THROUGHPUT + #include "damagewire.h" #include "../Xext/lgeint.h" extern int lgeTryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, Mask filter, GrabPtr grab); +extern WindowPtr XYToSubWindow (WindowPtr pWin, int x, int y, + int *xWinRel, int *yWinRel); + +extern Bool PointInBorderSize(WindowPtr pWin, int x, int y); + #endif /* LG3D */ #define EXTENSION_EVENT_BASE 64 @@ -331,33 +341,6 @@ static CARD8 criticalEvents[32] = 0x7c /* key and button events */ }; -#ifdef LG3D - -#define LG3D_DECLARE_WINDOW() \ - WindowPtr pEventWin = NULL - -#define LG3D_GET_WINDOW(e) \ - if ((e) != NULL) { \ - pEventWin = (WindowPtr) LookupIDByType((e)->u.keyButtonPointer.event, RT_WINDOW); \ - } - -/* -** In LG Event Mode the sprite hotspot is calculated by taking the -** event window local coordinates and converting them to screen -** absolute. -** -*/ -#define LG3D_CALC_SPRITE_HOTXY(e) \ - sprite.hot.x = (e)->u.keyButtonPointer.rootX; \ - sprite.hot.y = (e)->u.keyButtonPointer.rootY; - -extern WindowPtr XYToSubWindow (WindowPtr pWin, int x, int y, - int *xWinRel, int *yWinRel); - -extern Bool PointInBorderSize(WindowPtr pWin, int x, int y); - -#endif /* LG3D */ - #ifdef PANORAMIX static void ConfineToShape(RegionPtr shape, int *px, int *py); @@ -498,19 +481,8 @@ XineramaCheckVirtualMotion( if (qe) { sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ -#ifdef LG3D - if (lgeDisplayServerIsAlive) { - LG3D_DECLARE_WINDOW(); - LG3D_GET_WINDOW(qe->event); - LG3D_CALC_SPRITE_HOTXY(qe->event); - } else { - sprite.hot.x = qe->event->u.keyButtonPointer.rootX; - sprite.hot.y = qe->event->u.keyButtonPointer.rootY; - } -#else sprite.hot.x = qe->event->u.keyButtonPointer.rootX; sprite.hot.y = qe->event->u.keyButtonPointer.rootY; -#endif /* LG3D */ pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : NullWindow; } @@ -678,22 +650,18 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) static void XineramaChangeToCursor(CursorPtr cursor) { -#ifdef LG3D - if (plgeDisplayServerForceThisCursor != NULL) { - (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, - plgeDisplayServerForceThisCursor); - return; - } -#endif /* LG3D */ - +#ifndef LG3D if (cursor != sprite.current) { +#endif /* ! LG3D */ if ((sprite.current->bits->xhot != cursor->bits->xhot) || (sprite.current->bits->yhot != cursor->bits->yhot)) XineramaCheckPhysLimits(cursor, FALSE); (*sprite.screen->DisplayCursor)(sprite.screen, cursor); sprite.current = cursor; +#ifndef LG3D } +#endif /* ! LG3D */ } @@ -921,16 +889,10 @@ ChangeToCursor(CursorPtr cursor) } #endif -#ifdef LG3D - if (plgeDisplayServerForceThisCursor != NULL) { - (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, - plgeDisplayServerForceThisCursor); - return; - } -#endif /* LG3D */ - +#ifndef LG3D if (cursor != sprite.current) { +#endif /* ! LG3D */ if ((sprite.current->bits->xhot != cursor->bits->xhot) || (sprite.current->bits->yhot != cursor->bits->yhot)) CheckPhysLimits(cursor, FALSE, sprite.confined, @@ -938,7 +900,9 @@ ChangeToCursor(CursorPtr cursor) (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, cursor); sprite.current = cursor; +#ifndef LG3D } +#endif /* ! LG3D */ } /* returns true if b is a descendent of a */ @@ -973,6 +937,7 @@ PostNewCursor(void) } else win = sprite.win; + for (; win; win = win->parent) if (win->optional && win->optional->cursor != NullCursor) { @@ -1138,9 +1103,8 @@ lgeTryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, int destination; destination = lgeDSCaresAboutEvent (pEvents, &win); - - if (client == NULL /* For XDamageNotify */ || - (destination != SEND_TO_NORMAL_CLIENT && win == lgeGrabAllWindowEvents.window)) { + + if (destination != SEND_TO_NORMAL_CLIENT && win == lgeGrabAllWindowEvents.window) { /* ** Send events to grabbing client client. Use a null grab pointer ** in order to sure that the event isn't eaten by any grabs; we want @@ -1653,6 +1617,7 @@ ProcAllowEvents(client) REQUEST_SIZE_MATCH(xAllowEventsReq); time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) { case ReplayPointer: @@ -1981,20 +1946,66 @@ MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient) return 2; } +#ifdef LG3D + +/* +** Returns true if the event type is one which was generated +** by an input device. These are the only types of events +** which been sent to the Display Server so they are the only +** types of events which have the event field already set. +** +** TODO: this macro does not yet support XINPUT devices. +*/ + +#define EVENT_IS_DEVICE_EVENT(e) \ + ((e)->u.u.type == KeyPress || \ + (e)->u.u.type == KeyRelease || \ + (e)->u.u.type == ButtonPress || \ + (e)->u.u.type == ButtonRelease || \ + (e)->u.u.type == MotionNotify) + +/* Returns True if the event occurred above a 3D object rather than a native window */ +#define EVENT_IS_3D(e) \ + (EVENT_IS_DEVICE_EVENT(e) && (e)->u.keyButtonPointer.event == lgeDisplayServerPRW) + +/* +TODO: it's not clear whether this routine deals with grabs properly. +Must handle the following cases: + 2D event grabbed and forced to go to 2D win + 2D event grabbed and forced to go to 3D win + 3D event grabbed and forced to go to 2D win + 3D event grabbed and forced to go to 3D win +*/ + static void -FixUpEventFromWindow( +lgeFixUpEventFromWindow( xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) { -#ifdef LG3D - Bool isMouseEvent = FALSE; - Window mouseEventWinPrev = 0; -#endif /* LG3D */ + Window eventWindowOld = INVALID; + + /* + ErrorF("Enter FixUpEventFromWindow, event type = %d\n", xE->u.u.type); + if (EVENT_IS_3D(xE)) { + ErrorF("Event is 3D\n"); + } else { + ErrorF("Event is 2D\n"); + } + ErrorF("old event window = %d\n", XE_KBPTR.event); + ErrorF("old child window = %d\n", XE_KBPTR.child); + ErrorF("old eventxy = %d, %d\n", XE_KBPTR.eventX, XE_KBPTR.eventY); + */ + + /* TODO: This is merely an optimization; it is no longer functionally necessary */ + if (EVENT_IS_3D(xE)) { + calcChild = False; + } if (calcChild) { + /*ErrorF("Calculating child\n");*/ WindowPtr w=spriteTrace[spriteTraceGood-1]; /* If the search ends up past the root should the child field be set to none or should the value in the argument be passed @@ -2004,7 +2015,7 @@ FixUpEventFromWindow( while (w) { /* If the source window is same as event window, child should be - none. Don't bother going all all the way back to the root. */ + none. Don't bother going all all the way back to the root. */ if (w == pWin) { @@ -2021,93 +2032,116 @@ FixUpEventFromWindow( } } XE_KBPTR.root = ROOT->drawable.id; -#ifdef LG3D - if (xE->u.u.type == ButtonPress || - xE->u.u.type == ButtonRelease || - xE->u.u.type == MotionNotify) { - isMouseEvent = TRUE; - mouseEventWinPrev = XE_KBPTR.event; + + /* Set event field (only for non-3D events) */ + if (!EVENT_IS_3D(xE)) { + eventWindowOld = XE_KBPTR.event; + XE_KBPTR.event = pWin->drawable.id; + /*ErrorF("new event window = %d\n", XE_KBPTR.event);*/ + } + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + return; } - if (lgeDisplayServerIsAlive && - XE_KBPTR.event == lgeDisplayServerPRW) { + XE_KBPTR.sameScreen = xTrue; + + /* Set various fields (only for non-3D events) */ + if (!EVENT_IS_3D(xE)) { + + XE_KBPTR.child = child; + /*ErrorF("new child window = %d\n", XE_KBPTR.child);*/ /* - ** Event is going to the PRW. - ** Button and motion events already have the event - ** window field set. + ** The only events needing fixup at this point are mouse events + ** where the event window has been changed. */ - if (!isMouseEvent) { - XE_KBPTR.event = pWin->drawable.id; + if ((xE->u.u.type == ButtonPress || + xE->u.u.type == ButtonRelease || + xE->u.u.type == MotionNotify) && + eventWindowOld != XE_KBPTR.event) { + + /* TODO: it would be good to avoid a resource lookup here. Some sort of + caching might optimize this */ + WindowPtr pOuterWin = (WindowPtr) LookupIDByType(eventWindowOld, RT_WINDOW); + if (pOuterWin == NULL) { + /* + ** This can happen if the window has died since the pick on the window + ** occurred. So we don't need to be verbose about it. + ErrorF("Error: FixupEventFromWindow: outer window %d, not found. No XY fix up occuring.\n", + eventWindowOld); + */ + } else { + /* + ** Make the event coords relative to the destination window + ** instead of relative to the outer window. + */ + XE_KBPTR.eventX -= pWin->drawable.x - pOuterWin->drawable.x; + XE_KBPTR.eventY -= pWin->drawable.y - pOuterWin->drawable.y; + /*ErrorF("new eventxy = %d, %d", XE_KBPTR.eventX, XE_KBPTR.eventY);*/ + } } + } +} - } else { - /* - ** Non-LG event mode or the event is going to an - ** X application window. Need to set the event window - ** field to the destination window. - */ - XE_KBPTR.event = pWin->drawable.id; +#endif /* LG3D */ + +static void +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +{ +#ifdef LG3D + if (lgeDisplayServerIsAlive) { + lgeFixUpEventFromWindow(xE, pWin, child, calcChild); + return; } -#else - XE_KBPTR.event = pWin->drawable.id; #endif /* LG3D */ + + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; if (sprite.hot.pScreen == pWin->drawable.pScreen) { XE_KBPTR.sameScreen = xTrue; XE_KBPTR.child = child; -#ifdef LG3D - if (lgeDisplayServerIsAlive) { - if (XE_KBPTR.event == lgeDisplayServerPRW) { - /* - ** Event is going to the PRW. - ** Button and motion events already have the event - ** XY fields set. - */ - if (!isMouseEvent) { - XE_KBPTR.eventX = XE_KBPTR.rootX; - XE_KBPTR.eventY = XE_KBPTR.rootY; - } - } else { - /* - ** Event is going to an X application - ** window. Need to set the window relative event XY for - ** ALL event types. - ** - ** TODO: I don't think this code deals very well with grab cases, - */ - if (!isMouseEvent || mouseEventWinPrev == pWin->drawable.id) { - /* - ** A non-button/motion event (e.g. keypress or enter/leave) - ** or the event occurred in a top-level window. - ** Do nothing. The event coords are already correct. - */ - } else { - /* TODO: it would be good to avoid a resource lookup here */ - WindowPtr pOuterWin = (WindowPtr) LookupIDByType(mouseEventWinPrev, RT_WINDOW); - if (pOuterWin == NULL) { - ErrorF("Error: FixupEventFromWindow: outer window %d, not found. No XY fix up occuring.\n", mouseEventWinPrev); - } else { - /* - ** Make the event coords relative to the destination window - ** instead of relative to the outer window. - */ - XE_KBPTR.eventX -= pWin->drawable.x - pOuterWin->drawable.x; - XE_KBPTR.eventY -= pWin->drawable.y - pOuterWin->drawable.y; - } - } - } - } else { - /* Non-LG event mode */ - XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x; - XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y; - } -#else XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x; XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y; -#endif /* LG3D */ } else { @@ -2320,12 +2354,6 @@ static Bool CheckMotion(xEvent *xE) { WindowPtr prevSpriteWin = sprite.win; -#ifdef LG3D - LG3D_DECLARE_WINDOW(); - if (lgeDisplayServerIsAlive) { - LG3D_GET_WINDOW(xE); - } -#endif /* LG3D */ #ifdef PANORAMIX if(!noPanoramiXExtension) @@ -2339,17 +2367,8 @@ CheckMotion(xEvent *xE) sprite.hot.pScreen = sprite.hotPhys.pScreen; ROOT = WindowTable[sprite.hot.pScreen->myNum]; } -#ifdef LG3D - if (lgeDisplayServerIsAlive) { - LG3D_CALC_SPRITE_HOTXY(xE); - } else { - sprite.hot.x = XE_KBPTR.rootX; - sprite.hot.y = XE_KBPTR.rootY; - } -#else sprite.hot.x = XE_KBPTR.rootX; sprite.hot.y = XE_KBPTR.rootY; -#endif /* LG3D */ if (sprite.hot.x < sprite.physLimits.x1) sprite.hot.x = sprite.physLimits.x1; else if (sprite.hot.x >= sprite.physLimits.x2) @@ -2375,34 +2394,38 @@ CheckMotion(xEvent *xE) } #ifdef LG3D - if (pEventWin == NULL) { - sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); - virtualSprite.hot.x = sprite.hot.x - sprite.win->drawable.x; - virtualSprite.hot.y = sprite.hot.y - sprite.win->drawable.y; - } else { - WindowPtr pSpriteWin; + if (lgeDisplayServerIsAlive) { - /* - ** This is needed to decouple the virtual sprite position from - ** the physical sprite position. - */ - if (pEventWin->drawable.id == lgeDisplayServerPRW) { - pSpriteWin = pEventWin; + if (xE == NULL) { + /* WindowsRestructured case */ + /* TODO: this may change */ + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + virtualSprite.hot.x = sprite.hot.x - sprite.win->drawable.x; + virtualSprite.hot.y = sprite.hot.y - sprite.win->drawable.y; + } else if (XE_KBPTR.event == lgeDisplayServerPRW) { + /* 3D Event */ + sprite.win = pLgeDisplayServerPRWWin; virtualSprite.hot.x = sprite.hot.x; virtualSprite.hot.y = sprite.hot.y; } else { - pSpriteWin = XYToSubWindow(pEventWin, - xE->u.keyButtonPointer.eventX, - xE->u.keyButtonPointer.eventY, - &virtualSprite.hot.x, - &virtualSprite.hot.y); + /* Normal X Event */ + WindowPtr pEventWin = (WindowPtr) LookupIDByType(XE_KBPTR.event, RT_WINDOW); + if (pEventWin == NULL) { + /* This might happen if the window has been destroyed */ + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + virtualSprite.hot.x = sprite.hot.x - sprite.win->drawable.x; + virtualSprite.hot.y = sprite.hot.y - sprite.win->drawable.y; + return TRUE; + } + sprite.win = XYToSubWindow(pEventWin, + XE_KBPTR.eventX, XE_KBPTR.eventY, + &virtualSprite.hot.x, &virtualSprite.hot.y); } + virtualSprite.win = sprite.win; - sprite.win = pSpriteWin; + } else { + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); } - - virtualSprite.win = sprite.win; - #else sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); #endif /* LG3D */ @@ -2432,6 +2455,33 @@ void WindowsRestructured() { (void) CheckMotion((xEvent *)NULL); +#ifdef xLG3D + /* + ** + ** Bug: this code doesn't currently work. It messes up the sprite window. + ** Test case: freecell: click New button. Cursor jumps to upper left hand + ** corner because the button ends up getting sent to the DS! + */ + /* + ** In addition, we need to send a synthetic motion event with the + ** last physical sprite position to the Display Server so that it + ** will notice that something has changed and recompute the current + ** pointer window. + ** + ** Note: we cannot just skip the above call to CheckMotion and + ** send this synthetic event alone. We must call CheckMotion(NULL) + ** in order to the current sprite window to a valid window. Otherwise + ** when the synthetic event comes back to us the prevSpriteWindow + ** may still point to an invalid window and this will crash the server! + */ + xEvent xE; + xE.u.u.type = MotionNotify; + xE.u.keyButtonPointer.event = lgeDisplayServerPRW; + xE.u.keyButtonPointer.rootX = sprite.hot.x; + xE.u.keyButtonPointer.rootY = sprite.hot.y; + xE.u.keyButtonPointer.time = GetTimeInMillis(); + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +#endif /* LG3D */ } #ifdef PANORAMIX @@ -2971,6 +3021,7 @@ DeliverFocusedEvent(keybd, xE, window, count) if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) return; } + /* just deliver it to the focus window */ FixUpEventFromWindow(xE, focus, None, FALSE); if (xE->u.u.type & EXTENSION_EVENT_BASE) @@ -3107,7 +3158,16 @@ ProcessKeyboardEvent (xE, keybd, count) { xeviekb = keybd; if(!rootWin) { +#ifdef LG3D + /* TEMP Workaround */ + WindowPtr pWin; + if (lgeDisplayServerIsAlive) { + xeviewin = pLgeDisplayServerPRWWin; + } + pWin = xeviewin->parent; +#else WindowPtr pWin = xeviewin->parent; +#endif /* LG3D */ while(pWin) { if(!pWin->parent) { rootWin = pWin->drawable.id; @@ -3263,6 +3323,22 @@ FixKeyState (xE, keybd) } #endif +#if defined(LG3D_EVENT_TEST_LATENCY) || defined(LG3D_EVENT_TEST_THROUGHPUT) +#include <sys/time.h> +static int lg3dEventTestActive = 0; +static struct timeval lg3dEventTestStartTV; +#endif /* LG3D_EVENT_TEST_LATENCY || LG3D_EVENT_TEST_THROUGHPUT */ + +#ifdef LG3D_EVENT_TEST_LATENCY +#include "statbuf.h" +static StatBuf *lg3dEventTestSb = NULL; +#endif /* LG3D_EVENT_TEST_LATENCY */ + +#ifdef LG3D_EVENT_TEST_THROUGHPUT +static int lg3dEventTestReceived = 0; +static int lg3dEventTestCount = 10000; +#endif /* LG3D_EVENT_TEST_THROUGHPUT */ + void #ifdef XKB CoreProcessPointerEvent (xE, mouse, count) @@ -3286,12 +3362,110 @@ ProcessPointerEvent (xE, mouse, count) xevieEventSent = 0; else { xeviemouse = mouse; + +#ifdef LG3D_EVENT_TEST_LATENCY + /* For latency timing: send */ + if (xE->u.u.type == ButtonPress) { + + ErrorF("Start Test\n"); + if (lg3dEventTestSb == NULL) { + lg3dEventTestSb = statBufCreate(); + if (lg3dEventTestSb == NULL) { + FatalError("LG3D Event Test: cannot create integer statistics buffer\n"); + } + } + lg3dEventTestActive = 1; + gettimeofday(&lg3dEventTestStartTV, 0); + /*ErrorF("Start: sec = %d, usec = %d\n", lg3dEventTestStartTV.tv_sec, + lg3dEventTestStartTV.tv_usec);*/ + } + if (lg3dEventTestActive) { + struct timeval tv; + int deltaSecs; + gettimeofday(&tv, 0); + deltaSecs = tv.tv_sec - lg3dEventTestStartTV.tv_sec; + /*ErrorF("Send: deltaSecs = %d, usec = %d\n", deltaSecs, tv.tv_usec);*/ + xE->u.keyButtonPointer.time = deltaSecs; + xE->u.keyButtonPointer.child = tv.tv_usec; + } +#endif /* LG3D_EVENT_TEST_LATENCY */ + +#ifdef LG3D_EVENT_TEST_THROUGHPUT + /* For throughput timing */ + if (xE->u.u.type == ButtonPress) { + int i; + ErrorF("Start Test\n"); + lg3dEventTestActive = 1; + lg3dEventTestReceived = 0; + gettimeofday(&lg3dEventTestStartTV, 0); + for (i = 1; i <= lg3dEventTestCount; i++) { + /*ErrorF("Sending event %d\n", i);*/ + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); + } + } else +#endif /* LG3D_EVENT_TEST_THROUGHPUT */ + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); return; } } #endif +#ifdef LG3D_EVENT_TEST_LATENCY + /* For latency timing: receive */ + if (lg3dEventTestActive) { + struct timeval tv; + int deltaSecs, deltaUsecs; + float msecs; + + gettimeofday(&tv, 0); + /*ErrorF("Receive: sec = %d, usec = %d\n", tv.tv_sec, tv.tv_usec);*/ + + tv.tv_sec -= lg3dEventTestStartTV.tv_sec; + /* + ErrorF("Receive: deltaSecs = %d, usec = %d\n", tv.tv_sec, tv.tv_usec); + ErrorF("Receive: ev->time = %d, ev->child = %d\n", + xE->u.keyButtonPointer.time, xE->u.keyButtonPointer.child); + */ + + deltaSecs = tv.tv_sec - xE->u.keyButtonPointer.time; + deltaUsecs = tv.tv_usec - xE->u.keyButtonPointer.child; + + /* + ErrorF("Interval: deltaSecs = %d, deltaUsec = %d\n", + deltaSecs, deltaUsecs); + */ + + msecs = 1000.0f * deltaSecs + deltaUsecs / 1000.0f; + /*ErrorF("Interval: msecs = %f\n", msecs);*/ + + statBufAdd(lg3dEventTestSb, msecs); + + /* Discard event to avoid the additional computational load of + further processing */ + return; + } + +#endif /* LG3D_EVENT_TEST_LATENCY */ + +#ifdef LG3D_EVENT_TEST_THROUGHPUT + if (lg3dEventTestActive) { + lg3dEventTestReceived++; + /*ErrorF("Received event %d\n", lg3dEventTestReceived);*/ + if (lg3dEventTestReceived == lg3dEventTestCount) { + struct timeval stopTV; + gettimeofday(&stopTV, 0); + int deltaSecs = stopTV.tv_sec - lg3dEventTestStartTV.tv_sec; + int deltaUsecs = stopTV.tv_usec - lg3dEventTestStartTV.tv_usec; + float msecs = deltaSecs * 1000.0f + deltaUsecs / 1000.0f; + float msecsPerEvent = msecs / (float)lg3dEventTestCount; + ErrorF("LG3D Event Test: %d events in %f ms (%f ms/event)\n", + lg3dEventTestCount, msecs, msecsPerEvent); + lg3dEventTestActive = 0; + } + } +#endif /* LG3D_EVENT_TEST_THROUGHPUT */ + if (!syncEvents.playingEvents) NoticeTime(xE) XE_KBPTR.state = (butc->state | ( @@ -4971,11 +5145,17 @@ ProcRecolorCursor(client) return (Success); } +/*#define DEBUG*/ #if defined(LG3D) && defined (DEBUG) int print_events_all = 0; int print_events_to_ds = 0; int print_events_to_wm = 0; int print_events_to_app = 0; +int damageEventsOnly = 0; +int numDamageEvents = 0; +/* TODO: for damage event debug only */ +#include "damageproto.h" + #endif /* LG3D && DEBUG */ void @@ -5039,18 +5219,31 @@ WriteEventsToClient(pClient, count, events) } #if defined(LG3D) && defined (DEBUG) + if (print_events_all || + /* TODO: these indices are now out of date; update them */ (print_events_to_ds && pClient->index == 4) || - (print_events_to_wm && pClient->index == 5) || + (print_events_to_wm && pClient->index == 9) || (print_events_to_app && pClient->index == 6)) { xEvent *ev; for(i = 0; i < count; i++) { ev = &events[i]; - ErrorF("Send event %d to client %d, xy = %d, %d, event win = %d\n", - ev->u.u.type, pClient->index, - ev->u.keyButtonPointer.eventX, ev->u.keyButtonPointer.eventY, - ev->u.keyButtonPointer.event); + if (ev->u.u.type == 118) { + xDamageNotifyEvent *damev = (xDamageNotifyEvent *) ev; + ErrorF("Send damage event %d, to client %d, xywh = %d, %d, %d, %d\n", + ++numDamageEvents, pClient->index, + damev->area.x, damev->area.y, + damev->area.width, damev->area.height); + } else if (!damageEventsOnly) { + ErrorF("Send event %d to client %d, xy = %d, %d, event win = %d\n", + ev->u.u.type, pClient->index, + ev->u.keyButtonPointer.eventX, ev->u.keyButtonPointer.eventY, + ev->u.keyButtonPointer.event); + if (ev->u.u.type == 4 || ev->u.u.type == 5) { + ErrorF("Button detail = %d\n", ev->u.u.detail); + } + } } } #endif /* LG3D && DEBUG */ diff --git a/dix/window.c b/dix/window.c index f72f63a4c..dcba42a5c 100644 --- a/dix/window.c +++ b/dix/window.c @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.6 2004/07/31 08:24:13 anholt Exp $ */ +/* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.6.4.1.10.1 2005/01/10 03:45:03 deronj Exp $ */ /* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ /* @@ -833,6 +833,7 @@ CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist, event.u.createNotify.override = pWin->overrideRedirect; DeliverEvents(pParent, &event, 1, NullWindow); } + return pWin; } @@ -2269,9 +2270,6 @@ ConfigureWindow(pWin, mask, vlist, client) ClientPtr ag_leader = NULL; #endif xEvent event; -#ifdef LG3D - Bool redirToWm; -#endif /* LG3D */ if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) return(BadMatch); @@ -2372,23 +2370,8 @@ ConfigureWindow(pWin, mask, vlist, client) ag_leader = XagLeader (win_owner); #endif -#ifdef LG3D - if (lgeDisplayServerIsAlive) { - - /* TODO: RedirectSend is not always true for prw; I don't know why. */ - redirToWm = RedirectSend(pParent) || (pParent->drawable.id == lgeDisplayServerPRW); - - /* Note: even send notifications for override redirect window */ - - } else { - redirToWm = !pWin->overrideRedirect && RedirectSend(pParent); - } - - if ((redirToWm -#else if ((!pWin->overrideRedirect) && (RedirectSend(pParent) -#endif /* LG3D */ #ifdef XAPPGROUP || (win_owner->appgroup && ag_leader && XagIsControlledRoot (client, pParent)) @@ -2660,6 +2643,28 @@ ReparentWindow(pWin, pParent, x, y, client) event.u.reparent.override = pWin->overrideRedirect; DeliverEvents(pWin, &event, 1, pParent); +#ifdef LG3D + /* + ** HACK ALERT: + ** Bug fix for lg3d bug 213. If the window is override redirect, + ** and the old parent is the root window, and the new parent is + ** the PRW, have QueryTree lie about the parent and say that the + ** parent is still the root window. For more info refer to the + ** comment in ProcQueryTree. + ** + ** TODO: someday: it would be nice to fix the client bug and + ** get rid of this hack. + */ + if (pWin->overrideRedirect && + pWin->parent == WindowTable[pWin->drawable.pScreen->myNum] && + pParent == pLgeDisplayServerPRWWin) { + pWin->optional->ovRedirLieAboutRootParent = 1; + /*ErrorF("Lying about parent for window %d\n", pWin->drawable.id);*/ + } else { + pWin->optional->ovRedirLieAboutRootParent = 0; + } +#endif /* LG3D */ + /* take out of sibling chain */ pPriorParent = pPrev = pWin->parent; @@ -2752,6 +2757,68 @@ RealizeTree(WindowPtr pWin) } } +#ifdef LG3D + +/* +** The mapping of ordinary, non-override redirect windows is redirected to the +** window manager. This gives the window manager a chance to reparent the window +** to the pseudo-root-window and to redirect rendering to the composite backing +** pixmap. However, since override redirect windows are never redirected to +** the window manager we must perform these vital actions in the X server. +** +** Historical Note: in the early days of LG3D, we experimented with forcing +** the mapping of override redirect windows to be redirected to the window +** manager. This failed. This made the mapping of override redirect windows +** non-atomic. Many X applications assume that MapWindow for an override +** redirect window is atomic, such as GNOME and Mozilla.. For example, after +** the MapWindow request these apps send rendering requests without waiting +** for an expose, or they can send an UnmapWindow request almost immediately +** after the MapWindow request. Making MapWindow non-atomic meant that these +** succeeding requests would get lost while the WM was in the process of mapping +** the window. This manifested itself with GNOME tooltips that were stuck on +** the screen and tooltips or menus appearing that were blank or garbaged. +** Therefore, although it seems strange to perform the reparent and composite +** redirect operations in the X server for override redirect windows, this +** has proven to be the best approach available; it avoids altering client +** assumptions about the behavior of MapWindow on these types of windows. +*/ + +#include "composite.h" + +extern int +compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update); + +extern int +compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update); + +static void +lg3dMapWindowOverrideRedirect (WindowPtr pWin, ClientPtr client) +{ + WindowPtr pParent = pLgeDisplayServerPRWWin; + + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + + compRedirectWindow(client, pWin, CompositeRedirectManual); + + if (pWin->optional == NULL) { + if (!MakeWindowOptional(pWin)) { + FatalError("lg3dMapWindowOverrideRedirect: MakeWindowOptional out of memory\n"); + } + } + pWin->optional->ovRedirCompRedirClient = client; +} + +static void +lg3dUnmapWindowOverrideRedirect (WindowPtr pWin) +{ + compUnredirectWindow(wOvRedirCompRedirClient(pWin), pWin, CompositeRedirectManual); +} + +#endif /* LG3D */ + /***** * MapWindow * If some other client has selected SubStructureReDirect on the parent @@ -2772,9 +2839,6 @@ MapWindow(pWin, client) Bool dosave = FALSE; #endif WindowPtr pLayerWin; -#ifdef LG3D - Bool redirToWm; -#endif /* LG3D */ if (pWin->mapped) return(Success); @@ -2799,22 +2863,8 @@ MapWindow(pWin, client) ClientPtr ag_leader = XagLeader (win_owner); #endif -#ifdef LG3D - if (lgeDisplayServerIsAlive) { - - /* TODO: RedirectSend is not always true for prw; I don't know why. */ - redirToWm = RedirectSend(pParent) || (pParent->drawable.id == lgeDisplayServerPRW); - - /* Note: even send notifications for override redirect window */ - } else { - redirToWm = !pWin->overrideRedirect && RedirectSend(pParent); - } - - if ((redirToWm -#else if ((!pWin->overrideRedirect) && (RedirectSend(pParent) -#endif /* LG3D */ #ifdef XAPPGROUP || (win_owner->appgroup && ag_leader && XagIsControlledRoot (client, pParent)) @@ -2836,11 +2886,18 @@ MapWindow(pWin, client) event.u.mapRequest.parent = pParent->drawable.id; if (MaybeDeliverEventsToClient(pParent, &event, 1, - SubstructureRedirectMask, client) == 1) + SubstructureRedirectMask, client) == 1) { return(Success); + } } +#ifdef LG3D + else if (lgeDisplayServerIsAlive && pWin->overrideRedirect) { + lg3dMapWindowOverrideRedirect(pWin, client); + } +#endif /* LG3D */ pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) { event.u.u.type = MapNotify; @@ -2924,9 +2981,6 @@ MapSubwindows(pParent, client) Bool dosave = FALSE; #endif WindowPtr pLayerWin; -#ifdef LG3D - Bool redirToWm; -#endif /* LG3D */ pScreen = pParent->drawable.pScreen; parentRedirect = RedirectSend(pParent); @@ -2936,22 +2990,7 @@ MapSubwindows(pParent, client) { if (!pWin->mapped) { -#ifdef LG3D - if (lgeDisplayServerIsAlive) { - - /* TODO: RedirectSend is not always true for prw; I don't know why. */ - redirToWm = parentRedirect || (pParent->drawable.id == lgeDisplayServerPRW); - - /* Note: even send notifications for override redirect window */ - - } else { - redirToWm = parentRedirect && !pWin->overrideRedirect; - } - - if (redirToWm) -#else if (parentRedirect && !pWin->overrideRedirect) -#endif /* LG3D */ { event.u.u.type = MapRequest; event.u.mapRequest.window = pWin->drawable.id; @@ -2961,6 +3000,11 @@ MapSubwindows(pParent, client) SubstructureRedirectMask, client) == 1) continue; } +#ifdef LG3D + else if (lgeDisplayServerIsAlive && pWin->overrideRedirect) { + lg3dMapWindowOverrideRedirect(pWin, client); + } +#endif /* LG3D */ pWin->mapped = TRUE; if (parentNotify || StrSend(pWin)) @@ -3131,7 +3175,15 @@ UnmapWindow(pWin, fromConfigure) (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); (*pScreen->MarkWindow)(pLayerWin->parent); } + pWin->mapped = FALSE; + +#ifdef LG3D + if (lgeDisplayServerIsAlive && pWin->overrideRedirect) { + lg3dUnmapWindowOverrideRedirect(pWin); + } +#endif /* LG3D */ + if (wasRealized) UnrealizeTree(pWin, fromConfigure); if (wasViewable) @@ -3202,6 +3254,13 @@ UnmapSubwindows(pWin) pChild->valdata = UnmapValData; anyMarked = TRUE; } + +#ifdef LG3D + if (lgeDisplayServerIsAlive && pWin->overrideRedirect) { + lg3dUnmapWindowOverrideRedirect(pWin); + } +#endif /* LG3D */ + pChild->mapped = FALSE; if (pChild->realized) UnrealizeTree(pChild, FALSE); @@ -3718,6 +3777,14 @@ CheckWindowOptionalNeed (w) return; if (optional->colormap != parentOptional->colormap) return; +#ifdef LG3D + if (optional->ovRedirCompRedirClient != NULL) { + return; + } + if (optional->ovRedirLieAboutRootParent != 0) { + return; + } +#endif /* LG3D */ DisposeWindowOptional (w); } @@ -3766,6 +3833,10 @@ MakeWindowOptional (pWin) optional->cursor = None; } optional->colormap = parentOptional->colormap; +#ifdef LG3D + optional->ovRedirCompRedirClient = NULL; + optional->ovRedirLieAboutRootParent = 0; +#endif /* LG3D */ pWin->optional = optional; return TRUE; } |