From b6aec7f6f906a18d13586d63afabf1ee4fbb11c3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Apr 2007 16:51:16 +0930 Subject: [PATCH] Change FocusIn/Out semantics to match Enter/Leave semantics. --- dix/events.c | 94 +++++++++++++++++++++++++++++++++++---------- dix/window.c | 15 ++++++-- include/inputstr.h | 1 - include/windowstr.h | 10 ++++- 4 files changed, 93 insertions(+), 27 deletions(-) diff --git a/dix/events.c b/dix/events.c index def209eb8..1733e2d1e 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2272,7 +2272,7 @@ DefineInitialRootWindow(WindowPtr win) if (DevHasCursor(pDev)) { InitializeSprite(pDev, win); - win->devPrivates[EnterLeavePrivatesIndex].val++; + win->devPrivates[FocusPrivatesIndex].val++; } pDev = pDev->next; } @@ -3452,7 +3452,7 @@ EnterLeaveEvent( GrabPtr grab = mouse->coreGrab.grab; GrabPtr devgrab = mouse->deviceGrab.grab; Mask mask; - long* inWindow; /* no of sprites inside pWin */ + int* inWindow; /* no of sprites inside pWin */ Bool sendevent = FALSE; deviceEnterNotify *devEnterLeave; @@ -3502,7 +3502,7 @@ EnterLeaveEvent( IsParent(focus, pWin))) event.u.enterLeave.flags |= ELFlagFocus; - inWindow = &pWin->devPrivates[EnterLeavePrivatesIndex].val; + inWindow = &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave; /* * Sending multiple core enter/leave events to the same window confuse the @@ -3665,28 +3665,80 @@ static void FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) { xEvent event; + int* numFoci; /* no of foci the window has already */ + Bool sendevent = FALSE; + FocusSemaphoresPtr focus; if (dev != inputInfo.keyboard) DeviceFocusEvent(dev, type, mode, detail, pWin); - event.u.focus.mode = mode; - event.u.u.type = type; - event.u.u.detail = detail; - event.u.focus.window = pWin->drawable.id; - (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab, - 0); - if ((type == FocusIn) && - ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) - { - xKeymapEvent ke; - ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; - if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE)) - memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); - else - bzero((char *)&ke.map[0], 31); - ke.type = KeymapNotify; - (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1, - KeymapStateMask, NullGrab, 0); + /* + * Same procedure as for Enter/Leave events. + * + * Sending multiple core FocusIn/Out events to the same window may confuse + * the client. + * We can send multiple events that have detail NotifyVirtual, + * NotifyNonlinearVirtual, NotifyPointerRoot, NotifyDetailNone or + * NotifyPointer however. + * + * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear) + * we only send an FocusIn event for the first kbd to set the focus. A + * FocusOut event is sent for the last kbd to set the focus away from the + * window.. + * + * For events with Virtual detail, we send them only to a window that does + * not have a focus from another keyboard. + * + * For a window tree in the form of + * + * A -> Bf -> C -> D + * \ (where B and E have focus) + * -> Ef + * + * If the focus changes from E into D, a FocusOut is sent to E, a + * FocusIn is sent to D, a FocusIn with detail + * NotifyNonlinearVirtual to C and nothing to B. + */ + + numFoci = + &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout; + if (detail != NotifyVirtual && + detail != NotifyNonlinearVirtual && + detail != NotifyPointer && + detail != NotifyPointerRoot && + detail != NotifyDetailNone) + { + (type == FocusIn) ? (*numFoci)++ : (*numFoci)--; + if (((*numFoci) == (FocusOut - type))) + sendevent = TRUE; + } else + { + if (!(*numFoci)) + sendevent = TRUE; + } + + if (sendevent) + { + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE)) + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + else + bzero((char *)&ke.map[0], 31); + + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } } } diff --git a/dix/window.c b/dix/window.c index 5a03642d8..484693906 100644 --- a/dix/window.c +++ b/dix/window.c @@ -155,7 +155,7 @@ _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF; _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; -_X_EXPORT int EnterLeavePrivatesIndex = -1; +_X_EXPORT int FocusPrivatesIndex = -1; #if 0 extern void DeleteWindowFromAnyEvents(); @@ -312,6 +312,12 @@ SetWindowToDefaults(WindowPtr pWin) #ifdef COMPOSITE pWin->redirectDraw = 0; #endif + + ((FocusSemaphoresPtr) + pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave = 0; + ((FocusSemaphoresPtr) + pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout = 0; + } static void @@ -3981,10 +3987,11 @@ WindowParentHasDeviceCursor(WindowPtr pWin, _X_EXPORT Bool InitWindowPrivates(ScreenPtr screen) { - if (EnterLeavePrivatesIndex == -1) - EnterLeavePrivatesIndex = AllocateWindowPrivateIndex(); + if (FocusPrivatesIndex == -1) + FocusPrivatesIndex = AllocateWindowPrivateIndex(); - return AllocateWindowPrivate(screen, EnterLeavePrivatesIndex, 0); + return AllocateWindowPrivate(screen, FocusPrivatesIndex, + sizeof(FocusSemaphoresRec)); } #ifndef NOLOGOHACK diff --git a/include/inputstr.h b/include/inputstr.h index d8d12d732..bdb7518f2 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -391,5 +391,4 @@ typedef struct _QdEvent { int evcount; } QdEventRec; -#define MPXDBG(...) ErrorF("MPX: " __VA_ARGS__ ) #endif /* INPUTSTRUCT_H */ diff --git a/include/windowstr.h b/include/windowstr.h index 4683abeaa..87158b263 100644 --- a/include/windowstr.h +++ b/include/windowstr.h @@ -216,7 +216,15 @@ typedef struct _ScreenSaverStuff { extern int screenIsSaved; extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; -extern int EnterLeavePrivatesIndex; +extern int FocusPrivatesIndex; + +/* Used to maintain semantics of core protocol for Enter/LeaveNotifies and + * FocusIn/Out events for multiple pointers/keyboards. + */ +typedef struct _FocusSemaphores { + int enterleave; + int focusinout; +} FocusSemaphoresRec, *FocusSemaphoresPtr; /* * this is the configuration parameter "NO_BACK_SAVE"