dix: Move grab check and activation logic to CheckPassiveGrab()

This is needed for future pointer emulation work.

Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Chase Douglas 2011-11-17 17:40:24 -08:00 committed by Peter Hutterer
parent c53651dabc
commit 9ee62cd8ce
1 changed files with 204 additions and 180 deletions

View File

@ -3634,6 +3634,207 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
return FALSE;
}
/**
* Check an individual grab against an event to determine if a passive grab
* should be activated.
* If activate is true and a passive grab is found, it will be activated, and
* the event will be delivered to the client.
*
* @param device The device of the event to check.
* @param grab The grab to check.
* @param event The current device event.
* @param checkCore Check for core grabs too.
* @param activate Whether to activate a matching grab.
* @param tempGrab A pre-allocated temporary grab record for matching. This
* must have the window and device values filled in.
* @param[out] grab_return The modified value of grab, to be used in the
* caller for grab activation if a this function returns TRUE. May be NULL.
*
* @return Whether the grab matches the event.
*/
static Bool
CheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
Bool checkCore, Bool activate, GrabPtr tempGrab, GrabPtr *grab_return)
{
static const int CORE_MATCH = 0x1;
static const int XI_MATCH = 0x2;
static const int XI2_MATCH = 0x4;
SpritePtr pSprite = device->spriteInfo->sprite;
GrabInfoPtr grabinfo;
DeviceIntPtr gdev;
XkbSrvInfoPtr xkbi = NULL;
xEvent *xE = NULL;
int match = 0;
int count;
int rc;
gdev = grab->modifierDevice;
if (grab->grabtype == GRABTYPE_CORE)
{
gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
} else if (grab->grabtype == GRABTYPE_XI2)
{
/* if the device is an attached slave device, gdev must be the
* attached master keyboard. Since the slave may have been
* reattached after the grab, the modifier device may not be the
* same. */
if (!IsMaster(grab->device) && !IsFloating(device))
gdev = GetMaster(device, MASTER_KEYBOARD);
}
if (gdev && gdev->key)
xkbi= gdev->key->xkbInfo;
tempGrab->modifierDevice = grab->modifierDevice;
tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
/* Check for XI2 and XI grabs first */
tempGrab->type = GetXI2Type(event->any.type);
tempGrab->grabtype = GRABTYPE_XI2;
if (GrabMatchesSecond(tempGrab, grab, FALSE))
match = XI2_MATCH;
if (!match)
{
tempGrab->grabtype = GRABTYPE_XI;
if ((tempGrab->type = GetXIType(event->any.type)) &&
(GrabMatchesSecond(tempGrab, grab, FALSE)))
match = XI_MATCH;
}
/* Check for a core grab (ignore the device when comparing) */
if (!match && checkCore)
{
tempGrab->grabtype = GRABTYPE_CORE;
if ((tempGrab->type = GetCoreType(event->any.type)) &&
(GrabMatchesSecond(tempGrab, grab, TRUE)))
match = CORE_MATCH;
}
if (!match || (grab->confineTo &&
(!grab->confineTo->realized ||
!BorderSizeNotEmpty(device, grab->confineTo))))
return FALSE;
*grab_return = grab;
grabinfo = &device->deviceGrab;
/* In some cases a passive core grab may exist, but the client
* already has a core grab on some other device. In this case we
* must not get the grab, otherwise we may never ungrab the
* device.
*/
if (grab->grabtype == GRABTYPE_CORE)
{
DeviceIntPtr other;
BOOL interfering = FALSE;
/* A passive grab may have been created for a different device
than it is assigned to at this point in time.
Update the grab's device and modifier device to reflect the
current state.
Since XGrabDeviceButton requires to specify the
modifierDevice explicitly, we don't override this choice.
*/
if (tempGrab->type < GenericEvent)
{
grab->device = device;
grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
}
for (other = inputInfo.devices; other; other = other->next)
{
GrabPtr othergrab = other->deviceGrab.grab;
if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
SameClient(grab, rClient(othergrab)) &&
((IsPointerDevice(grab->device) &&
IsPointerDevice(othergrab->device)) ||
(IsKeyboardDevice(grab->device) &&
IsKeyboardDevice(othergrab->device))))
{
interfering = TRUE;
break;
}
}
if (interfering)
return FALSE;
}
if (!activate)
return TRUE;
else if (!GetXIType(event->any.type) && !GetCoreType(event->any.type))
{
ErrorF("Event type %d in CheckPassiveGrabsOnWindow is neither"
" XI 1.x nor core\n", event->any.type);
*grab_return = NULL;
return TRUE;
}
/* The only consumers of corestate are Xi 1.x and core events, which
* are guaranteed to come from DeviceEvents. */
if (match & (XI_MATCH | CORE_MATCH))
{
event->device_event.corestate &= 0x1f00;
event->device_event.corestate |= tempGrab->modifiersDetail.exact &
(~0x1f00);
}
if (match & CORE_MATCH)
{
rc = EventToCore(event, &xE, &count);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: core conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->any.type, rc);
return TRUE;
}
} else if (match & XI2_MATCH)
{
rc = EventToXI2(event, &xE);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->any.type, rc);
return TRUE;
}
count = 1;
} else
{
rc = EventToXI(event, &xE, &count);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: XI conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->any.type, rc);
return TRUE;
}
}
(*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
if (xE)
{
FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
/* XXX: XACE? */
TryClientEvents(rClient(grab), device, xE, count,
GetEventFilter(device, xE),
GetEventFilter(device, xE), grab);
}
if (grabinfo->sync.state == FROZEN_NO_EVENT)
{
if (!grabinfo->sync.event)
grabinfo->sync.event = calloc(1, sizeof(DeviceEvent));
*grabinfo->sync.event = event->device_event;
grabinfo->sync.state = FROZEN_WITH_EVENT;
}
free(xE);
return TRUE;
}
/**
* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
* passive grab set on the window to be activated.
@ -3655,14 +3856,8 @@ CheckPassiveGrabsOnWindow(
BOOL checkCore,
BOOL activate)
{
SpritePtr pSprite = device->spriteInfo->sprite;
GrabPtr grab = wPassiveGrabs(pWin);
GrabPtr tempGrab;
GrabInfoPtr grabinfo;
#define CORE_MATCH 0x1
#define XI_MATCH 0x2
#define XI2_MATCH 0x4
int match = 0;
if (!grab)
return NULL;
@ -3690,185 +3885,14 @@ CheckPassiveGrabsOnWindow(
tempGrab->detail.pMask = NULL;
tempGrab->modifiersDetail.pMask = NULL;
tempGrab->next = NULL;
for (; grab; grab = grab->next)
{
DeviceIntPtr gdev;
XkbSrvInfoPtr xkbi = NULL;
xEvent *xE = NULL;
int count, rc;
gdev= grab->modifierDevice;
if (grab->grabtype == GRABTYPE_CORE)
{
gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
} else if (grab->grabtype == GRABTYPE_XI2)
{
/* if the device is an attached slave device, gdev must be the
* attached master keyboard. Since the slave may have been
* reattached after the grab, the modifier device may not be the
* same. */
if (!IsMaster(grab->device) && !IsFloating(device))
gdev = GetMaster(device, MASTER_KEYBOARD);
}
if (gdev && gdev->key)
xkbi= gdev->key->xkbInfo;
tempGrab->modifierDevice = grab->modifierDevice;
tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
/* Check for XI2 and XI grabs first */
tempGrab->type = GetXI2Type(event->any.type);
tempGrab->grabtype = GRABTYPE_XI2;
if (GrabMatchesSecond(tempGrab, grab, FALSE))
match = XI2_MATCH;
if (!match)
{
tempGrab->grabtype = GRABTYPE_XI;
if ((tempGrab->type = GetXIType(event->any.type)) &&
(GrabMatchesSecond(tempGrab, grab, FALSE)))
match = XI_MATCH;
}
/* Check for a core grab (ignore the device when comparing) */
if (!match && checkCore)
{
tempGrab->grabtype = GRABTYPE_CORE;
if ((tempGrab->type = GetCoreType(event->any.type)) &&
(GrabMatchesSecond(tempGrab, grab, TRUE)))
match = CORE_MATCH;
}
if (!match || (grab->confineTo &&
(!grab->confineTo->realized ||
!BorderSizeNotEmpty(device, grab->confineTo))))
continue;
grabinfo = &device->deviceGrab;
/* In some cases a passive core grab may exist, but the client
* already has a core grab on some other device. In this case we
* must not get the grab, otherwise we may never ungrab the
* device.
*/
if (grab->grabtype == GRABTYPE_CORE)
{
DeviceIntPtr other;
BOOL interfering = FALSE;
/* A passive grab may have been created for a different device
than it is assigned to at this point in time.
Update the grab's device and modifier device to reflect the
current state.
Since XGrabDeviceButton requires to specify the
modifierDevice explicitly, we don't override this choice.
*/
if (tempGrab->type < GenericEvent)
{
grab->device = device;
grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
}
for (other = inputInfo.devices; other; other = other->next)
{
GrabPtr othergrab = other->deviceGrab.grab;
if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
SameClient(grab, rClient(othergrab)) &&
((IsPointerDevice(grab->device) &&
IsPointerDevice(othergrab->device)) ||
(IsKeyboardDevice(grab->device) &&
IsKeyboardDevice(othergrab->device))))
{
interfering = TRUE;
break;
}
}
if (interfering)
continue;
}
if (!activate)
if (CheckPassiveGrab(device, grab, event, checkCore, activate,
tempGrab, &grab))
break;
else if (!GetXIType(event->any.type) && !GetCoreType(event->any.type))
{
ErrorF("Event type %d in CheckPassiveGrabsOnWindow is neither"
" XI 1.x nor core\n", event->any.type);
grab = NULL;
break;
}
/* The only consumers of corestate are Xi 1.x and core events, which
* are guaranteed to come from DeviceEvents. */
if (match & (XI_MATCH | CORE_MATCH))
{
event->device_event.corestate &= 0x1f00;
event->device_event.corestate |= tempGrab->modifiersDetail.exact &
(~0x1f00);
}
if (match & CORE_MATCH)
{
rc = EventToCore(event, &xE, &count);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: core conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->any.type, rc);
continue;
}
} else if (match & XI2_MATCH)
{
rc = EventToXI2(event, &xE);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->any.type, rc);
continue;
}
count = 1;
} else
{
rc = EventToXI(event, &xE, &count);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: XI conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->any.type, rc);
continue;
}
}
(*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
if (xE)
{
FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
/* XXX: XACE? */
TryClientEvents(rClient(grab), device, xE, count,
GetEventFilter(device, xE),
GetEventFilter(device, xE), grab);
}
if (grabinfo->sync.state == FROZEN_NO_EVENT)
{
if (!grabinfo->sync.event)
grabinfo->sync.event = calloc(1, sizeof(DeviceEvent));
*grabinfo->sync.event = event->device_event;
grabinfo->sync.state = FROZEN_WITH_EVENT;
}
free(xE);
break;
}
FreeGrab(tempGrab);
return grab;
#undef CORE_MATCH
#undef XI_MATCH
#undef XI2_MATCH
}
/**