[PATCH 3/7] dix: split enter/leave event handling into core and device handling.
peter.hutterer at who-t.net
peter.hutterer at who-t.net
Fri Nov 14 02:51:12 PST 2008
From: Peter Hutterer <peter.hutterer at redhat.com>
Device events always need to be delivered, core events only in some cases.
Let's keep them completely separate so we can adjust core event delivery.
Signed-off-by: Peter Hutterer <peter.hutterer at redhat.com>
---
dix/enterleave.c | 76 +++++++++++---------------
dix/enterleave.h | 13 +++++
dix/events.c | 159 +++++++++++++++++++++++++++---------------------------
3 files changed, 125 insertions(+), 123 deletions(-)
diff --git a/dix/enterleave.c b/dix/enterleave.c
index 941aa52..11929c6 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -30,6 +30,7 @@
#include <X11/X.h>
#include "windowstr.h"
+#include "exglobals.h"
#include "enterleave.h"
/**
@@ -47,46 +48,57 @@ CommonAncestor(
/**
- * Send enter notifies to all parent windows up to ancestor.
- * This function recurses.
+ * Send enter notifies to all windows between @ancestor and @child (excluding
+ * both). Events are sent running up the window hierarchy. This function
+ * recurses.
+ * If @core is TRUE, core events are sent, otherwise XI events will be sent.
*/
static void
-EnterNotifies(DeviceIntPtr pDev,
+EnterNotifies(DeviceIntPtr dev,
WindowPtr ancestor,
WindowPtr child,
int mode,
- int detail)
+ int detail,
+ BOOL core)
{
WindowPtr parent = child->parent;
if (ancestor == parent)
return;
- EnterNotifies(pDev, ancestor, parent, mode, detail);
- EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent,
- child->drawable.id);
+ EnterNotifies(dev, ancestor, parent, mode, detail, core);
+ if (core)
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent,
+ child->drawable.id);
+ else
+ DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, detail, parent,
+ child->drawable.id);
}
-
/**
- * Send leave notifies to all parent windows up to ancestor.
- * This function recurses.
+ * Send leave notifies to all windows between @child and @ancestor.
+ * Events are sent running up the hierarchy.
*/
static void
-LeaveNotifies(DeviceIntPtr pDev,
+LeaveNotifies(DeviceIntPtr dev,
WindowPtr child,
WindowPtr ancestor,
int mode,
- int detail)
+ int detail,
+ BOOL core)
{
- WindowPtr pWin;
+ WindowPtr win;
if (ancestor == child)
return;
- for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
+ for (win = child->parent; win != ancestor; win = win->parent)
{
- EnterLeaveEvent(pDev, LeaveNotify, mode, detail, pWin,
- child->drawable.id);
- child = pWin;
+ if (core)
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win,
+ child->drawable.id);
+ else
+ DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, detail, win,
+ child->drawable.id);
+ child = win;
}
}
@@ -108,31 +120,7 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
if (fromWin == toWin)
return;
- if (IsParent(fromWin, toWin))
- {
- EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
- None);
- EnterNotifies(pDev, fromWin, toWin, mode,
- NotifyVirtual);
- EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None);
- }
- else if (IsParent(toWin, fromWin))
- {
- EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin,
- None);
- LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
- EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None);
- }
- else
- { /* neither fromWin nor toWin is descendent of the other */
- WindowPtr common = CommonAncestor(toWin, fromWin);
- /* common == NullWindow ==> different screens */
- EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
- None);
- LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
- EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
- EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
- None);
- }
-}
+ CoreEnterLeaveEvents(pDev, fromWin, toWin, mode);
+ DeviceEnterLeaveEvents(pDev, fromWin, toWin, mode);
+}
diff --git a/dix/enterleave.h b/dix/enterleave.h
index c1bfc3a..6e06226 100644
--- a/dix/enterleave.h
+++ b/dix/enterleave.h
@@ -50,4 +50,17 @@ extern WindowPtr CommonAncestor(
WindowPtr a,
WindowPtr b);
+extern void CoreEnterLeaveEvent(DeviceIntPtr mouse,
+ int type,
+ int mode,
+ int detail,
+ WindowPtr pWin,
+ Window child);
+extern void DeviceEnterLeaveEvent(DeviceIntPtr mouse,
+ int type,
+ int mode,
+ int detail,
+ WindowPtr pWin,
+ Window child);
+
#endif /* _ENTERLEAVE_H_ */
diff --git a/dix/events.c b/dix/events.c
index eff7eeb..047ec60 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4184,7 +4184,7 @@ EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
* Uses the paired keyboard to get some additional information.
*/
void
-EnterLeaveEvent(
+CoreEnterLeaveEvent(
DeviceIntPtr mouse,
int type,
int mode,
@@ -4197,12 +4197,6 @@ EnterLeaveEvent(
DeviceIntPtr keybd;
GrabPtr grab = mouse->deviceGrab.grab;
Mask mask;
- int inWindow; /* zero if no sprites are in window */
- Bool sendevent = FALSE;
-
- deviceEnterNotify *devEnterLeave;
- int mskidx;
- OtherInputMasks *inputMasks;
keybd = GetPairedDevice(mouse);
@@ -4250,44 +4244,7 @@ EnterLeaveEvent(
IsParent(focus, pWin)))
event.u.enterLeave.flags |= ELFlagFocus;
-
- /*
- * Sending multiple core enter/leave events to the same window confuse the
- * client.
- * We can send multiple events that have detail NotifyVirtual or
- * NotifyNonlinearVirtual however. For most clients anyway.
- *
- * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
- * we only send an enter event for the first pointer to enter. A leave
- * event is sent for the last pointer to leave.
- *
- * For events with Virtual detail, we send them only to a window that does
- * not have a pointer inside.
- *
- * For a window tree in the form of
- *
- * A -> Bp -> C -> D
- * \ (where B and E have pointers)
- * -> Ep
- *
- * If the pointer moves from E into D, a LeaveNotify is sent to E, an
- * EnterNotify is sent to D, an EnterNotify with detail
- * NotifyNonlinearVirtual to C and nothing to B.
- */
-
- /* Clear bit for device, but don't worry about SDs. */
- if (mouse->isMaster && type == LeaveNotify &&
- (detail != NotifyVirtual && detail != NotifyNonlinearVirtual))
- if (mode != NotifyUngrab)
- ENTER_LEAVE_SEMAPHORE_UNSET(pWin, mouse);
-
- inWindow = EnterLeaveSemaphoresIsset(pWin);
-
- if(!inWindow || mode == NotifyGrab || mode == NotifyUngrab)
- sendevent = TRUE;
-
-
- if ((mask & filters[mouse->id][type]) && sendevent)
+ if ((mask & filters[mouse->id][type]))
{
if (grab)
TryClientEvents(rClient(grab), mouse, &event, 1, mask,
@@ -4297,18 +4254,81 @@ EnterLeaveEvent(
filters[mouse->id][type], NullGrab, 0);
}
- if (mouse->isMaster && type == EnterNotify &&
- (detail != NotifyVirtual && detail != NotifyNonlinearVirtual))
- if (mode != NotifyGrab)
- ENTER_LEAVE_SEMAPHORE_SET(pWin, mouse);
+ if ((type == EnterNotify) && (mask & KeymapStateMask))
+ {
+ xKeymapEvent ke;
+ ClientPtr client = grab ? rClient(grab)
+ : clients[CLIENT_ID(pWin->drawable.id)];
+ if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
+ bzero((char *)&ke.map[0], 31);
+ else
+ memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
+
+ ke.type = KeymapNotify;
+ if (grab)
+ TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
+ mask, KeymapStateMask, grab);
+ else
+ DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
+ KeymapStateMask, NullGrab, 0);
+ }
+}
+
+void
+DeviceEnterLeaveEvent(
+ DeviceIntPtr mouse,
+ int type,
+ int mode,
+ int detail,
+ WindowPtr pWin,
+ Window child)
+{
+ xEvent event;
+ GrabPtr grab = mouse->deviceGrab.grab;
+ deviceEnterNotify *devEnterLeave;
+ int mskidx;
+ OtherInputMasks *inputMasks;
+ Mask mask;
+ DeviceIntPtr keybd = GetPairedDevice(mouse);
+ BOOL sameScreen;
+
+ if (grab) {
+ mask = (pWin == grab->window) ? grab->eventMask : 0;
+ if (grab->ownerEvents)
+ mask |= EventMaskForClient(pWin, rClient(grab));
+ } else {
+ mask = pWin->eventMask | wOtherEventMasks(pWin);
+ }
/* we don't have enough bytes, so we squash flags and mode into
one byte, and use the last byte for the deviceid. */
- devEnterLeave = (deviceEnterNotify*)&event;
- devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify :
- DeviceLeaveNotify;
- devEnterLeave->mode |= (event.u.enterLeave.flags << 4);
+ devEnterLeave = (deviceEnterNotify*)&event;
+ devEnterLeave->detail = detail;
+ devEnterLeave->time = currentTime.milliseconds;
+ devEnterLeave->rootX = mouse->spriteInfo->sprite->hot.x;
+ devEnterLeave->rootY = mouse->spriteInfo->sprite->hot.y;
+ FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
+ sameScreen = event.u.keyButtonPointer.sameScreen;
+
+ devEnterLeave->child = child;
+ devEnterLeave->type = type;
devEnterLeave->deviceid = mouse->id;
+ devEnterLeave->mode = mode;
+ devEnterLeave->mode |= (sameScreen ? (ELFlagSameScreen << 4) : 0);
+
+#ifdef XKB
+ if (!noXkbExtension) {
+ devEnterLeave->state = mouse->button->state & 0x1f00;
+ if (keybd)
+ devEnterLeave->state |=
+ XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
+ } else
+#endif
+ {
+ devEnterLeave->state = (keybd) ? keybd->key->state : 0;
+ devEnterLeave->state |= mouse->button->state;
+ }
+
mskidx = mouse->id;
inputMasks = wOtherInputMasks(pWin);
if (inputMasks &&
@@ -4316,34 +4336,15 @@ EnterLeaveEvent(
inputMasks->deliverableEvents[mskidx]))
{
if (grab)
- (void)TryClientEvents(rClient(grab), mouse,
- (xEvent*)devEnterLeave, 1,
- mask, filters[mouse->id][devEnterLeave->type],
- grab);
- else
- (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave,
- 1, filters[mouse->id][devEnterLeave->type],
- NullGrab, mouse->id);
+ TryClientEvents(rClient(grab), mouse,
+ (xEvent*)devEnterLeave, 1, mask,
+ filters[mouse->id][devEnterLeave->type], grab);
+ else
+ DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, 1,
+ filters[mouse->id][devEnterLeave->type],
+ NullGrab, mouse->id);
}
- if ((type == EnterNotify) && (mask & KeymapStateMask))
- {
- xKeymapEvent ke;
- ClientPtr client = grab ? rClient(grab)
- : clients[CLIENT_ID(pWin->drawable.id)];
- if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
- bzero((char *)&ke.map[0], 31);
- else
- memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
-
- ke.type = KeymapNotify;
- if (grab)
- (void)TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
- mask, KeymapStateMask, grab);
- else
- (void)DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
- KeymapStateMask, NullGrab, 0);
- }
}
static void
--
1.6.0.3
More information about the xorg
mailing list