aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix')
-rw-r--r--xorg-server/dix/devices.c3
-rw-r--r--xorg-server/dix/events.c288
-rw-r--r--xorg-server/dix/grabs.c84
-rw-r--r--xorg-server/dix/inpututils.c181
4 files changed, 407 insertions, 149 deletions
diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c
index 37cbcdb78..e448eab62 100644
--- a/xorg-server/dix/devices.c
+++ b/xorg-server/dix/devices.c
@@ -73,6 +73,7 @@ SOFTWARE.
#include "dixevents.h"
#include "mipointer.h"
#include "eventstr.h"
+#include "dixgrabs.h"
#include <X11/extensions/XI.h>
#include <X11/extensions/XI2.h>
@@ -273,6 +274,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
dev->deviceGrab.grabTime = currentTime;
dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
+ dev->deviceGrab.activeGrab = AllocGrab();
XkbSetExtension(dev, ProcessKeyboardEvent);
@@ -941,6 +943,7 @@ CloseDevice(DeviceIntPtr dev)
}
}
+ FreeGrab(dev->deviceGrab.activeGrab);
free(dev->deviceGrab.sync.event);
free(dev->config_info); /* Allocated in xf86ActivateDevice. */
free(dev->last.scroll);
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 4847db005..59caa918f 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -420,12 +420,6 @@ GetXI2EventFilterMask(int evtype)
return (1 << (evtype % 8));
}
-static inline int
-GetXI2EventFilterOffset(int evtype)
-{
- return (evtype / 8);
-}
-
/**
* For the given event, return the matching event filter. This filter may then
* be AND'ed with the selected event mask.
@@ -459,12 +453,15 @@ GetEventFilter(DeviceIntPtr dev, xEvent *event)
* for the event_type.
*/
static int
-GetXI2MaskByte(unsigned char xi2mask[][XI2MASKSIZE], DeviceIntPtr dev, int event_type)
+GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type)
{
- int byte = GetXI2EventFilterOffset(event_type);
- return xi2mask[dev->id][byte] |
- xi2mask[XIAllDevices][byte] |
- (IsMaster(dev) ? xi2mask[XIAllMasterDevices][byte] : 0);
+ /* we just return the matching filter because that's the only use
+ * for this mask anyway.
+ */
+ if (xi2mask_isset(mask, dev, event_type))
+ return GetXI2EventFilterMask(event_type);
+ else
+ return 0;
}
@@ -476,16 +473,14 @@ Bool
WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
{
OtherInputMasks *inputMasks = wOtherInputMasks(win);
- int filter;
int evtype;
if (!inputMasks || xi2_get_type(ev) == 0)
return 0;
evtype = ((xGenericEvent*)ev)->evtype;
- filter = GetEventFilter(dev, ev);
- return !!(GetXI2MaskByte(inputMasks->xi2mask, dev, evtype) & filter);
+ return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
}
Mask
@@ -1132,12 +1127,14 @@ NoticeEventTime(InternalEvent *ev)
void
EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
{
- QdEventPtr tail = *syncEvents.pendtail;
+ QdEventPtr tail;
QdEventPtr qe;
SpritePtr pSprite = device->spriteInfo->sprite;
int eventlen;
DeviceEvent *event = &ev->device_event;
+ tail = list_last_entry(&syncEvents.pending, QdEventRec, next);
+
NoticeTime((InternalEvent*)event);
/* Fix for key repeating bug. */
@@ -1196,15 +1193,13 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
qe = malloc(sizeof(QdEventRec) + eventlen);
if (!qe)
return;
- qe->next = (QdEventPtr)NULL;
+ list_init(&qe->next);
qe->device = device;
qe->pScreen = pSprite->hotPhys.pScreen;
qe->months = currentTime.months;
qe->event = (InternalEvent *)(qe + 1);
memcpy(qe->event, event, eventlen);
- if (tail)
- syncEvents.pendtail = &tail->next;
- *syncEvents.pendtail = qe;
+ list_append(&qe->next, &syncEvents.pending);
}
/**
@@ -1216,22 +1211,20 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
* If there is none, we're done. If there is at least one device that is not
* frozen, then re-run from the beginning of the event queue.
*/
-static void
+void
PlayReleasedEvents(void)
{
- QdEventPtr *prev, qe;
+ QdEventPtr tmp;
+ QdEventPtr qe;
DeviceIntPtr dev;
DeviceIntPtr pDev;
- prev = &syncEvents.pending;
- while ( (qe = *prev) )
- {
+restart:
+ list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
if (!qe->device->deviceGrab.sync.frozen)
{
- *prev = qe->next;
- pDev = qe->device;
- if (*syncEvents.pendtail == *prev)
- syncEvents.pendtail = prev;
+ list_del(&qe->next);
+ pDev = qe->device;
if (qe->event->any.type == ET_Motion)
CheckVirtualMotion(pDev, qe, NullWindow);
syncEvents.time.months = qe->months;
@@ -1268,12 +1261,11 @@ PlayReleasedEvents(void)
;
if (!dev)
break;
+
/* Playing the event may have unfrozen another device. */
/* So to play it safe, restart at the head of the queue */
- prev = &syncEvents.pending;
+ goto restart;
}
- else
- prev = &qe->next;
}
}
@@ -1314,7 +1306,8 @@ ComputeFreezes(void)
for (dev = inputInfo.devices; dev; dev = dev->next)
FreezeThaw(dev, dev->deviceGrab.sync.other ||
(dev->deviceGrab.sync.state >= FROZEN));
- if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
+ if (syncEvents.playingEvents ||
+ (!replayDev && list_is_empty(&syncEvents.pending)))
return;
syncEvents.playingEvents = TRUE;
if (replayDev)
@@ -1511,8 +1504,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
grabinfo->grabTime = time;
if (grab->cursor)
grab->cursor->refcnt++;
- grabinfo->activeGrab = *grab;
- grabinfo->grab = &grabinfo->activeGrab;
+ CopyGrab(grabinfo->activeGrab, grab);
+ grabinfo->grab = grabinfo->activeGrab;
grabinfo->fromPassiveGrab = isPassive;
grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
PostNewCursor(mouse);
@@ -1588,8 +1581,8 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
grabinfo->grabTime = syncEvents.time;
else
grabinfo->grabTime = time;
- grabinfo->activeGrab = *grab;
- grabinfo->grab = &grabinfo->activeGrab;
+ CopyGrab(grabinfo->activeGrab, grab);
+ grabinfo->grab = grabinfo->activeGrab;
grabinfo->fromPassiveGrab = passive;
grabinfo->implicitGrab = passive & ImplicitGrabMask;
CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
@@ -1978,7 +1971,7 @@ static BOOL
ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
xEvent *event, Mask deliveryMask)
{
- GrabRec tempGrab;
+ GrabPtr tempGrab;
OtherInputMasks *inputMasks;
CARD8 type = event->u.u.type;
GrabType grabtype;
@@ -1992,30 +1985,32 @@ ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
else
return FALSE;
- memset(&tempGrab, 0, sizeof(GrabRec));
- tempGrab.next = NULL;
- tempGrab.device = dev;
- tempGrab.resource = client->clientAsMask;
- tempGrab.window = win;
- tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
- tempGrab.eventMask = deliveryMask;
- tempGrab.keyboardMode = GrabModeAsync;
- tempGrab.pointerMode = GrabModeAsync;
- tempGrab.confineTo = NullWindow;
- tempGrab.cursor = NullCursor;
- tempGrab.type = type;
- tempGrab.grabtype = grabtype;
+ tempGrab = AllocGrab();
+ if (!tempGrab)
+ return FALSE;
+ tempGrab->next = NULL;
+ tempGrab->device = dev;
+ tempGrab->resource = client->clientAsMask;
+ tempGrab->window = win;
+ tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
+ tempGrab->eventMask = deliveryMask;
+ tempGrab->keyboardMode = GrabModeAsync;
+ tempGrab->pointerMode = GrabModeAsync;
+ tempGrab->confineTo = NullWindow;
+ tempGrab->cursor = NullCursor;
+ tempGrab->type = type;
+ tempGrab->grabtype = grabtype;
/* get the XI and XI2 device mask */
inputMasks = wOtherInputMasks(win);
- tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0;
+ tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0;
if (inputMasks)
- memcpy(tempGrab.xi2mask, inputMasks->xi2mask,
- sizeof(tempGrab.xi2mask));
+ xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
- (*dev->deviceGrab.ActivateGrab)(dev, &tempGrab,
+ (*dev->deviceGrab.ActivateGrab)(dev, tempGrab,
currentTime, TRUE | ImplicitGrabMask);
+ FreeGrab(tempGrab);
return TRUE;
}
@@ -2560,10 +2555,7 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
if ((type = GetXI2Type(event)) != 0)
{
- filter = GetXI2EventFilterMask(type);
-
- if (inputMasks &&
- (GetXI2MaskByte(inputMasks->xi2mask, dev, type) & filter))
+ if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
rc |= EVENT_XI2_MASK;
}
@@ -3659,7 +3651,7 @@ CheckPassiveGrabsOnWindow(
{
SpritePtr pSprite = device->spriteInfo->sprite;
GrabPtr grab = wPassiveGrabs(pWin);
- GrabRec tempGrab;
+ GrabPtr tempGrab;
GrabInfoPtr grabinfo;
#define CORE_MATCH 0x1
#define XI_MATCH 0x2
@@ -3668,27 +3660,30 @@ CheckPassiveGrabsOnWindow(
if (!grab)
return NULL;
+
+ tempGrab = AllocGrab();
+
/* Fill out the grab details, but leave the type for later before
* comparing */
switch (event->any.type)
{
case ET_KeyPress:
case ET_KeyRelease:
- tempGrab.detail.exact = event->device_event.detail.key;
+ tempGrab->detail.exact = event->device_event.detail.key;
break;
case ET_ButtonPress:
case ET_ButtonRelease:
- tempGrab.detail.exact = event->device_event.detail.button;
+ tempGrab->detail.exact = event->device_event.detail.button;
break;
default:
- tempGrab.detail.exact = 0;
+ tempGrab->detail.exact = 0;
break;
}
- tempGrab.window = pWin;
- tempGrab.device = device;
- tempGrab.detail.pMask = NULL;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.next = NULL;
+ tempGrab->window = pWin;
+ tempGrab->device = device;
+ tempGrab->detail.pMask = NULL;
+ tempGrab->modifiersDetail.pMask = NULL;
+ tempGrab->next = NULL;
for (; grab; grab = grab->next)
{
DeviceIntPtr gdev;
@@ -3713,29 +3708,29 @@ CheckPassiveGrabsOnWindow(
if (gdev && gdev->key)
xkbi= gdev->key->xkbInfo;
- tempGrab.modifierDevice = grab->modifierDevice;
- tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
+ tempGrab->modifierDevice = grab->modifierDevice;
+ tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
/* Check for XI2 and XI grabs first */
- tempGrab.type = GetXI2Type(event);
- tempGrab.grabtype = GRABTYPE_XI2;
- if (GrabMatchesSecond(&tempGrab, grab, FALSE))
+ tempGrab->type = GetXI2Type(event);
+ tempGrab->grabtype = GRABTYPE_XI2;
+ if (GrabMatchesSecond(tempGrab, grab, FALSE))
match = XI2_MATCH;
if (!match)
{
- tempGrab.grabtype = GRABTYPE_XI;
- if ((tempGrab.type = GetXIType(event)) &&
- (GrabMatchesSecond(&tempGrab, grab, FALSE)))
+ tempGrab->grabtype = GRABTYPE_XI;
+ if ((tempGrab->type = GetXIType(event)) &&
+ (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)) &&
- (GrabMatchesSecond(&tempGrab, grab, TRUE)))
+ tempGrab->grabtype = GRABTYPE_CORE;
+ if ((tempGrab->type = GetCoreType(event)) &&
+ (GrabMatchesSecond(tempGrab, grab, TRUE)))
match = CORE_MATCH;
}
@@ -3763,7 +3758,7 @@ CheckPassiveGrabsOnWindow(
Since XGrabDeviceButton requires to specify the
modifierDevice explicitly, we don't override this choice.
*/
- if (tempGrab.type < GenericEvent)
+ if (tempGrab->type < GenericEvent)
{
grab->device = device;
grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
@@ -3802,7 +3797,7 @@ CheckPassiveGrabsOnWindow(
if (match & (XI_MATCH | CORE_MATCH))
{
event->device_event.corestate &= 0x1f00;
- event->device_event.corestate |= tempGrab.modifiersDetail.exact &
+ event->device_event.corestate |= tempGrab->modifiersDetail.exact &
(~0x1f00);
}
@@ -3863,6 +3858,7 @@ CheckPassiveGrabsOnWindow(
break;
}
+ FreeGrab(tempGrab);
return grab;
#undef CORE_MATCH
#undef XI_MATCH
@@ -4150,12 +4146,11 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
if (rc == Success)
{
int evtype = xi2_get_type(xi2);
- mask = GetXI2MaskByte(grab->xi2mask, thisDev, evtype);
+ mask = xi2mask_isset(grab->xi2mask, thisDev, evtype);
/* try XI2 event */
FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
/* XXX: XACE */
- deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask,
- GetEventFilter(thisDev, xi2), grab);
+ deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, 1, grab);
} else if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
thisDev->name, event->any.type, rc);
@@ -4629,9 +4624,8 @@ DeviceEnterLeaveEvent(
if (grab)
{
Mask mask;
- mask = GetXI2MaskByte(grab->xi2mask, mouse, type);
- TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
- filter, grab);
+ mask = xi2mask_isset(grab->xi2mask, mouse, type);
+ TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, 1, grab);
} else {
if (!WindowXI2MaskIsset(mouse, pWin, (xEvent*)event))
goto out;
@@ -5080,29 +5074,30 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
*status = GrabFrozen;
else
{
- GrabRec tempGrab;
+ GrabPtr tempGrab;
- /* Otherwise segfaults happen on grabbed MPX devices */
- memset(&tempGrab, 0, sizeof(GrabRec));
+ tempGrab = AllocGrab();
- tempGrab.next = NULL;
- tempGrab.window = pWin;
- tempGrab.resource = client->clientAsMask;
- tempGrab.ownerEvents = ownerEvents;
- tempGrab.keyboardMode = keyboard_mode;
- tempGrab.pointerMode = pointer_mode;
+ tempGrab->next = NULL;
+ tempGrab->window = pWin;
+ tempGrab->resource = client->clientAsMask;
+ tempGrab->ownerEvents = ownerEvents;
+ tempGrab->keyboardMode = keyboard_mode;
+ tempGrab->pointerMode = pointer_mode;
if (grabtype == GRABTYPE_CORE)
- tempGrab.eventMask = mask->core;
+ tempGrab->eventMask = mask->core;
else if (grabtype == GRABTYPE_XI)
- tempGrab.eventMask = mask->xi;
+ tempGrab->eventMask = mask->xi;
else
- memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask));
- tempGrab.device = dev;
- tempGrab.cursor = cursor;
- tempGrab.confineTo = confineTo;
- tempGrab.grabtype = grabtype;
- (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
+ xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
+ tempGrab->device = dev;
+ tempGrab->cursor = cursor;
+ tempGrab->confineTo = confineTo;
+ tempGrab->grabtype = grabtype;
+ (*grabInfo->ActivateGrab)(dev, tempGrab, time, FALSE);
*status = GrabSuccess;
+
+ FreeGrab(tempGrab);
}
return Success;
}
@@ -5258,6 +5253,7 @@ void
InitEvents(void)
{
int i;
+ QdEventPtr qe, tmp;
inputInfo.numDevices = 0;
inputInfo.devices = (DeviceIntPtr)NULL;
@@ -5271,13 +5267,10 @@ InitEvents(void)
syncEvents.replayDev = (DeviceIntPtr)NULL;
syncEvents.replayWin = NullWindow;
- while (syncEvents.pending)
- {
- QdEventPtr next = syncEvents.pending->next;
- free(syncEvents.pending);
- syncEvents.pending = next;
- }
- syncEvents.pendtail = &syncEvents.pending;
+ if (syncEvents.pending.next)
+ list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
+ free(qe);
+ list_init(&syncEvents.pending);
syncEvents.playingEvents = FALSE;
syncEvents.time.months = 0;
syncEvents.time.milliseconds = 0; /* hardly matters */
@@ -5423,7 +5416,7 @@ ProcUngrabKey(ClientPtr client)
{
REQUEST(xUngrabKeyReq);
WindowPtr pWin;
- GrabRec tempGrab;
+ GrabPtr tempGrab;
DeviceIntPtr keybd = PickKeyboard(client);
int rc;
@@ -5445,21 +5438,27 @@ ProcUngrabKey(ClientPtr client)
client->errorValue = stuff->modifiers;
return BadValue;
}
- tempGrab.resource = client->clientAsMask;
- tempGrab.device = keybd;
- tempGrab.window = pWin;
- tempGrab.modifiersDetail.exact = stuff->modifiers;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.modifierDevice = keybd;
- tempGrab.type = KeyPress;
- tempGrab.grabtype = GRABTYPE_CORE;
- tempGrab.detail.exact = stuff->key;
- tempGrab.detail.pMask = NULL;
- tempGrab.next = NULL;
-
- if (!DeletePassiveGrabFromList(&tempGrab))
- return BadAlloc;
- return Success;
+ tempGrab = AllocGrab();
+ if (!tempGrab)
+ return BadAlloc;
+ tempGrab->resource = client->clientAsMask;
+ tempGrab->device = keybd;
+ tempGrab->window = pWin;
+ tempGrab->modifiersDetail.exact = stuff->modifiers;
+ tempGrab->modifiersDetail.pMask = NULL;
+ tempGrab->modifierDevice = keybd;
+ tempGrab->type = KeyPress;
+ tempGrab->grabtype = GRABTYPE_CORE;
+ tempGrab->detail.exact = stuff->key;
+ tempGrab->detail.pMask = NULL;
+ tempGrab->next = NULL;
+
+ if (!DeletePassiveGrabFromList(tempGrab))
+ rc = BadAlloc;
+
+ FreeGrab(tempGrab);
+
+ return rc;
}
/**
@@ -5623,7 +5622,7 @@ ProcUngrabButton(ClientPtr client)
{
REQUEST(xUngrabButtonReq);
WindowPtr pWin;
- GrabRec tempGrab;
+ GrabPtr tempGrab;
int rc;
DeviceIntPtr ptr;
@@ -5640,21 +5639,26 @@ ProcUngrabButton(ClientPtr client)
ptr = PickPointer(client);
- tempGrab.resource = client->clientAsMask;
- tempGrab.device = ptr;
- tempGrab.window = pWin;
- tempGrab.modifiersDetail.exact = stuff->modifiers;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
- tempGrab.type = ButtonPress;
- tempGrab.detail.exact = stuff->button;
- tempGrab.grabtype = GRABTYPE_CORE;
- tempGrab.detail.pMask = NULL;
- tempGrab.next = NULL;
-
- if (!DeletePassiveGrabFromList(&tempGrab))
- return BadAlloc;
- return Success;
+ tempGrab = AllocGrab();
+ if (!tempGrab)
+ return BadAlloc;
+ tempGrab->resource = client->clientAsMask;
+ tempGrab->device = ptr;
+ tempGrab->window = pWin;
+ tempGrab->modifiersDetail.exact = stuff->modifiers;
+ tempGrab->modifiersDetail.pMask = NULL;
+ tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
+ tempGrab->type = ButtonPress;
+ tempGrab->detail.exact = stuff->button;
+ tempGrab->grabtype = GRABTYPE_CORE;
+ tempGrab->detail.pMask = NULL;
+ tempGrab->next = NULL;
+
+ if (!DeletePassiveGrabFromList(tempGrab))
+ rc = BadAlloc;
+
+ FreeGrab(tempGrab);
+ return rc;
}
/**
diff --git a/xorg-server/dix/grabs.c b/xorg-server/dix/grabs.c
index c28356d9b..aced130a7 100644
--- a/xorg-server/dix/grabs.c
+++ b/xorg-server/dix/grabs.c
@@ -60,6 +60,7 @@ SOFTWARE.
#include "dixgrabs.h"
#include "xace.h"
#include "exevents.h"
+#include "inpututils.h"
#define BITMASK(i) (((Mask)1) << ((i) & 31))
#define MASKIDX(i) ((i) >> 5)
@@ -122,13 +123,15 @@ PrintDeviceGrabInfo(DeviceIntPtr dev)
}
else if (grab->grabtype == GRABTYPE_XI2)
{
- for (i = 0; i < EMASKSIZE; i++)
+ for (i = 0; i < xi2mask_num_masks(grab->xi2mask); i++)
{
+ const unsigned char *mask;
int print;
print = 0;
for (j = 0; j < XI2MASKSIZE; j++)
{
- if (grab->xi2mask[i][j])
+ mask = xi2mask_get_one_mask(grab->xi2mask, i);
+ if (mask[j])
{
print = 1;
break;
@@ -137,8 +140,8 @@ PrintDeviceGrabInfo(DeviceIntPtr dev)
if (!print)
continue;
ErrorF(" xi2 event mask for device %d: 0x", dev->id);
- for (j = 0; j < XI2MASKSIZE; j++)
- ErrorF("%x", grab->xi2mask[i][j]);
+ for (j = 0; j < xi2mask_mask_size(grab->xi2mask); j++)
+ ErrorF("%x", mask[j]);
ErrorF("\n");
}
}
@@ -181,6 +184,22 @@ UngrabAllDevices(Bool kill_client)
}
GrabPtr
+AllocGrab(void)
+{
+ GrabPtr grab = calloc(1, sizeof(GrabRec));
+
+ if (grab) {
+ grab->xi2mask = xi2mask_new();
+ if (!grab->xi2mask) {
+ free(grab);
+ grab = NULL;
+ }
+ }
+
+ return grab;
+}
+
+GrabPtr
CreateGrab(
int client,
DeviceIntPtr device,
@@ -196,7 +215,7 @@ CreateGrab(
{
GrabPtr grab;
- grab = calloc(1, sizeof(GrabRec));
+ grab = AllocGrab();
if (!grab)
return (GrabPtr)NULL;
grab->resource = FakeClientID(client);
@@ -219,14 +238,14 @@ CreateGrab(
grab->next = NULL;
if (grabtype == GRABTYPE_XI2)
- memcpy(grab->xi2mask, mask->xi2mask, sizeof(mask->xi2mask));
+ xi2mask_merge(grab->xi2mask, mask->xi2mask);
if (cursor)
cursor->refcnt++;
return grab;
}
-static void
+void
FreeGrab(GrabPtr pGrab)
{
free(pGrab->modifiersDetail.pMask);
@@ -235,9 +254,60 @@ FreeGrab(GrabPtr pGrab)
if (pGrab->cursor)
FreeCursor(pGrab->cursor, (Cursor)0);
+ xi2mask_free(&pGrab->xi2mask);
free(pGrab);
}
+Bool
+CopyGrab(GrabPtr dst, const GrabPtr src)
+{
+ Mask *mdetails_mask = NULL;
+ Mask *details_mask = NULL;
+ XI2Mask *xi2mask;
+
+ if (src->cursor)
+ src->cursor->refcnt++;
+
+ if (src->modifiersDetail.pMask) {
+ int len = MasksPerDetailMask * sizeof(Mask);
+ mdetails_mask = malloc(len);
+ if (!mdetails_mask)
+ return FALSE;
+ memcpy(mdetails_mask, src->modifiersDetail.pMask, len);
+ }
+
+ if (src->detail.pMask) {
+ int len = MasksPerDetailMask * sizeof(Mask);
+ details_mask = malloc(len);
+ if (!details_mask) {
+ free(mdetails_mask);
+ return FALSE;
+ }
+ memcpy(details_mask, src->detail.pMask, len);
+ }
+
+ if (!dst->xi2mask) {
+ xi2mask = xi2mask_new();
+ if (!xi2mask) {
+ free(mdetails_mask);
+ free(details_mask);
+ return FALSE;
+ }
+ } else {
+ xi2mask = dst->xi2mask;
+ xi2mask_zero(xi2mask, -1);
+ }
+
+ *dst = *src;
+ dst->modifiersDetail.pMask = mdetails_mask;
+ dst->detail.pMask = details_mask;
+ dst->xi2mask = xi2mask;
+
+ xi2mask_merge(dst->xi2mask, src->xi2mask);
+
+ return TRUE;
+}
+
int
DeletePassiveGrab(pointer value, XID id)
{
diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c
index c152b2d8b..60f9fa0a8 100644
--- a/xorg-server/dix/inpututils.c
+++ b/xorg-server/dix/inpututils.c
@@ -892,3 +892,184 @@ double_to_fp3232(double in)
ret.frac = frac_d;
return ret;
}
+
+/**
+ * DO NOT USE THIS FUNCTION. It only exists for the test cases. Use
+ * xi2mask_new() instead to get the standard sized masks.
+ *
+ * @param nmasks The number of masks (== number of devices)
+ * @param size The size of the masks in bytes
+ * @return The new mask or NULL on allocation error.
+ */
+XI2Mask*
+xi2mask_new_with_size(size_t nmasks, size_t size)
+{
+ int i;
+
+ XI2Mask *mask = calloc(1, sizeof(*mask));
+ if (!mask)
+ return NULL;
+
+
+ mask->nmasks = nmasks;
+ mask->mask_size = size;
+
+ mask->masks = calloc(mask->nmasks, sizeof(*mask->masks));
+ if (!mask->masks)
+ goto unwind;
+
+ for (i = 0; i < mask->nmasks; i++) {
+ mask->masks[i] = calloc(1, mask->mask_size);
+ if (!mask->masks[i])
+ goto unwind;
+ }
+ return mask;
+
+unwind:
+ xi2mask_free(&mask);
+ return NULL;
+}
+
+
+/**
+ * Create a new XI2 mask of the standard size, i.e. for all devices + fake
+ * devices and for the highest supported XI2 event type.
+ *
+ * @return The new mask or NULL on allocation error.
+ */
+XI2Mask*
+xi2mask_new(void)
+{
+ return xi2mask_new_with_size(EMASKSIZE, XI2MASKSIZE);
+}
+
+/**
+ * Frees memory associated with mask and resets mask to NULL.
+ */
+void
+xi2mask_free(XI2Mask** mask)
+{
+ int i;
+
+ if (!(*mask))
+ return;
+
+ for (i = 0; (*mask)->masks && i < (*mask)->nmasks; i++)
+ free((*mask)->masks[i]);
+ free((*mask)->masks);
+ free((*mask));
+ *mask = NULL;
+}
+
+/**
+ * Test if the bit for event type is set for this device, or the
+ * XIAllDevices/XIAllMasterDevices (if applicable) is set.
+ *
+ * @return TRUE if the bit is set, FALSE otherwise
+ */
+Bool
+xi2mask_isset(XI2Mask* mask, const DeviceIntPtr dev, int event_type)
+{
+ int set = 0;
+
+ BUG_WARN(dev->id < 0);
+ BUG_WARN(dev->id >= mask->nmasks);
+ BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
+
+ set = !!BitIsOn(mask->masks[XIAllDevices], event_type);
+ if (!set)
+ set = !!BitIsOn(mask->masks[dev->id], event_type);
+ if (!set && IsMaster(dev))
+ set = !!BitIsOn(mask->masks[XIAllMasterDevices], event_type);
+
+ return set;
+}
+
+/**
+ * Set the mask bit for this event type for this device.
+ */
+void
+xi2mask_set(XI2Mask *mask, int deviceid, int event_type)
+{
+ BUG_WARN(deviceid < 0);
+ BUG_WARN(deviceid >= mask->nmasks);
+ BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
+
+ SetBit(mask->masks[deviceid], event_type);
+}
+
+/**
+ * Zero out the xi2mask, for the deviceid given. If the deviceid is < 0, all
+ * masks are zeroed.
+ */
+void
+xi2mask_zero(XI2Mask *mask, int deviceid)
+{
+ int i;
+
+ BUG_WARN(deviceid > 0 && deviceid >= mask->nmasks);
+
+ if (deviceid >= 0)
+ memset(mask->masks[deviceid], 0, mask->mask_size);
+ else
+ for (i = 0; i < mask->nmasks; i++)
+ memset(mask->masks[i], 0, mask->mask_size);
+}
+
+/**
+ * Merge source into dest, i.e. dest |= source.
+ * If the masks are of different size, only the overlapping section is merged.
+ */
+void
+xi2mask_merge(XI2Mask *dest, const XI2Mask *source)
+{
+ int i, j;
+
+ for (i = 0; i < min(dest->nmasks, source->nmasks); i++)
+ for (j = 0; j < min(dest->mask_size, source->mask_size); j++)
+ dest->masks[i][j] |= source->masks[i][j];
+}
+
+/**
+ * @return The number of masks in mask
+ */
+size_t
+xi2mask_num_masks(const XI2Mask *mask)
+{
+ return mask->nmasks;
+}
+
+/**
+ * @return The size of each mask in bytes
+ */
+size_t
+xi2mask_mask_size(const XI2Mask *mask)
+{
+ return mask->mask_size;
+}
+
+/**
+ * Set the mask for the given deviceid to the source mask.
+ * If the mask given is larger than the target memory, only the overlapping
+ * parts are copied.
+ */
+void
+xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, size_t mask_size)
+{
+ BUG_WARN(deviceid < 0);
+ BUG_WARN(deviceid >= xi2mask->nmasks);
+
+ memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size));
+}
+
+/**
+ * Get a reference to the XI2mask for this particular device.
+ */
+const unsigned char*
+xi2mask_get_one_mask(const XI2Mask *mask, int deviceid)
+{
+ BUG_WARN(deviceid < 0);
+ BUG_WARN(deviceid >= mask->nmasks);
+
+ return mask->masks[deviceid];
+}