summaryrefslogtreecommitdiff
path: root/dix/grabs.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2007-06-13 15:26:03 +0930
committerPeter Hutterer <peter@cs.unisa.edu.au>2007-06-25 09:35:30 +0930
commitb141b85c254afff3ce2221d899787fab3dc295bd (patch)
treefe97343cc118a27b07b39f62a12a5781ec8bd829 /dix/grabs.c
parent19cde59c41cf167cc609debfee75bfc015beac12 (diff)
Check for identical grabs when adding a new passive grab. If an identical grab
exists, remove the old one and prepend the new one. X.org Bug 2738 <https://bugs.freedesktop.org/show_bug.cgi?id=2738>
Diffstat (limited to 'dix/grabs.c')
-rw-r--r--dix/grabs.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/dix/grabs.c b/dix/grabs.c
index 714fea3e5..cecd7ec39 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -269,6 +269,42 @@ GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
return FALSE;
}
+static Bool
+GrabsAreIdentical(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
+{
+ if (pFirstGrab->device != pSecondGrab->device ||
+ (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
+ (pFirstGrab->type != pSecondGrab->type))
+ return FALSE;
+
+ if (!(DetailSupersedesSecond(pFirstGrab->detail,
+ pSecondGrab->detail,
+ (unsigned short)AnyKey) &&
+ DetailSupersedesSecond(pSecondGrab->detail,
+ pFirstGrab->detail,
+ (unsigned short)AnyKey)))
+ return FALSE;
+
+ if (!(DetailSupersedesSecond(pFirstGrab->modifiersDetail,
+ pSecondGrab->modifiersDetail,
+ (unsigned short)AnyModifier) &&
+ DetailSupersedesSecond(pSecondGrab->modifiersDetail,
+ pFirstGrab->modifiersDetail,
+ (unsigned short)AnyModifier)))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * Prepend the new grab to the list of passive grabs on the window.
+ * Any previously existing grab that matches the new grab will be removed.
+ * Adding a new grab that would override another client's grab will result in
+ * a BadAccess.
+ *
+ * @return Success or X error code on failure.
+ */
int
AddPassiveGrabToList(GrabPtr pGrab)
{
@@ -291,6 +327,17 @@ AddPassiveGrabToList(GrabPtr pGrab)
FreeGrab(pGrab);
return BadAlloc;
}
+
+ /* Remove all grabs that match the new one exactly */
+ for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
+ {
+ if (GrabsAreIdentical(pGrab, grab))
+ {
+ DeletePassiveGrabFromList(grab);
+ break;
+ }
+ }
+
pGrab->next = pGrab->window->optional->passiveGrabs;
pGrab->window->optional->passiveGrabs = pGrab;
if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab))