aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xi
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/Xi')
-rwxr-xr-x[-rw-r--r--]xorg-server/Xi/chgdctl.c6
-rw-r--r--xorg-server/Xi/devbell.c3
-rw-r--r--xorg-server/Xi/exevents.c179
-rw-r--r--xorg-server/Xi/extinit.c38
-rw-r--r--xorg-server/Xi/setdval.c3
-rw-r--r--xorg-server/Xi/setmode.c4
-rw-r--r--xorg-server/Xi/ungrdevb.c2
-rw-r--r--xorg-server/Xi/ungrdevk.c2
-rw-r--r--xorg-server/Xi/xibarriers.c12
-rw-r--r--xorg-server/Xi/xibarriers.h4
-rw-r--r--xorg-server/Xi/xigrabdev.c15
-rw-r--r--xorg-server/Xi/xipassivegrab.c2
12 files changed, 155 insertions, 115 deletions
diff --git a/xorg-server/Xi/chgdctl.c b/xorg-server/Xi/chgdctl.c
index 84aa1c4df..106b9aaed 100644..100755
--- a/xorg-server/Xi/chgdctl.c
+++ b/xorg-server/Xi/chgdctl.c
@@ -122,6 +122,12 @@ ProcXChangeDeviceControl(ClientPtr client)
if (ret != Success)
goto out;
+ /* XTest devices are special, none of the below apply to them anyway */
+ if (IsXTestDevice(dev, NULL)) {
+ ret = BadMatch;
+ goto out;
+ }
+
rep.repType = X_Reply;
rep.RepType = X_ChangeDeviceControl;
diff --git a/xorg-server/Xi/devbell.c b/xorg-server/Xi/devbell.c
index c75b94dee..202c8de18 100644
--- a/xorg-server/Xi/devbell.c
+++ b/xorg-server/Xi/devbell.c
@@ -142,7 +142,8 @@ ProcXDeviceBell(ClientPtr client)
newpercent = base + newpercent;
else
newpercent = base - newpercent + stuff->percent;
+ if (proc == NULL)
+ return BadValue;
(*proc) (newpercent, dev, ctrl, class);
-
return Success;
}
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c
index bcbf97006..6c40df494 100644
--- a/xorg-server/Xi/exevents.c
+++ b/xorg-server/Xi/exevents.c
@@ -1038,47 +1038,22 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
static void
ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
{
- int rc;
ClientPtr client;
XID error;
+ GrabPtr grab = ti->listeners[0].grab;
- rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient,
- DixSendAccess);
- if (rc != Success) {
- ErrorF("[Xi] Failed to lookup early accepting client.\n");
- return;
- }
+ BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
+ ti->listeners[0].type != LISTENER_POINTER_GRAB);
+ BUG_RETURN(!grab);
+
+ client = rClient(grab);
if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
- ti->listeners[0].window->drawable.id, &error) !=
- Success)
+ ti->listeners[0].window->drawable.id, &error) != Success)
ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
}
/**
- * Generate and deliver a TouchEnd event.
- *
- * @param dev The device to deliver the event for.
- * @param ti The touch point record to deliver the event for.
- * @param flags Internal event flags. The called does not need to provide
- * TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
- * they are set appropriately.
- * @param resource The client resource to deliver to, or 0 for all clients.
- */
-static void
-EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
-{
- InternalEvent event;
-
- flags |= TOUCH_CLIENT_ID;
- if (ti->emulate_pointer)
- flags |= TOUCH_POINTER_EMULATED;
- TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource);
- GetDixTouchEnd(&event, dev, ti, flags);
- DeliverTouchEvents(dev, ti, &event, resource);
-}
-
-/**
* Find the oldest touch that still has a pointer emulation client.
*
* Pointer emulation can only be performed for the oldest touch. Otherwise, the
@@ -1129,10 +1104,10 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
TouchOwnershipEvent *ev)
{
TouchListener *listener = &ti->listeners[0]; /* new owner */
+ int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
/* Deliver the ownership */
- if (listener->state == LISTENER_AWAITING_OWNER ||
- listener->state == LISTENER_EARLY_ACCEPT)
+ if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
listener->listener);
else if (listener->state == LISTENER_AWAITING_BEGIN) {
@@ -1146,15 +1121,24 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
TouchEventHistoryReplay(ti, dev, listener->listener);
}
- /* If we've just removed the last grab and the touch has physically
- * ended, send a TouchEnd event too and finalise the touch. */
- if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) {
- EmitTouchEnd(dev, ti, 0, 0);
- TouchEndTouch(dev, ti);
- return;
+ /* New owner has Begin/Update but not end. If touch is pending_finish,
+ * emulate the TouchEnd now */
+ if (ti->pending_finish) {
+ TouchEmitTouchEnd(dev, ti, 0, 0);
+
+ /* If the last owner is not a touch grab, finalise the touch, we
+ won't get more correspondence on this.
+ */
+ if (ti->num_listeners == 1 &&
+ (ti->num_grabs == 0 ||
+ listener->grab->grabtype != XI2 ||
+ !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
+ TouchEndTouch(dev, ti);
+ return;
+ }
}
- if (listener->state == LISTENER_EARLY_ACCEPT)
+ if (accepted_early)
ActivateEarlyAccept(dev, ti);
}
@@ -1198,7 +1182,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
for (i = 0; i < ti->num_listeners; i++) {
if (ti->listeners[i].listener == resource) {
if (ti->listeners[i].state != LISTENER_HAS_END)
- EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
+ TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
break;
}
}
@@ -1225,9 +1209,16 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
* touchpoint if it is pending finish.
*/
static void
-ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
- TouchOwnershipEvent *ev)
+ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
+ DeviceIntPtr dev)
{
+ TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
+
+ if (!ti) {
+ DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
+ dev->name, ev->type, ev->touchid);
+ return;
+ }
if (ev->reason == XIRejectTouch)
TouchRejected(dev, ti, ev->resource, ev);
@@ -1238,12 +1229,12 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
* already seen the end. This ensures that the touch record is ended in
* the server. */
if (ti->listeners[0].state == LISTENER_HAS_END)
- EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
+ TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
/* The touch owner has accepted the touch. Send TouchEnd events to
* everyone else, and truncate the list of listeners. */
for (i = 1; i < ti->num_listeners; i++)
- EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
+ TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
while (ti->num_listeners > 1)
TouchRemoveListener(ti, ti->listeners[1].listener);
@@ -1412,7 +1403,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
}
if (!deliveries)
- DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
+ deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
/* We must accept the touch sequence once a pointer listener has
* received one event past ButtonPress. */
@@ -1420,8 +1411,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
!(ev->device_event.flags & TOUCH_CLIENT_ID))
TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
- if (ev->any.type == ET_TouchEnd &&
- !(ev->device_event.flags & TOUCH_CLIENT_ID) &&
+ if (deliveries && ev->any.type == ET_TouchEnd &&
!dev->button->buttonsDown &&
dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
(*dev->deviceGrab.DeactivateGrab) (dev);
@@ -1440,8 +1430,11 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
*/
if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
TouchListener *l;
+ GrabPtr g;
devgrab = dev->deviceGrab.grab;
+ g = AllocGrab(devgrab);
+ BUG_WARN(!g);
*dev->deviceGrab.sync.event = ev->device_event;
@@ -1450,8 +1443,8 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
* event selection. Thus, we update the last listener in the array.
*/
l = &ti->listeners[ti->num_listeners - 1];
- l->listener = devgrab->resource;
- l->grab = devgrab;
+ l->listener = g->resource;
+ l->grab = g;
//l->resource_type = RT_NONE;
if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
@@ -1540,12 +1533,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
if (!t)
return;
- if (ev->any.type == ET_TouchOwnership)
- touchid = ev->touch_ownership_event.touchid;
- else
- touchid = ev->device_event.touchid;
+ touchid = ev->device_event.touchid;
- if (type == ET_TouchBegin) {
+ if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
emulate_pointer);
}
@@ -1612,23 +1602,19 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
* called after event type mutation. Touch end events are always processed
* in order to end touch records. */
/* FIXME: check this */
- if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) ||
+ if ((type == ET_TouchBegin &&
+ !(ev->device_event.flags & TOUCH_REPLAYING) &&
+ !TouchBuildSprite(dev, ti, ev)) ||
(type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
return;
- /* TouchOwnership events are handled separately from the rest, as they
- * have more complex semantics. */
- if (ev->any.type == ET_TouchOwnership)
- ProcessTouchOwnershipEvent(dev, ti, &ev->touch_ownership_event);
- else {
- TouchCopyValuatorData(&ev->device_event, ti);
- /* WARNING: the event type may change to TouchUpdate in
- * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
- * owner */
- DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0);
- if (ev->any.type == ET_TouchEnd)
- TouchEndTouch(dev, ti);
- }
+ TouchCopyValuatorData(&ev->device_event, ti);
+ /* WARNING: the event type may change to TouchUpdate in
+ * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
+ * owner */
+ DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
+ if (ev->any.type == ET_TouchEnd)
+ TouchEndTouch(dev, ti);
if (emulate_pointer)
UpdateDeviceState(dev, &ev->device_event);
@@ -1824,10 +1810,14 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
break;
case ET_TouchBegin:
case ET_TouchUpdate:
- case ET_TouchOwnership:
case ET_TouchEnd:
ProcessTouchEvent(ev, device);
break;
+ case ET_TouchOwnership:
+ /* TouchOwnership events are handled separately from the rest, as they
+ * have more complex semantics. */
+ ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
+ break;
case ET_BarrierHit:
case ET_BarrierLeave:
ProcessBarrierEvent(ev, device);
@@ -1852,6 +1842,14 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
listener->type == LISTENER_POINTER_GRAB) {
rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
grab, xi2mask);
+ if (rc == Success) {
+ listener->state = LISTENER_IS_OWNER;
+ /* async grabs cannot replay, so automatically accept this touch */
+ if (dev->deviceGrab.grab &&
+ dev->deviceGrab.fromPassiveGrab &&
+ dev->deviceGrab.grab->pointerMode == GrabModeAsync)
+ ActivateEarlyAccept(dev, ti);
+ }
goto out;
}
@@ -1869,7 +1867,7 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
if (has_ownershipmask)
TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
- if (!has_ownershipmask || listener->type == LISTENER_REGULAR)
+ if (listener->type == LISTENER_REGULAR)
state = LISTENER_HAS_ACCEPTED;
else
state = LISTENER_IS_OWNER;
@@ -1892,13 +1890,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
grab, xi2mask);
- if (ti->num_listeners > 1) {
- ev->any.type = ET_TouchUpdate;
- ev->device_event.flags |= TOUCH_PENDING_END;
- if (!(ev->device_event.flags & TOUCH_CLIENT_ID))
- ti->pending_finish = TRUE;
- }
-
+ /* Once we send a TouchEnd to a legacy listener, we're already well
+ * past the accepting/rejecting stage (can only happen on
+ * GrabModeSync + replay. This listener now gets the end event,
+ * and we can continue.
+ */
+ if (rc == Success)
+ listener->state = LISTENER_HAS_END;
goto out;
}
@@ -1924,7 +1922,7 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
if ((ti->num_listeners > 1 ||
- listener->state != LISTENER_HAS_ACCEPTED) &&
+ (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
(ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
ev->any.type = ET_TouchUpdate;
ev->device_event.flags |= TOUCH_PENDING_END;
@@ -2025,6 +2023,9 @@ InitProximityClassDeviceStruct(DeviceIntPtr dev)
{
ProximityClassPtr proxc;
+ BUG_RETURN_VAL(dev == NULL, FALSE);
+ BUG_RETURN_VAL(dev->proximity != NULL, FALSE);
+
proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
if (!proxc)
return FALSE;
@@ -2050,10 +2051,10 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
{
AxisInfoPtr ax;
- if (!dev || !dev->valuator || (minval > maxval && mode == Absolute))
- return FALSE;
- if (axnum >= dev->valuator->numAxes)
- return FALSE;
+ BUG_RETURN_VAL(dev == NULL, FALSE);
+ BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
+ BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
+ BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE);
ax = dev->valuator->axes + axnum;
@@ -2083,8 +2084,9 @@ SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
InternalEvent dce;
DeviceIntPtr master;
- if (!dev || !dev->valuator || axnum >= dev->valuator->numAxes)
- return FALSE;
+ BUG_RETURN_VAL(dev == NULL, FALSE);
+ BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
+ BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
switch (type) {
case SCROLL_TYPE_VERTICAL:
@@ -2224,8 +2226,7 @@ GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
}
/**
- * Grab the given key. If grabtype is XI, the key is a keycode. If
- * grabtype is XI2, the key is a keysym.
+ * Grab the given key.
*/
int
GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
@@ -2853,7 +2854,7 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
(deliveryMask & DeviceButtonGrabMask)) {
GrabPtr tempGrab;
- tempGrab = AllocGrab();
+ tempGrab = AllocGrab(NULL);
if (!tempGrab)
return;
diff --git a/xorg-server/Xi/extinit.c b/xorg-server/Xi/extinit.c
index 619d0e468..a49a42152 100644
--- a/xorg-server/Xi/extinit.c
+++ b/xorg-server/Xi/extinit.c
@@ -848,24 +848,24 @@ SBarrierEvent(xXIBarrierEvent * from,
*to = *from;
- swaps(&from->sequenceNumber);
- swapl(&from->length);
- swaps(&from->evtype);
- swapl(&from->time);
- swaps(&from->deviceid);
- swaps(&from->sourceid);
- swapl(&from->event);
- swapl(&from->root);
- swapl(&from->root_x);
- swapl(&from->root_y);
-
- swapl(&from->dx.integral);
- swapl(&from->dx.frac);
- swapl(&from->dy.integral);
- swapl(&from->dy.frac);
- swapl(&from->dtime);
- swapl(&from->barrier);
- swapl(&from->eventid);
+ swaps(&to->sequenceNumber);
+ swapl(&to->length);
+ swaps(&to->evtype);
+ swapl(&to->time);
+ swaps(&to->deviceid);
+ swaps(&to->sourceid);
+ swapl(&to->event);
+ swapl(&to->root);
+ swapl(&to->root_x);
+ swapl(&to->root_y);
+
+ swapl(&to->dx.integral);
+ swapl(&to->dx.frac);
+ swapl(&to->dy.integral);
+ swapl(&to->dy.frac);
+ swapl(&to->dtime);
+ swapl(&to->barrier);
+ swapl(&to->eventid);
}
/** Event swapping function for XI2 events. */
@@ -1171,6 +1171,8 @@ IResetProc(ExtensionEntry * unused)
free(xi_all_devices.name);
free(xi_all_master_devices.name);
+
+ XIBarrierReset();
}
/***********************************************************************
diff --git a/xorg-server/Xi/setdval.c b/xorg-server/Xi/setdval.c
index 79f3d2ab4..1e2e59772 100644
--- a/xorg-server/Xi/setdval.c
+++ b/xorg-server/Xi/setdval.c
@@ -109,6 +109,9 @@ ProcXSetDeviceValuators(ClientPtr client)
if (dev->valuator == NULL)
return BadMatch;
+ if (IsXTestDevice(dev, NULL))
+ return BadMatch;
+
if (stuff->first_valuator + stuff->num_valuators > dev->valuator->numAxes)
return BadValue;
diff --git a/xorg-server/Xi/setmode.c b/xorg-server/Xi/setmode.c
index df3880d11..a57cc7b08 100644
--- a/xorg-server/Xi/setmode.c
+++ b/xorg-server/Xi/setmode.c
@@ -103,6 +103,10 @@ ProcXSetDeviceMode(ClientPtr client)
return rc;
if (dev->valuator == NULL)
return BadMatch;
+
+ if (IsXTestDevice(dev, NULL))
+ return BadMatch;
+
if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
rep.status = AlreadyGrabbed;
else
diff --git a/xorg-server/Xi/ungrdevb.c b/xorg-server/Xi/ungrdevb.c
index c4632fadc..b02510ea0 100644
--- a/xorg-server/Xi/ungrdevb.c
+++ b/xorg-server/Xi/ungrdevb.c
@@ -127,7 +127,7 @@ ProcXUngrabDeviceButton(ClientPtr client)
(stuff->modifiers & ~AllModifiersMask))
return BadValue;
- temporaryGrab = AllocGrab();
+ temporaryGrab = AllocGrab(NULL);
if (!temporaryGrab)
return BadAlloc;
diff --git a/xorg-server/Xi/ungrdevk.c b/xorg-server/Xi/ungrdevk.c
index 3273878d3..f98117168 100644
--- a/xorg-server/Xi/ungrdevk.c
+++ b/xorg-server/Xi/ungrdevk.c
@@ -134,7 +134,7 @@ ProcXUngrabDeviceKey(ClientPtr client)
(stuff->modifiers & ~AllModifiersMask))
return BadValue;
- temporaryGrab = AllocGrab();
+ temporaryGrab = AllocGrab(NULL);
if (!temporaryGrab)
return BadAlloc;
diff --git a/xorg-server/Xi/xibarriers.c b/xorg-server/Xi/xibarriers.c
index b8a27af25..a83457b10 100644
--- a/xorg-server/Xi/xibarriers.c
+++ b/xorg-server/Xi/xibarriers.c
@@ -916,3 +916,15 @@ XIBarrierInit(void)
return PointerBarrierType;
}
+
+void
+XIBarrierReset(void)
+{
+ int i;
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ BarrierScreenPtr cs = GetBarrierScreen(pScreen);
+ free(cs);
+ SetBarrierScreen(pScreen, NULL);
+ }
+}
diff --git a/xorg-server/Xi/xibarriers.h b/xorg-server/Xi/xibarriers.h
index 11e84ec9f..f61b48214 100644
--- a/xorg-server/Xi/xibarriers.h
+++ b/xorg-server/Xi/xibarriers.h
@@ -36,8 +36,8 @@ int
XIDestroyPointerBarrier(ClientPtr client,
xXFixesDestroyPointerBarrierReq * stuff);
-Bool
-XIBarrierInit(void);
+Bool XIBarrierInit(void);
+void XIBarrierReset(void);
int SProcXIBarrierReleasePointer(ClientPtr client);
int ProcXIBarrierReleasePointer(ClientPtr client);
diff --git a/xorg-server/Xi/xigrabdev.c b/xorg-server/Xi/xigrabdev.c
index a4344be4a..086e275d8 100644
--- a/xorg-server/Xi/xigrabdev.c
+++ b/xorg-server/Xi/xigrabdev.c
@@ -67,6 +67,8 @@ ProcXIGrabDevice(ClientPtr client)
uint8_t status;
GrabMask mask = { 0 };
int mask_len;
+ unsigned int keyboard_mode;
+ unsigned int pointer_mode;
REQUEST(xXIGrabDeviceReq);
REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq);
@@ -78,6 +80,15 @@ ProcXIGrabDevice(ClientPtr client)
if (!IsMaster(dev))
stuff->paired_device_mode = GrabModeAsync;
+ if (IsKeyboardDevice(dev)) {
+ keyboard_mode = stuff->grab_mode;
+ pointer_mode = stuff->paired_device_mode;
+ }
+ else {
+ keyboard_mode = stuff->paired_device_mode;
+ pointer_mode = stuff->grab_mode;
+ }
+
if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1],
stuff->mask_len * 4) != Success)
return BadValue;
@@ -91,8 +102,8 @@ ProcXIGrabDevice(ClientPtr client)
xi2mask_set_one_mask(mask.xi2mask, dev->id, (unsigned char *) &stuff[1],
mask_len);
- ret = GrabDevice(client, dev, stuff->grab_mode,
- stuff->paired_device_mode,
+ ret = GrabDevice(client, dev, pointer_mode,
+ keyboard_mode,
stuff->grab_window,
stuff->owner_events,
stuff->time,
diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c
index b5b9e86c4..28c502f69 100644
--- a/xorg-server/Xi/xipassivegrab.c
+++ b/xorg-server/Xi/xipassivegrab.c
@@ -307,7 +307,7 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
- tempGrab = AllocGrab();
+ tempGrab = AllocGrab(NULL);
if (!tempGrab)
return BadAlloc;