summaryrefslogtreecommitdiff
path: root/dix/grabs.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2007-08-12 15:31:10 +0930
committerPeter Hutterer <peter@cs.unisa.edu.au>2007-08-12 15:31:10 +0930
commitf367285fd5825e0adc271982a529c9904ad65c89 (patch)
tree4e7081da773c51cc9448cefe17c2c3639f33ad6d /dix/grabs.c
parentb1272eefd9a3e340d65c14903f337747ec82d021 (diff)
parentff4bd3addb48df3eacc4b121cc249a7f38eb981a (diff)
Merge branch 'master' into mpx
Conflicts: Xi/exevents.c dix/devices.c dix/getevents.c include/dix.h mi/mieq.c
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 01f4b6439..f1d00867e 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -287,6 +287,42 @@ GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice)
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)
{
@@ -304,11 +340,22 @@ AddPassiveGrabToList(GrabPtr pGrab)
}
}
+ /* 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;
+ }
+ }
+
if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window))
{
FreeGrab(pGrab);
return BadAlloc;
}
+
pGrab->next = pGrab->window->optional->passiveGrabs;
pGrab->window->optional->passiveGrabs = pGrab;
if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab))