xserver: Branch 'mpx'
Peter Hutterer
whot at kemper.freedesktop.org
Tue Apr 17 10:23:41 EEST 2007
dix/events.c | 92 ++++++++++++++++++++++++++++++++++++++++------------
dix/window.c | 15 ++++++--
include/inputstr.h | 1
include/windowstr.h | 10 +++++
4 files changed, 92 insertions(+), 26 deletions(-)
New commits:
diff-tree b6aec7f6f906a18d13586d63afabf1ee4fbb11c3 (from 451d5464b4e8a2516b8a4598b3c4eb14656be90e)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date: Tue Apr 17 16:51:16 2007 +0930
Change FocusIn/Out semantics to match Enter/Leave semantics.
diff --git a/dix/events.c b/dix/events.c
index def209e..1733e2d 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))
+
+ /*
+ * 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)
{
- 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);
+ (type == FocusIn) ? (*numFoci)++ : (*numFoci)--;
+ if (((*numFoci) == (FocusOut - type)))
+ sendevent = TRUE;
+ } else
+ {
+ if (!(*numFoci))
+ sendevent = TRUE;
+ }
- ke.type = KeymapNotify;
- (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
- KeymapStateMask, NullGrab, 0);
+ 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 5a03642..4846939 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -155,7 +155,7 @@ _X_EXPORT int screenIsSaved = SCREEN_SAV
_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 pW
_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 d8d12d7..bdb7518 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 4683abe..87158b2 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"
More information about the xorg-commit
mailing list