#include "X.h"
#include "misc.h"
#define NEED_EVENTS
#include "Xproto.h"
#include "windowstr.h"
#include "inputstr.h"
#include "cursorstr.h"
#include "dixgrabs.h"
#define BITMASK(i) (((Mask)1) << ((i) & 31))
#define MASKIDX(i) ((i) >> 5)
#define MASKWORD(buf, i) buf[MASKIDX(i)]
#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
GrabPtr
CreateGrab(
int client,
DeviceIntPtr device,
WindowPtr window,
Mask eventMask,
Bool ownerEvents, Bool keyboardMode, Bool pointerMode,
DeviceIntPtr modDevice,
unsigned short modifiers,
int type,
KeyCode keybut,
WindowPtr confineTo,
CursorPtr cursor)
{
GrabPtr grab;
grab = (GrabPtr)xalloc(sizeof(GrabRec));
if (!grab)
return (GrabPtr)NULL;
grab->resource = FakeClientID(client);
grab->device = device;
grab->coreGrab = ((device == inputInfo.keyboard) ||
(device == inputInfo.pointer));
grab->window = window;
grab->eventMask = eventMask;
grab->ownerEvents = ownerEvents;
grab->keyboardMode = keyboardMode;
grab->pointerMode = pointerMode;
grab->modifiersDetail.exact = modifiers;
grab->modifiersDetail.pMask = NULL;
grab->modifierDevice = modDevice;
grab->coreMods = ((modDevice == inputInfo.keyboard) ||
(modDevice == inputInfo.pointer));
grab->type = type;
grab->detail.exact = keybut;
grab->detail.pMask = NULL;
grab->confineTo = confineTo;
grab->cursor = cursor;
if (cursor)
cursor->refcnt++;
return grab;
}
static void
FreeGrab(GrabPtr pGrab)
{
if (pGrab->modifiersDetail.pMask != NULL)
xfree(pGrab->modifiersDetail.pMask);
if (pGrab->detail.pMask != NULL)
xfree(pGrab->detail.pMask);
if (pGrab->cursor)
FreeCursor(pGrab->cursor, (Cursor)0);
xfree(pGrab);
}
int
DeletePassiveGrab(value, id)
pointer value;
XID id;
{
register GrabPtr g, prev;
GrabPtr pGrab = (GrabPtr)value;
prev = 0;
for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next)
{
if (pGrab == g)
{
if (prev)
prev->next = g->next;
else
if (!(pGrab->window->optional->passiveGrabs = g->next))
CheckWindowOptionalNeed (pGrab->window);
break;
}
prev = g;
}
FreeGrab(pGrab);
return Success;
}
static Mask *
DeleteDetailFromMask(Mask *pDetailMask, unsigned short detail)
{
register Mask *mask;
register int i;
mask = (Mask *)xalloc(sizeof(Mask) * MasksPerDetailMask);
if (mask)
{
if (pDetailMask)
for (i = 0; i < MasksPerDetailMask; i++)
mask[i]= pDetailMask[i];
else
for (i = 0; i < MasksPerDetailMask; i++)
mask[i]= ~0L;
BITCLEAR(mask, detail);
}
return mask;
}
static Bool
IsInGrabMask(
DetailRec firstDetail,
DetailRec secondDetail,
unsigned short exception)
{
if (firstDetail.exact == exception)
{
if (firstDetail.pMask == NULL)
return TRUE;
if (secondDetail.exact == exception)
return FALSE;
if (GETBIT(firstDetail.pMask, secondDetail.exact))
return TRUE;
}
return FALSE;
}
static Bool
IdenticalExactDetails(
unsigned short firstExact,
unsigned short secondExact,
unsigned short exception)
{
if ((firstExact == exception) || (secondExact == exception))
return FALSE;
if (firstExact == secondExact)
return TRUE;
return FALSE;
}
static Bool
DetailSupersedesSecond(
DetailRec firstDetail,
DetailRec secondDetail,
unsigned short exception)
{
if (IsInGrabMask(firstDetail, secondDetail, exception))
return TRUE;
if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact,
exception))
return TRUE;
return FALSE;
}
static Bool
GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
{
if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail,
pSecondGrab->modifiersDetail,
(unsigned short)AnyModifier))
return FALSE;
if (DetailSupersedesSecond(pFirstGrab->detail,
pSecondGrab->detail, (unsigned short)AnyKey))
return TRUE;
return FALSE;
}
Bool
GrabMatchesSecond(pFirstGrab, pSecondGrab)
GrabPtr pFirstGrab, pSecondGrab;
{
if ((pFirstGrab->device != pSecondGrab->device) ||
(pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
(pFirstGrab->type != pSecondGrab->type))
return FALSE;
if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
GrabSupersedesSecond(pSecondGrab, pFirstGrab))
return TRUE;
if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail,
(unsigned short)AnyKey)
&&
DetailSupersedesSecond(pFirstGrab->modifiersDetail,
pSecondGrab->modifiersDetail,
(unsigned short)AnyModifier))
return TRUE;
if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail,
(unsigned short)AnyKey)
&&
DetailSupersedesSecond(pSecondGrab->modifiersDetail,
pFirstGrab->modifiersDetail,
(unsigned short)AnyModifier))
return TRUE;
return FALSE;
}
int
AddPassiveGrabToList(pGrab)
GrabPtr pGrab;
{
GrabPtr grab;
for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
{
if (GrabMatchesSecond(pGrab, grab))
{
if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
{
FreeGrab(pGrab);
return BadAccess;
}
}
}
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))
return Success;
return BadAlloc;
}
Bool
DeletePassiveGrabFromList(pMinuendGrab)
GrabPtr pMinuendGrab;
{
register GrabPtr grab;
GrabPtr *deletes, *adds;
Mask ***updates, **details;
int i, ndels, nadds, nups;
Bool ok;
#define UPDATE(mask,exact) \
if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
ok = FALSE; \
else \
updates[nups++] = &(mask)
i = 0;
for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next)
i++;
if (!i)
return TRUE;
deletes = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr));
adds = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr));
updates = (Mask ***)ALLOCATE_LOCAL(i * sizeof(Mask **));
details = (Mask **)ALLOCATE_LOCAL(i * sizeof(Mask *));
if (!deletes || !adds || !updates || !details)
{
if (details) DEALLOCATE_LOCAL(details);
if (updates) DEALLOCATE_LOCAL(updates);
if (adds) DEALLOCATE_LOCAL(adds);
if (deletes) DEALLOCATE_LOCAL(deletes);
return FALSE;
}
ndels = nadds = nups = 0;
ok = TRUE;
for (grab = wPassiveGrabs(pMinuendGrab->window);
grab && ok;
grab = grab->next)
{
if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) ||
!GrabMatchesSecond(grab, pMinuendGrab))
continue;
if (GrabSupersedesSecond(pMinuendGrab, grab))
{
deletes[ndels++] = grab;
}
else if ((grab->detail.exact == AnyKey)
&& (grab->modifiersDetail.exact != AnyModifier))
{
UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
}
else if ((grab->modifiersDetail.exact == AnyModifier)
&& (grab->detail.exact != AnyKey))
{
UPDATE(grab->modifiersDetail.pMask,
pMinuendGrab->modifiersDetail.exact);
}
else if ((pMinuendGrab->detail.exact != AnyKey)
&& (pMinuendGrab->modifiersDetail.exact != AnyModifier))
{
GrabPtr pNewGrab;
UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device,
grab->window, (Mask)grab->eventMask,
(Bool)grab->ownerEvents,
(Bool)grab->keyboardMode,
(Bool)grab->pointerMode,
grab->modifierDevice,
AnyModifier, (int)grab->type,
pMinuendGrab->detail.exact,
grab->confineTo, grab->cursor);
if (!pNewGrab)
ok = FALSE;
else if (!(pNewGrab->modifiersDetail.pMask =
DeleteDetailFromMask(grab->modifiersDetail.pMask,
pMinuendGrab->modifiersDetail.exact))
||
(!pNewGrab->window->optional &&
!MakeWindowOptional(pNewGrab->window)))
{
FreeGrab(pNewGrab);
ok = FALSE;
}
else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB,
(pointer)pNewGrab))
ok = FALSE;
else
adds[nadds++] = pNewGrab;
}
else if (pMinuendGrab->detail.exact == AnyKey)
{
UPDATE(grab->modifiersDetail.pMask,
pMinuendGrab->modifiersDetail.exact);
}
else
{
UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
}
}
if (!ok)
{
for (i = 0; i < nadds; i++)
FreeResource(adds[i]->resource, RT_NONE);
for (i = 0; i < nups; i++)
xfree(details[i]);
}
else
{
for (i = 0; i < ndels; i++)
FreeResource(deletes[i]->resource, RT_NONE);
for (i = 0; i < nadds; i++)
{
grab = adds[i];
grab->next = grab->window->optional->passiveGrabs;
grab->window->optional->passiveGrabs = grab;
}
for (i = 0; i < nups; i++)
{
xfree(*updates[i]);
*updates[i] = details[i];
}
}
DEALLOCATE_LOCAL(details);
DEALLOCATE_LOCAL(updates);
DEALLOCATE_LOCAL(adds);
DEALLOCATE_LOCAL(deletes);
return ok;
#undef UPDATE
}