Change FocusIn/Out semantics to match Enter/Leave semantics.

This commit is contained in:
Peter Hutterer 2007-04-17 16:51:16 +09:30
parent 451d5464b4
commit b6aec7f6f9
4 changed files with 93 additions and 27 deletions

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -391,5 +391,4 @@ typedef struct _QdEvent {
int evcount;
} QdEventRec;
#define MPXDBG(...) ErrorF("MPX: " __VA_ARGS__ )
#endif /* INPUTSTRUCT_H */

View File

@ -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"