Merge remote-tracking branch 'whot/for-keith'

This commit is contained in:
Keith Packard 2011-12-08 20:57:26 -08:00
commit 522f8bcc03
25 changed files with 890 additions and 272 deletions

View File

@ -885,7 +885,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
int key = 0, rootX, rootY; int key = 0, rootX, rootY;
ButtonClassPtr b; ButtonClassPtr b;
int ret = 0; int ret = 0;
int state, i; int corestate, i;
DeviceIntPtr mouse = NULL, kbd = NULL; DeviceIntPtr mouse = NULL, kbd = NULL;
DeviceEvent *event = &ev->device_event; DeviceEvent *event = &ev->device_event;
@ -915,9 +915,9 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
mouse = NULL; mouse = NULL;
} }
/* State needs to be assembled BEFORE the device is updated. */ /* core state needs to be assembled BEFORE the device is updated. */
state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0; corestate = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
state |= (mouse && mouse->button) ? (mouse->button->state) : 0; corestate |= (mouse && mouse->button) ? (mouse->button->state) : 0;
for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
if (BitIsOn(mouse->button->down, i)) if (BitIsOn(mouse->button->down, i))
@ -965,7 +965,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
event->root_x = rootX; event->root_x = rootX;
event->root_y = rootY; event->root_y = rootY;
NoticeEventTime((InternalEvent*)event); NoticeEventTime((InternalEvent*)event);
event->corestate = state; event->corestate = corestate;
key = event->detail.key; key = event->detail.key;
break; break;
default: default:
@ -1002,11 +1002,9 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
deactivateDeviceGrab = TRUE; deactivateDeviceGrab = TRUE;
break; break;
case ET_ButtonPress: case ET_ButtonPress:
event->detail.button = b->map[key]; if (b->map[key] == 0) /* there's no button 0 */
if (!event->detail.button) { /* there's no button 0 */
event->detail.button = key;
return; return;
} event->detail.button = b->map[key];
if (!grab && CheckDeviceGrabs(device, event, 0)) if (!grab && CheckDeviceGrabs(device, event, 0))
{ {
/* if a passive grab was activated, the event has been sent /* if a passive grab was activated, the event has been sent
@ -1015,11 +1013,9 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
} }
break; break;
case ET_ButtonRelease: case ET_ButtonRelease:
event->detail.button = b->map[key]; if (b->map[key] == 0) /* there's no button 0 */
if (!event->detail.button) { /* there's no button 0 */
event->detail.button = key;
return; return;
} event->detail.button = b->map[key];
if (grab && !b->buttonsDown && if (grab && !b->buttonsDown &&
device->deviceGrab.fromPassiveGrab && device->deviceGrab.fromPassiveGrab &&
(device->deviceGrab.grab->type == ButtonPress || (device->deviceGrab.grab->type == ButtonPress ||
@ -1033,7 +1029,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
if (grab) if (grab)
DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab); DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
else if (device->focus && !IsPointerEvent((InternalEvent*)ev)) else if (device->focus && !IsPointerEvent(ev))
DeliverFocusedEvent(device, (InternalEvent*)event, DeliverFocusedEvent(device, (InternalEvent*)event,
GetSpriteWindow(device)); GetSpriteWindow(device));
else else
@ -1631,6 +1627,7 @@ SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
static void static void
FreeInputClient(InputClientsPtr *other) FreeInputClient(InputClientsPtr *other)
{ {
xi2mask_free(&(*other)->xi2mask);
free(*other); free(*other);
*other = NULL; *other = NULL;
} }
@ -1653,6 +1650,9 @@ AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
return BadAlloc; return BadAlloc;
if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
goto bail; goto bail;
others->xi2mask = xi2mask_new();
if (!others->xi2mask)
goto bail;
others->mask[mskidx] = mask; others->mask[mskidx] = mask;
others->resource = FakeClientID(client->index); others->resource = FakeClientID(client->index);
others->next = pWin->optional->inputMasks->inputClients; others->next = pWin->optional->inputMasks->inputClients;
@ -1674,6 +1674,12 @@ MakeInputMasks(WindowPtr pWin)
imasks = calloc(1, sizeof(struct _OtherInputMasks)); imasks = calloc(1, sizeof(struct _OtherInputMasks));
if (!imasks) if (!imasks)
return FALSE; return FALSE;
imasks->xi2mask = xi2mask_new();
if (!imasks->xi2mask)
{
free(imasks);
return FALSE;
}
pWin->optional->inputMasks = imasks; pWin->optional->inputMasks = imasks;
return TRUE; return TRUE;
} }
@ -1681,6 +1687,7 @@ MakeInputMasks(WindowPtr pWin)
static void static void
FreeInputMask(OtherInputMasks **imask) FreeInputMask(OtherInputMasks **imask)
{ {
xi2mask_free(&(*imask)->xi2mask);
free(*imask); free(*imask);
*imask = NULL; *imask = NULL;
} }
@ -1691,20 +1698,17 @@ RecalculateDeviceDeliverableEvents(WindowPtr pWin)
InputClientsPtr others; InputClientsPtr others;
struct _OtherInputMasks *inputMasks; /* default: NULL */ struct _OtherInputMasks *inputMasks; /* default: NULL */
WindowPtr pChild, tmp; WindowPtr pChild, tmp;
int i, j; int i;
pChild = pWin; pChild = pWin;
while (1) { while (1) {
if ((inputMasks = wOtherInputMasks(pChild)) != 0) { if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
for (i = 0; i < EMASKSIZE; i++) xi2mask_zero(inputMasks->xi2mask, -1);
memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
for (others = inputMasks->inputClients; others; for (others = inputMasks->inputClients; others;
others = others->next) { others = others->next) {
for (i = 0; i < EMASKSIZE; i++) for (i = 0; i < EMASKSIZE; i++)
inputMasks->inputEvents[i] |= others->mask[i]; inputMasks->inputEvents[i] |= others->mask[i];
for (i = 0; i < EMASKSIZE; i++) xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
for (j = 0; j < XI2MASKSIZE; j++)
inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
} }
for (i = 0; i < EMASKSIZE; i++) for (i = 0; i < EMASKSIZE; i++)
inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
@ -2024,20 +2028,25 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
dev->valuator->motionHintWindow = pWin; dev->valuator->motionHintWindow = pWin;
else if ((type == DeviceButtonPress) && (!grab) && else if ((type == DeviceButtonPress) && (!grab) &&
(deliveryMask & DeviceButtonGrabMask)) { (deliveryMask & DeviceButtonGrabMask)) {
GrabRec tempGrab; GrabPtr tempGrab;
tempGrab.device = dev; tempGrab = AllocGrab();
tempGrab.resource = client->clientAsMask; if (!tempGrab)
tempGrab.window = pWin; return;
tempGrab.ownerEvents =
tempGrab->device = dev;
tempGrab->resource = client->clientAsMask;
tempGrab->window = pWin;
tempGrab->ownerEvents =
(deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
tempGrab.eventMask = deliveryMask; tempGrab->eventMask = deliveryMask;
tempGrab.keyboardMode = GrabModeAsync; tempGrab->keyboardMode = GrabModeAsync;
tempGrab.pointerMode = GrabModeAsync; tempGrab->pointerMode = GrabModeAsync;
tempGrab.confineTo = NullWindow; tempGrab->confineTo = NullWindow;
tempGrab.cursor = NullCursor; tempGrab->cursor = NullCursor;
tempGrab.next = NULL; tempGrab->next = NULL;
(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE); (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
FreeGrab(tempGrab);
} }
} }
@ -2183,14 +2192,12 @@ XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
for (others = wOtherInputMasks(win)->inputClients; others; for (others = wOtherInputMasks(win)->inputClients; others;
others = others->next) { others = others->next) {
if (SameClient(others, client)) { if (SameClient(others, client)) {
memset(others->xi2mask[dev->id], 0, xi2mask_zero(others->xi2mask, dev->id);
sizeof(others->xi2mask[dev->id]));
break; break;
} }
} }
} }
len = min(len, sizeof(others->xi2mask[dev->id]));
if (len && !others) if (len && !others)
{ {
@ -2199,11 +2206,14 @@ XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
others= wOtherInputMasks(win)->inputClients; others= wOtherInputMasks(win)->inputClients;
} }
if (others) if (others) {
memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id])); xi2mask_zero(others->xi2mask, dev->id);
len = min(len, xi2mask_mask_size(others->xi2mask));
}
if (len) if (len) {
memcpy(others->xi2mask[dev->id], mask, len); xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
}
RecalculateDeviceDeliverableEvents(win); RecalculateDeviceDeliverableEvents(win);

View File

@ -96,7 +96,7 @@ ProcXUngrabDeviceButton(ClientPtr client)
DeviceIntPtr dev; DeviceIntPtr dev;
DeviceIntPtr mdev; DeviceIntPtr mdev;
WindowPtr pWin; WindowPtr pWin;
GrabRec temporaryGrab; GrabPtr temporaryGrab;
int rc; int rc;
REQUEST(xUngrabDeviceButtonReq); REQUEST(xUngrabDeviceButtonReq);
@ -126,17 +126,23 @@ ProcXUngrabDeviceButton(ClientPtr client)
(stuff->modifiers & ~AllModifiersMask)) (stuff->modifiers & ~AllModifiersMask))
return BadValue; return BadValue;
temporaryGrab.resource = client->clientAsMask; temporaryGrab = AllocGrab();
temporaryGrab.device = dev; if (!temporaryGrab)
temporaryGrab.window = pWin; return BadAlloc;
temporaryGrab.type = DeviceButtonPress;
temporaryGrab.grabtype = GRABTYPE_XI;
temporaryGrab.modifierDevice = mdev;
temporaryGrab.modifiersDetail.exact = stuff->modifiers;
temporaryGrab.modifiersDetail.pMask = NULL;
temporaryGrab.detail.exact = stuff->button;
temporaryGrab.detail.pMask = NULL;
DeletePassiveGrabFromList(&temporaryGrab); temporaryGrab->resource = client->clientAsMask;
temporaryGrab->device = dev;
temporaryGrab->window = pWin;
temporaryGrab->type = DeviceButtonPress;
temporaryGrab->grabtype = GRABTYPE_XI;
temporaryGrab->modifierDevice = mdev;
temporaryGrab->modifiersDetail.exact = stuff->modifiers;
temporaryGrab->modifiersDetail.pMask = NULL;
temporaryGrab->detail.exact = stuff->button;
temporaryGrab->detail.pMask = NULL;
DeletePassiveGrabFromList(temporaryGrab);
FreeGrab(temporaryGrab);
return Success; return Success;
} }

View File

@ -98,7 +98,7 @@ ProcXUngrabDeviceKey(ClientPtr client)
DeviceIntPtr dev; DeviceIntPtr dev;
DeviceIntPtr mdev; DeviceIntPtr mdev;
WindowPtr pWin; WindowPtr pWin;
GrabRec temporaryGrab; GrabPtr temporaryGrab;
int rc; int rc;
REQUEST(xUngrabDeviceKeyReq); REQUEST(xUngrabDeviceKeyReq);
@ -133,17 +133,22 @@ ProcXUngrabDeviceKey(ClientPtr client)
(stuff->modifiers & ~AllModifiersMask)) (stuff->modifiers & ~AllModifiersMask))
return BadValue; return BadValue;
temporaryGrab.resource = client->clientAsMask; temporaryGrab = AllocGrab();
temporaryGrab.device = dev; if (!temporaryGrab)
temporaryGrab.window = pWin; return BadAlloc;
temporaryGrab.type = DeviceKeyPress;
temporaryGrab.grabtype = GRABTYPE_XI;
temporaryGrab.modifierDevice = mdev;
temporaryGrab.modifiersDetail.exact = stuff->modifiers;
temporaryGrab.modifiersDetail.pMask = NULL;
temporaryGrab.detail.exact = stuff->key;
temporaryGrab.detail.pMask = NULL;
DeletePassiveGrabFromList(&temporaryGrab); temporaryGrab->resource = client->clientAsMask;
temporaryGrab->device = dev;
temporaryGrab->window = pWin;
temporaryGrab->type = DeviceKeyPress;
temporaryGrab->grabtype = GRABTYPE_XI;
temporaryGrab->modifierDevice = mdev;
temporaryGrab->modifiersDetail.exact = stuff->modifiers;
temporaryGrab->modifiersDetail.pMask = NULL;
temporaryGrab->detail.exact = stuff->key;
temporaryGrab->detail.pMask = NULL;
DeletePassiveGrabFromList(temporaryGrab);
FreeGrab(temporaryGrab);
return Success; return Success;
} }

View File

@ -200,6 +200,19 @@ unwind:
return rc; return rc;
} }
static int
disable_clientpointer(DeviceIntPtr dev)
{
int i;
for (i = 0; i < currentMaxClients; i++)
{
ClientPtr client = clients[i];
if (client && client->clientPtr == dev)
client->clientPtr = NULL;
}
}
static int static int
remove_master(ClientPtr client, xXIRemoveMasterInfo *r, remove_master(ClientPtr client, xXIRemoveMasterInfo *r,
int flags[MAXDEVICES]) int flags[MAXDEVICES])
@ -250,6 +263,8 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo *r,
if (rc != Success) if (rc != Success)
goto unwind; goto unwind;
disable_clientpointer(ptr);
/* Disabling sends the devices floating, reattach them if /* Disabling sends the devices floating, reattach them if
* desired. */ * desired. */
if (r->return_mode == XIAttachToMaster) if (r->return_mode == XIAttachToMaster)

View File

@ -41,6 +41,7 @@
#include "exglobals.h" /* BadDevice */ #include "exglobals.h" /* BadDevice */
#include "exevents.h" #include "exevents.h"
#include "xigrabdev.h" #include "xigrabdev.h"
#include "inpututils.h"
int int
SProcXIGrabDevice(ClientPtr client) SProcXIGrabDevice(ClientPtr client)
@ -64,7 +65,7 @@ ProcXIGrabDevice(ClientPtr client)
xXIGrabDeviceReply rep; xXIGrabDeviceReply rep;
int ret = Success; int ret = Success;
uint8_t status; uint8_t status;
GrabMask mask; GrabMask mask = { 0 };
int mask_len; int mask_len;
REQUEST(xXIGrabDeviceReq); REQUEST(xXIGrabDeviceReq);
@ -81,9 +82,13 @@ ProcXIGrabDevice(ClientPtr client)
stuff->mask_len * 4) != Success) stuff->mask_len * 4) != Success)
return BadValue; return BadValue;
mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); mask.xi2mask = xi2mask_new();
memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); if (!mask.xi2mask)
memcpy(mask.xi2mask, (char*)&stuff[1], mask_len); return BadAlloc;
mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4);
/* FIXME: I think the old code was broken here */
xi2mask_set_one_mask(mask.xi2mask, dev->id, (unsigned char*)&stuff[1], mask_len);
ret = GrabDevice(client, dev, stuff->grab_mode, ret = GrabDevice(client, dev, stuff->grab_mode,
stuff->paired_device_mode, stuff->paired_device_mode,
@ -96,6 +101,8 @@ ProcXIGrabDevice(ClientPtr client)
None /* confineTo */, None /* confineTo */,
&status); &status);
xi2mask_free(&mask.xi2mask);
if (ret != Success) if (ret != Success)
return ret; return ret;

View File

@ -44,6 +44,7 @@
#include "xipassivegrab.h" #include "xipassivegrab.h"
#include "dixgrabs.h" #include "dixgrabs.h"
#include "misc.h" #include "misc.h"
#include "inpututils.h"
int int
SProcXIPassiveGrabDevice(ClientPtr client) SProcXIPassiveGrabDevice(ClientPtr client)
@ -82,7 +83,7 @@ ProcXIPassiveGrabDevice(ClientPtr client)
int i, ret = Success; int i, ret = Success;
uint32_t *modifiers; uint32_t *modifiers;
xXIGrabModifierInfo *modifiers_failed; xXIGrabModifierInfo *modifiers_failed;
GrabMask mask; GrabMask mask = { 0 };
GrabParameters param; GrabParameters param;
void *tmp; void *tmp;
int mask_len; int mask_len;
@ -124,9 +125,12 @@ ProcXIPassiveGrabDevice(ClientPtr client)
stuff->mask_len * 4) != Success) stuff->mask_len * 4) != Success)
return BadValue; return BadValue;
mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); mask.xi2mask = xi2mask_new();
memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); if (!mask.xi2mask)
memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4); return BadAlloc;
mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4);
xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid, (unsigned char*)&stuff[1], mask_len * 4);
rep.repType = X_Reply; rep.repType = X_Reply;
rep.RepType = X_XIPassiveGrabDevice; rep.RepType = X_XIPassiveGrabDevice;
@ -212,6 +216,7 @@ ProcXIPassiveGrabDevice(ClientPtr client)
free(modifiers_failed); free(modifiers_failed);
out: out:
xi2mask_free(&mask.xi2mask);
return ret; return ret;
} }
@ -253,7 +258,7 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
{ {
DeviceIntPtr dev, mod_dev; DeviceIntPtr dev, mod_dev;
WindowPtr win; WindowPtr win;
GrabRec tempGrab; GrabPtr tempGrab;
uint32_t* modifiers; uint32_t* modifiers;
int i, rc; int i, rc;
@ -293,29 +298,36 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
tempGrab.resource = client->clientAsMask;
tempGrab.device = dev; tempGrab = AllocGrab();
tempGrab.window = win; if (!tempGrab)
return BadAlloc;
tempGrab->resource = client->clientAsMask;
tempGrab->device = dev;
tempGrab->window = win;
switch(stuff->grab_type) switch(stuff->grab_type)
{ {
case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break; case XIGrabtypeButton: tempGrab->type = XI_ButtonPress; break;
case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break; case XIGrabtypeKeycode: tempGrab->type = XI_KeyPress; break;
case XIGrabtypeEnter: tempGrab.type = XI_Enter; break; case XIGrabtypeEnter: tempGrab->type = XI_Enter; break;
case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break; case XIGrabtypeFocusIn: tempGrab->type = XI_FocusIn; break;
} }
tempGrab.grabtype = GRABTYPE_XI2; tempGrab->grabtype = GRABTYPE_XI2;
tempGrab.modifierDevice = mod_dev; tempGrab->modifierDevice = mod_dev;
tempGrab.modifiersDetail.pMask = NULL; tempGrab->modifiersDetail.pMask = NULL;
tempGrab.detail.exact = stuff->detail; tempGrab->detail.exact = stuff->detail;
tempGrab.detail.pMask = NULL; tempGrab->detail.pMask = NULL;
modifiers = (uint32_t*)&stuff[1]; modifiers = (uint32_t*)&stuff[1];
for (i = 0; i < stuff->num_modifiers; i++, modifiers++) for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
{ {
tempGrab.modifiersDetail.exact = *modifiers; tempGrab->modifiersDetail.exact = *modifiers;
DeletePassiveGrabFromList(&tempGrab); DeletePassiveGrabFromList(tempGrab);
} }
FreeGrab(tempGrab);
return Success; return Success;
} }

View File

@ -33,6 +33,7 @@
#include "exglobals.h" #include "exglobals.h"
#include "exevents.h" #include "exevents.h"
#include <X11/extensions/XI2proto.h> #include <X11/extensions/XI2proto.h>
#include "inpututils.h"
#include "xiselectev.h" #include "xiselectev.h"
@ -249,7 +250,7 @@ ProcXIGetSelectedEvents(ClientPtr client)
for (i = 0; i < MAXDEVICES; i++) for (i = 0; i < MAXDEVICES; i++)
{ {
int j; int j;
unsigned char *devmask = others->xi2mask[i]; const unsigned char *devmask = xi2mask_get_one_mask(others->xi2mask, i);
if (i > 2) if (i > 2)
{ {
@ -259,7 +260,7 @@ ProcXIGetSelectedEvents(ClientPtr client)
} }
for (j = XI2MASKSIZE - 1; j >= 0; j--) for (j = xi2mask_mask_size(others->xi2mask) - 1; j >= 0; j--)
{ {
if (devmask[j] != 0) if (devmask[j] != 0)
{ {

View File

@ -73,6 +73,7 @@ SOFTWARE.
#include "dixevents.h" #include "dixevents.h"
#include "mipointer.h" #include "mipointer.h"
#include "eventstr.h" #include "eventstr.h"
#include "dixgrabs.h"
#include <X11/extensions/XI.h> #include <X11/extensions/XI.h>
#include <X11/extensions/XI2.h> #include <X11/extensions/XI2.h>
@ -273,6 +274,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
dev->deviceGrab.grabTime = currentTime; dev->deviceGrab.grabTime = currentTime;
dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
dev->deviceGrab.activeGrab = AllocGrab();
XkbSetExtension(dev, ProcessKeyboardEvent); XkbSetExtension(dev, ProcessKeyboardEvent);
@ -941,6 +943,7 @@ CloseDevice(DeviceIntPtr dev)
} }
} }
FreeGrab(dev->deviceGrab.activeGrab);
free(dev->deviceGrab.sync.event); free(dev->deviceGrab.sync.event);
free(dev->config_info); /* Allocated in xf86ActivateDevice. */ free(dev->config_info); /* Allocated in xf86ActivateDevice. */
free(dev->last.scroll); free(dev->last.scroll);

View File

@ -420,12 +420,6 @@ GetXI2EventFilterMask(int evtype)
return (1 << (evtype % 8)); 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 * For the given event, return the matching event filter. This filter may then
* be AND'ed with the selected event mask. * be AND'ed with the selected event mask.
@ -459,12 +453,15 @@ GetEventFilter(DeviceIntPtr dev, xEvent *event)
* for the event_type. * for the event_type.
*/ */
static int 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); /* we just return the matching filter because that's the only use
return xi2mask[dev->id][byte] | * for this mask anyway.
xi2mask[XIAllDevices][byte] | */
(IsMaster(dev) ? xi2mask[XIAllMasterDevices][byte] : 0); 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) WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
{ {
OtherInputMasks *inputMasks = wOtherInputMasks(win); OtherInputMasks *inputMasks = wOtherInputMasks(win);
int filter;
int evtype; int evtype;
if (!inputMasks || xi2_get_type(ev) == 0) if (!inputMasks || xi2_get_type(ev) == 0)
return 0; return 0;
evtype = ((xGenericEvent*)ev)->evtype; evtype = ((xGenericEvent*)ev)->evtype;
filter = GetEventFilter(dev, ev);
return !!(GetXI2MaskByte(inputMasks->xi2mask, dev, evtype) & filter); return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
} }
Mask Mask
@ -1132,12 +1127,14 @@ NoticeEventTime(InternalEvent *ev)
void void
EnqueueEvent(InternalEvent *ev, DeviceIntPtr device) EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
{ {
QdEventPtr tail = *syncEvents.pendtail; QdEventPtr tail;
QdEventPtr qe; QdEventPtr qe;
SpritePtr pSprite = device->spriteInfo->sprite; SpritePtr pSprite = device->spriteInfo->sprite;
int eventlen; int eventlen;
DeviceEvent *event = &ev->device_event; DeviceEvent *event = &ev->device_event;
tail = list_last_entry(&syncEvents.pending, QdEventRec, next);
NoticeTime((InternalEvent*)event); NoticeTime((InternalEvent*)event);
/* Fix for key repeating bug. */ /* Fix for key repeating bug. */
@ -1196,15 +1193,13 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
qe = malloc(sizeof(QdEventRec) + eventlen); qe = malloc(sizeof(QdEventRec) + eventlen);
if (!qe) if (!qe)
return; return;
qe->next = (QdEventPtr)NULL; list_init(&qe->next);
qe->device = device; qe->device = device;
qe->pScreen = pSprite->hotPhys.pScreen; qe->pScreen = pSprite->hotPhys.pScreen;
qe->months = currentTime.months; qe->months = currentTime.months;
qe->event = (InternalEvent *)(qe + 1); qe->event = (InternalEvent *)(qe + 1);
memcpy(qe->event, event, eventlen); memcpy(qe->event, event, eventlen);
if (tail) list_append(&qe->next, &syncEvents.pending);
syncEvents.pendtail = &tail->next;
*syncEvents.pendtail = qe;
} }
/** /**
@ -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 * 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. * frozen, then re-run from the beginning of the event queue.
*/ */
static void void
PlayReleasedEvents(void) PlayReleasedEvents(void)
{ {
QdEventPtr *prev, qe; QdEventPtr tmp;
QdEventPtr qe;
DeviceIntPtr dev; DeviceIntPtr dev;
DeviceIntPtr pDev; DeviceIntPtr pDev;
prev = &syncEvents.pending; restart:
while ( (qe = *prev) ) list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
{
if (!qe->device->deviceGrab.sync.frozen) if (!qe->device->deviceGrab.sync.frozen)
{ {
*prev = qe->next; list_del(&qe->next);
pDev = qe->device; pDev = qe->device;
if (*syncEvents.pendtail == *prev)
syncEvents.pendtail = prev;
if (qe->event->any.type == ET_Motion) if (qe->event->any.type == ET_Motion)
CheckVirtualMotion(pDev, qe, NullWindow); CheckVirtualMotion(pDev, qe, NullWindow);
syncEvents.time.months = qe->months; syncEvents.time.months = qe->months;
@ -1268,12 +1261,11 @@ PlayReleasedEvents(void)
; ;
if (!dev) if (!dev)
break; break;
/* Playing the event may have unfrozen another device. */ /* Playing the event may have unfrozen another device. */
/* So to play it safe, restart at the head of the queue */ /* 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) for (dev = inputInfo.devices; dev; dev = dev->next)
FreezeThaw(dev, dev->deviceGrab.sync.other || FreezeThaw(dev, dev->deviceGrab.sync.other ||
(dev->deviceGrab.sync.state >= FROZEN)); (dev->deviceGrab.sync.state >= FROZEN));
if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) if (syncEvents.playingEvents ||
(!replayDev && list_is_empty(&syncEvents.pending)))
return; return;
syncEvents.playingEvents = TRUE; syncEvents.playingEvents = TRUE;
if (replayDev) if (replayDev)
@ -1511,8 +1504,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
grabinfo->grabTime = time; grabinfo->grabTime = time;
if (grab->cursor) if (grab->cursor)
grab->cursor->refcnt++; grab->cursor->refcnt++;
grabinfo->activeGrab = *grab; CopyGrab(grabinfo->activeGrab, grab);
grabinfo->grab = &grabinfo->activeGrab; grabinfo->grab = grabinfo->activeGrab;
grabinfo->fromPassiveGrab = isPassive; grabinfo->fromPassiveGrab = isPassive;
grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
PostNewCursor(mouse); PostNewCursor(mouse);
@ -1588,8 +1581,8 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
grabinfo->grabTime = syncEvents.time; grabinfo->grabTime = syncEvents.time;
else else
grabinfo->grabTime = time; grabinfo->grabTime = time;
grabinfo->activeGrab = *grab; CopyGrab(grabinfo->activeGrab, grab);
grabinfo->grab = &grabinfo->activeGrab; grabinfo->grab = grabinfo->activeGrab;
grabinfo->fromPassiveGrab = passive; grabinfo->fromPassiveGrab = passive;
grabinfo->implicitGrab = passive & ImplicitGrabMask; grabinfo->implicitGrab = passive & ImplicitGrabMask;
CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
@ -1978,7 +1971,7 @@ static BOOL
ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
xEvent *event, Mask deliveryMask) xEvent *event, Mask deliveryMask)
{ {
GrabRec tempGrab; GrabPtr tempGrab;
OtherInputMasks *inputMasks; OtherInputMasks *inputMasks;
CARD8 type = event->u.u.type; CARD8 type = event->u.u.type;
GrabType grabtype; GrabType grabtype;
@ -1992,30 +1985,32 @@ ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
else else
return FALSE; return FALSE;
memset(&tempGrab, 0, sizeof(GrabRec)); tempGrab = AllocGrab();
tempGrab.next = NULL; if (!tempGrab)
tempGrab.device = dev; return FALSE;
tempGrab.resource = client->clientAsMask; tempGrab->next = NULL;
tempGrab.window = win; tempGrab->device = dev;
tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; tempGrab->resource = client->clientAsMask;
tempGrab.eventMask = deliveryMask; tempGrab->window = win;
tempGrab.keyboardMode = GrabModeAsync; tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
tempGrab.pointerMode = GrabModeAsync; tempGrab->eventMask = deliveryMask;
tempGrab.confineTo = NullWindow; tempGrab->keyboardMode = GrabModeAsync;
tempGrab.cursor = NullCursor; tempGrab->pointerMode = GrabModeAsync;
tempGrab.type = type; tempGrab->confineTo = NullWindow;
tempGrab.grabtype = grabtype; tempGrab->cursor = NullCursor;
tempGrab->type = type;
tempGrab->grabtype = grabtype;
/* get the XI and XI2 device mask */ /* get the XI and XI2 device mask */
inputMasks = wOtherInputMasks(win); inputMasks = wOtherInputMasks(win);
tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0; tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0;
if (inputMasks) if (inputMasks)
memcpy(tempGrab.xi2mask, inputMasks->xi2mask, xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
sizeof(tempGrab.xi2mask));
(*dev->deviceGrab.ActivateGrab)(dev, &tempGrab, (*dev->deviceGrab.ActivateGrab)(dev, tempGrab,
currentTime, TRUE | ImplicitGrabMask); currentTime, TRUE | ImplicitGrabMask);
FreeGrab(tempGrab);
return TRUE; return TRUE;
} }
@ -2560,10 +2555,7 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
if ((type = GetXI2Type(event)) != 0) if ((type = GetXI2Type(event)) != 0)
{ {
filter = GetXI2EventFilterMask(type); if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
if (inputMasks &&
(GetXI2MaskByte(inputMasks->xi2mask, dev, type) & filter))
rc |= EVENT_XI2_MASK; rc |= EVENT_XI2_MASK;
} }
@ -3659,7 +3651,7 @@ CheckPassiveGrabsOnWindow(
{ {
SpritePtr pSprite = device->spriteInfo->sprite; SpritePtr pSprite = device->spriteInfo->sprite;
GrabPtr grab = wPassiveGrabs(pWin); GrabPtr grab = wPassiveGrabs(pWin);
GrabRec tempGrab; GrabPtr tempGrab;
GrabInfoPtr grabinfo; GrabInfoPtr grabinfo;
#define CORE_MATCH 0x1 #define CORE_MATCH 0x1
#define XI_MATCH 0x2 #define XI_MATCH 0x2
@ -3668,27 +3660,30 @@ CheckPassiveGrabsOnWindow(
if (!grab) if (!grab)
return NULL; return NULL;
tempGrab = AllocGrab();
/* Fill out the grab details, but leave the type for later before /* Fill out the grab details, but leave the type for later before
* comparing */ * comparing */
switch (event->any.type) switch (event->any.type)
{ {
case ET_KeyPress: case ET_KeyPress:
case ET_KeyRelease: case ET_KeyRelease:
tempGrab.detail.exact = event->device_event.detail.key; tempGrab->detail.exact = event->device_event.detail.key;
break; break;
case ET_ButtonPress: case ET_ButtonPress:
case ET_ButtonRelease: case ET_ButtonRelease:
tempGrab.detail.exact = event->device_event.detail.button; tempGrab->detail.exact = event->device_event.detail.button;
break; break;
default: default:
tempGrab.detail.exact = 0; tempGrab->detail.exact = 0;
break; break;
} }
tempGrab.window = pWin; tempGrab->window = pWin;
tempGrab.device = device; tempGrab->device = device;
tempGrab.detail.pMask = NULL; tempGrab->detail.pMask = NULL;
tempGrab.modifiersDetail.pMask = NULL; tempGrab->modifiersDetail.pMask = NULL;
tempGrab.next = NULL; tempGrab->next = NULL;
for (; grab; grab = grab->next) for (; grab; grab = grab->next)
{ {
DeviceIntPtr gdev; DeviceIntPtr gdev;
@ -3713,29 +3708,29 @@ CheckPassiveGrabsOnWindow(
if (gdev && gdev->key) if (gdev && gdev->key)
xkbi= gdev->key->xkbInfo; xkbi= gdev->key->xkbInfo;
tempGrab.modifierDevice = grab->modifierDevice; tempGrab->modifierDevice = grab->modifierDevice;
tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
/* Check for XI2 and XI grabs first */ /* Check for XI2 and XI grabs first */
tempGrab.type = GetXI2Type(event); tempGrab->type = GetXI2Type(event);
tempGrab.grabtype = GRABTYPE_XI2; tempGrab->grabtype = GRABTYPE_XI2;
if (GrabMatchesSecond(&tempGrab, grab, FALSE)) if (GrabMatchesSecond(tempGrab, grab, FALSE))
match = XI2_MATCH; match = XI2_MATCH;
if (!match) if (!match)
{ {
tempGrab.grabtype = GRABTYPE_XI; tempGrab->grabtype = GRABTYPE_XI;
if ((tempGrab.type = GetXIType(event)) && if ((tempGrab->type = GetXIType(event)) &&
(GrabMatchesSecond(&tempGrab, grab, FALSE))) (GrabMatchesSecond(tempGrab, grab, FALSE)))
match = XI_MATCH; match = XI_MATCH;
} }
/* Check for a core grab (ignore the device when comparing) */ /* Check for a core grab (ignore the device when comparing) */
if (!match && checkCore) if (!match && checkCore)
{ {
tempGrab.grabtype = GRABTYPE_CORE; tempGrab->grabtype = GRABTYPE_CORE;
if ((tempGrab.type = GetCoreType(event)) && if ((tempGrab->type = GetCoreType(event)) &&
(GrabMatchesSecond(&tempGrab, grab, TRUE))) (GrabMatchesSecond(tempGrab, grab, TRUE)))
match = CORE_MATCH; match = CORE_MATCH;
} }
@ -3763,7 +3758,7 @@ CheckPassiveGrabsOnWindow(
Since XGrabDeviceButton requires to specify the Since XGrabDeviceButton requires to specify the
modifierDevice explicitly, we don't override this choice. modifierDevice explicitly, we don't override this choice.
*/ */
if (tempGrab.type < GenericEvent) if (tempGrab->type < GenericEvent)
{ {
grab->device = device; grab->device = device;
grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD); grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
@ -3802,7 +3797,7 @@ CheckPassiveGrabsOnWindow(
if (match & (XI_MATCH | CORE_MATCH)) if (match & (XI_MATCH | CORE_MATCH))
{ {
event->device_event.corestate &= 0x1f00; event->device_event.corestate &= 0x1f00;
event->device_event.corestate |= tempGrab.modifiersDetail.exact & event->device_event.corestate |= tempGrab->modifiersDetail.exact &
(~0x1f00); (~0x1f00);
} }
@ -3863,6 +3858,7 @@ CheckPassiveGrabsOnWindow(
break; break;
} }
FreeGrab(tempGrab);
return grab; return grab;
#undef CORE_MATCH #undef CORE_MATCH
#undef XI_MATCH #undef XI_MATCH
@ -4150,12 +4146,11 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
if (rc == Success) if (rc == Success)
{ {
int evtype = xi2_get_type(xi2); int evtype = xi2_get_type(xi2);
mask = GetXI2MaskByte(grab->xi2mask, thisDev, evtype); mask = xi2mask_isset(grab->xi2mask, thisDev, evtype);
/* try XI2 event */ /* try XI2 event */
FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE); FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
/* XXX: XACE */ /* XXX: XACE */
deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, 1, grab);
GetEventFilter(thisDev, xi2), grab);
} else if (rc != BadMatch) } else if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n", ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
thisDev->name, event->any.type, rc); thisDev->name, event->any.type, rc);
@ -4629,9 +4624,8 @@ DeviceEnterLeaveEvent(
if (grab) if (grab)
{ {
Mask mask; Mask mask;
mask = GetXI2MaskByte(grab->xi2mask, mouse, type); mask = xi2mask_isset(grab->xi2mask, mouse, type);
TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, 1, grab);
filter, grab);
} else { } else {
if (!WindowXI2MaskIsset(mouse, pWin, (xEvent*)event)) if (!WindowXI2MaskIsset(mouse, pWin, (xEvent*)event))
goto out; goto out;
@ -5080,29 +5074,30 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
*status = GrabFrozen; *status = GrabFrozen;
else else
{ {
GrabRec tempGrab; GrabPtr tempGrab;
/* Otherwise segfaults happen on grabbed MPX devices */ tempGrab = AllocGrab();
memset(&tempGrab, 0, sizeof(GrabRec));
tempGrab.next = NULL; tempGrab->next = NULL;
tempGrab.window = pWin; tempGrab->window = pWin;
tempGrab.resource = client->clientAsMask; tempGrab->resource = client->clientAsMask;
tempGrab.ownerEvents = ownerEvents; tempGrab->ownerEvents = ownerEvents;
tempGrab.keyboardMode = keyboard_mode; tempGrab->keyboardMode = keyboard_mode;
tempGrab.pointerMode = pointer_mode; tempGrab->pointerMode = pointer_mode;
if (grabtype == GRABTYPE_CORE) if (grabtype == GRABTYPE_CORE)
tempGrab.eventMask = mask->core; tempGrab->eventMask = mask->core;
else if (grabtype == GRABTYPE_XI) else if (grabtype == GRABTYPE_XI)
tempGrab.eventMask = mask->xi; tempGrab->eventMask = mask->xi;
else else
memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask)); xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
tempGrab.device = dev; tempGrab->device = dev;
tempGrab.cursor = cursor; tempGrab->cursor = cursor;
tempGrab.confineTo = confineTo; tempGrab->confineTo = confineTo;
tempGrab.grabtype = grabtype; tempGrab->grabtype = grabtype;
(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE); (*grabInfo->ActivateGrab)(dev, tempGrab, time, FALSE);
*status = GrabSuccess; *status = GrabSuccess;
FreeGrab(tempGrab);
} }
return Success; return Success;
} }
@ -5258,6 +5253,7 @@ void
InitEvents(void) InitEvents(void)
{ {
int i; int i;
QdEventPtr qe, tmp;
inputInfo.numDevices = 0; inputInfo.numDevices = 0;
inputInfo.devices = (DeviceIntPtr)NULL; inputInfo.devices = (DeviceIntPtr)NULL;
@ -5271,13 +5267,10 @@ InitEvents(void)
syncEvents.replayDev = (DeviceIntPtr)NULL; syncEvents.replayDev = (DeviceIntPtr)NULL;
syncEvents.replayWin = NullWindow; syncEvents.replayWin = NullWindow;
while (syncEvents.pending) if (syncEvents.pending.next)
{ list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
QdEventPtr next = syncEvents.pending->next; free(qe);
free(syncEvents.pending); list_init(&syncEvents.pending);
syncEvents.pending = next;
}
syncEvents.pendtail = &syncEvents.pending;
syncEvents.playingEvents = FALSE; syncEvents.playingEvents = FALSE;
syncEvents.time.months = 0; syncEvents.time.months = 0;
syncEvents.time.milliseconds = 0; /* hardly matters */ syncEvents.time.milliseconds = 0; /* hardly matters */
@ -5423,7 +5416,7 @@ ProcUngrabKey(ClientPtr client)
{ {
REQUEST(xUngrabKeyReq); REQUEST(xUngrabKeyReq);
WindowPtr pWin; WindowPtr pWin;
GrabRec tempGrab; GrabPtr tempGrab;
DeviceIntPtr keybd = PickKeyboard(client); DeviceIntPtr keybd = PickKeyboard(client);
int rc; int rc;
@ -5445,21 +5438,27 @@ ProcUngrabKey(ClientPtr client)
client->errorValue = stuff->modifiers; client->errorValue = stuff->modifiers;
return BadValue; return BadValue;
} }
tempGrab.resource = client->clientAsMask; tempGrab = AllocGrab();
tempGrab.device = keybd; if (!tempGrab)
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 BadAlloc;
return Success; 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); REQUEST(xUngrabButtonReq);
WindowPtr pWin; WindowPtr pWin;
GrabRec tempGrab; GrabPtr tempGrab;
int rc; int rc;
DeviceIntPtr ptr; DeviceIntPtr ptr;
@ -5640,21 +5639,26 @@ ProcUngrabButton(ClientPtr client)
ptr = PickPointer(client); ptr = PickPointer(client);
tempGrab.resource = client->clientAsMask; tempGrab = AllocGrab();
tempGrab.device = ptr; if (!tempGrab)
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 BadAlloc;
return Success; 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;
} }
/** /**

View File

@ -60,6 +60,7 @@ SOFTWARE.
#include "dixgrabs.h" #include "dixgrabs.h"
#include "xace.h" #include "xace.h"
#include "exevents.h" #include "exevents.h"
#include "inpututils.h"
#define BITMASK(i) (((Mask)1) << ((i) & 31)) #define BITMASK(i) (((Mask)1) << ((i) & 31))
#define MASKIDX(i) ((i) >> 5) #define MASKIDX(i) ((i) >> 5)
@ -122,13 +123,15 @@ PrintDeviceGrabInfo(DeviceIntPtr dev)
} }
else if (grab->grabtype == GRABTYPE_XI2) 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; int print;
print = 0; print = 0;
for (j = 0; j < XI2MASKSIZE; j++) for (j = 0; j < XI2MASKSIZE; j++)
{ {
if (grab->xi2mask[i][j]) mask = xi2mask_get_one_mask(grab->xi2mask, i);
if (mask[j])
{ {
print = 1; print = 1;
break; break;
@ -137,8 +140,8 @@ PrintDeviceGrabInfo(DeviceIntPtr dev)
if (!print) if (!print)
continue; continue;
ErrorF(" xi2 event mask for device %d: 0x", dev->id); ErrorF(" xi2 event mask for device %d: 0x", dev->id);
for (j = 0; j < XI2MASKSIZE; j++) for (j = 0; j < xi2mask_mask_size(grab->xi2mask); j++)
ErrorF("%x", grab->xi2mask[i][j]); ErrorF("%x", mask[j]);
ErrorF("\n"); ErrorF("\n");
} }
} }
@ -180,6 +183,22 @@ UngrabAllDevices(Bool kill_client)
ErrorF("End list of ungrabbed devices\n"); ErrorF("End list of ungrabbed devices\n");
} }
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 GrabPtr
CreateGrab( CreateGrab(
int client, int client,
@ -196,7 +215,7 @@ CreateGrab(
{ {
GrabPtr grab; GrabPtr grab;
grab = calloc(1, sizeof(GrabRec)); grab = AllocGrab();
if (!grab) if (!grab)
return (GrabPtr)NULL; return (GrabPtr)NULL;
grab->resource = FakeClientID(client); grab->resource = FakeClientID(client);
@ -219,14 +238,14 @@ CreateGrab(
grab->next = NULL; grab->next = NULL;
if (grabtype == GRABTYPE_XI2) if (grabtype == GRABTYPE_XI2)
memcpy(grab->xi2mask, mask->xi2mask, sizeof(mask->xi2mask)); xi2mask_merge(grab->xi2mask, mask->xi2mask);
if (cursor) if (cursor)
cursor->refcnt++; cursor->refcnt++;
return grab; return grab;
} }
static void void
FreeGrab(GrabPtr pGrab) FreeGrab(GrabPtr pGrab)
{ {
free(pGrab->modifiersDetail.pMask); free(pGrab->modifiersDetail.pMask);
@ -235,9 +254,60 @@ FreeGrab(GrabPtr pGrab)
if (pGrab->cursor) if (pGrab->cursor)
FreeCursor(pGrab->cursor, (Cursor)0); FreeCursor(pGrab->cursor, (Cursor)0);
xi2mask_free(&pGrab->xi2mask);
free(pGrab); 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 int
DeletePassiveGrab(pointer value, XID id) DeletePassiveGrab(pointer value, XID id)
{ {

View File

@ -892,3 +892,184 @@ double_to_fp3232(double in)
ret.frac = frac_d; ret.frac = frac_d;
return ret; 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];
}

View File

@ -83,7 +83,7 @@ typedef enum {
*/ */
#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(12, 0) #define ABI_VIDEODRV_VERSION SET_ABI_VERSION(12, 0)
#define ABI_XINPUT_VERSION SET_ABI_VERSION(14, 0) #define ABI_XINPUT_VERSION SET_ABI_VERSION(15, 0)
#define ABI_EXTENSION_VERSION SET_ABI_VERSION(6, 0) #define ABI_EXTENSION_VERSION SET_ABI_VERSION(6, 0)
#define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6)

View File

@ -2,6 +2,10 @@
#ifndef _XAALOCAL_H #ifndef _XAALOCAL_H
#define _XAALOCAL_H #define _XAALOCAL_H
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
/* This file is very unorganized ! */ /* This file is very unorganized ! */

View File

@ -339,6 +339,7 @@ extern _X_EXPORT void NoticeEventTime(InternalEvent *ev);
extern void EnqueueEvent( extern void EnqueueEvent(
InternalEvent * /* ev */, InternalEvent * /* ev */,
DeviceIntPtr /* device */); DeviceIntPtr /* device */);
extern void PlayReleasedEvents(void);
extern void ActivatePointerGrab( extern void ActivatePointerGrab(
DeviceIntPtr /* mouse */, DeviceIntPtr /* mouse */,

View File

@ -31,6 +31,10 @@ struct _GrabParameters;
extern void PrintDeviceGrabInfo(DeviceIntPtr dev); extern void PrintDeviceGrabInfo(DeviceIntPtr dev);
extern void UngrabAllDevices(Bool kill_client); extern void UngrabAllDevices(Bool kill_client);
extern GrabPtr AllocGrab(void);
extern void FreeGrab(GrabPtr grab);
extern Bool CopyGrab(GrabPtr dst, const GrabPtr src);
extern GrabPtr CreateGrab( extern GrabPtr CreateGrab(
int /* client */, int /* client */,
DeviceIntPtr /* device */, DeviceIntPtr /* device */,

View File

@ -205,6 +205,7 @@ extern _X_EXPORT KeybdCtrl defaultKeyboardControl;
extern _X_EXPORT PtrCtrl defaultPointerControl; extern _X_EXPORT PtrCtrl defaultPointerControl;
typedef struct _InputOption InputOption; typedef struct _InputOption InputOption;
typedef struct _XI2Mask XI2Mask;
typedef struct _InputAttributes { typedef struct _InputAttributes {
char *product; char *product;

View File

@ -118,7 +118,7 @@ typedef struct _InputClients {
XID resource; /**< id for putting into resource manager */ XID resource; /**< id for putting into resource manager */
Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */ Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */
/** XI2 event masks. One per device, each bit is a mask of (1 << type) */ /** XI2 event masks. One per device, each bit is a mask of (1 << type) */
unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; struct _XI2Mask *xi2mask;
} InputClients; } InputClients;
/** /**
@ -148,7 +148,7 @@ typedef struct _OtherInputMasks {
/** The clients that selected for events */ /** The clients that selected for events */
InputClientsPtr inputClients; InputClientsPtr inputClients;
/* XI2 event masks. One per device, each bit is a mask of (1 << type) */ /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; struct _XI2Mask *xi2mask;
} OtherInputMasks; } OtherInputMasks;
/* /*
@ -176,7 +176,7 @@ typedef enum {
union _GrabMask { union _GrabMask {
Mask core; Mask core;
Mask xi; Mask xi;
char xi2mask[EMASKSIZE][XI2MASKSIZE]; struct _XI2Mask *xi2mask;
}; };
/** /**
@ -210,7 +210,7 @@ typedef struct _GrabRec {
Mask eventMask; Mask eventMask;
Mask deviceMask; Mask deviceMask;
/* XI2 event masks. One per device, each bit is a mask of (1 << type) */ /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; struct _XI2Mask *xi2mask;
} GrabRec; } GrabRec;
/** /**
@ -451,7 +451,7 @@ typedef struct _GrabInfoRec {
TimeStamp grabTime; TimeStamp grabTime;
Bool fromPassiveGrab; /* true if from passive grab */ Bool fromPassiveGrab; /* true if from passive grab */
Bool implicitGrab; /* implicit from ButtonPress */ Bool implicitGrab; /* implicit from ButtonPress */
GrabRec activeGrab; GrabPtr activeGrab;
GrabPtr grab; GrabPtr grab;
CARD8 activatingKey; CARD8 activatingKey;
void (*ActivateGrab) ( void (*ActivateGrab) (
@ -575,7 +575,7 @@ extern _X_EXPORT InputInfo inputInfo;
/* for keeping the events for devices grabbed synchronously */ /* for keeping the events for devices grabbed synchronously */
typedef struct _QdEvent *QdEventPtr; typedef struct _QdEvent *QdEventPtr;
typedef struct _QdEvent { typedef struct _QdEvent {
QdEventPtr next; struct list next;
DeviceIntPtr device; DeviceIntPtr device;
ScreenPtr pScreen; /* what screen the pointer was on */ ScreenPtr pScreen; /* what screen the pointer was on */
unsigned long months; /* milliseconds is in the event */ unsigned long months; /* milliseconds is in the event */
@ -591,8 +591,8 @@ typedef struct _QdEvent {
* replayed and processed as if they would come from the device directly. * replayed and processed as if they would come from the device directly.
*/ */
typedef struct _EventSyncInfo { typedef struct _EventSyncInfo {
QdEventPtr pending, /**< list of queued events */ struct list pending;
*pendtail; /**< last event in list */
/** The device to replay events for. Only set in AllowEvents(), in which /** The device to replay events for. Only set in AllowEvents(), in which
* case it is set to the device specified in the request. */ * case it is set to the device specified in the request. */
DeviceIntPtr replayDev; /* kludgy rock to put flag for */ DeviceIntPtr replayDev; /* kludgy rock to put flag for */
@ -622,4 +622,10 @@ static inline WindowPtr DeepestSpriteWin(SpritePtr sprite)
return sprite->spriteTrace[sprite->spriteTraceGood - 1]; return sprite->spriteTrace[sprite->spriteTraceGood - 1];
} }
struct _XI2Mask {
unsigned char **masks; /* event mask in masks[deviceid][event type byte] */
size_t nmasks; /* number of masks */
size_t mask_size; /* size of each mask in bytes */
};
#endif /* INPUTSTRUCT_H */ #endif /* INPUTSTRUCT_H */

View File

@ -46,4 +46,16 @@ FP1616 double_to_fp1616(double in);
double fp1616_to_double(FP1616 in); double fp1616_to_double(FP1616 in);
double fp3232_to_double(FP3232 in); double fp3232_to_double(FP3232 in);
XI2Mask* xi2mask_new(void);
XI2Mask* xi2mask_new_with_size(size_t, size_t); /* don't use it */
void xi2mask_free(XI2Mask** mask);
Bool xi2mask_isset(XI2Mask* mask, const DeviceIntPtr dev, int event_type);
void xi2mask_set(XI2Mask *mask, int deviceid, int event_type);
void xi2mask_zero(XI2Mask *mask, int deviceid);
void xi2mask_merge(XI2Mask *dest, const XI2Mask *source);
size_t xi2mask_num_masks(const XI2Mask *mask);
size_t xi2mask_mask_size(const XI2Mask *mask);
void xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, size_t mask_size);
const unsigned char* xi2mask_get_one_mask(const XI2Mask *xi2mask, int deviceid);
#endif #endif

View File

@ -28,6 +28,7 @@
/** /**
* @file Classic doubly-link circular list implementation. * @file Classic doubly-link circular list implementation.
* For real usage examples of the linked list, see the file test/list.c
* *
* Example: * Example:
* We need to keep a list of struct foo in the parent struct bar, i.e. what * We need to keep a list of struct foo in the parent struct bar, i.e. what
@ -35,16 +36,16 @@
* *
* struct bar { * struct bar {
* ... * ...
* struct foo *foos; -----> struct foo {}, struct foo {}, struct foo{} * struct foo *list_of_foos; -----> struct foo {}, struct foo {}, struct foo{}
* ... * ...
* } * }
* *
* We need one list head in bar and a list element in all foos (both are of * We need one list head in bar and a list element in all list_of_foos (both are of
* data type 'struct list'). * data type 'struct list').
* *
* struct bar { * struct bar {
* ... * ...
* struct list foos; * struct list list_of_foos;
* ... * ...
* } * }
* *
@ -58,27 +59,27 @@
* *
* struct bar bar; * struct bar bar;
* ... * ...
* list_init(&bar.foos); * list_init(&bar.list_of_foos);
* *
* Then we create the first element and add it to this list: * Then we create the first element and add it to this list:
* *
* struct foo *foo = malloc(...); * struct foo *foo = malloc(...);
* .... * ....
* list_add(&foo->entry, &bar.foos); * list_add(&foo->entry, &bar.list_of_foos);
* *
* Repeat the above for each element you want to add to the list. Deleting * Repeat the above for each element you want to add to the list. Deleting
* works with the element itself. * works with the element itself.
* list_del(&foo->entry); * list_del(&foo->entry);
* free(foo); * free(foo);
* *
* Note: calling list_del(&bar.foos) will set bar.foos to an empty * Note: calling list_del(&bar.list_of_foos) will set bar.list_of_foos to an empty
* list again. * list again.
* *
* Looping through the list requires a 'struct foo' as iterator and the * Looping through the list requires a 'struct foo' as iterator and the
* name of the field the subnodes use. * name of the field the subnodes use.
* *
* struct foo *iterator; * struct foo *iterator;
* list_for_each_entry(iterator, &bar.foos, entry) { * list_for_each_entry(iterator, &bar.list_of_foos, entry) {
* if (iterator->something == ...) * if (iterator->something == ...)
* ... * ...
* } * }
@ -87,7 +88,7 @@
* loop. You need to run the safe for-each loop instead: * loop. You need to run the safe for-each loop instead:
* *
* struct foo *iterator, *next; * struct foo *iterator, *next;
* list_for_each_entry_safe(iterator, next, &bar.foos, entry) { * list_for_each_entry_safe(iterator, next, &bar.list_of_foos, entry) {
* if (...) * if (...)
* list_del(&iterator->entry); * list_del(&iterator->entry);
* } * }
@ -96,14 +97,8 @@
/** /**
* The linkage struct for list nodes. This struct must be part of your * The linkage struct for list nodes. This struct must be part of your
* to-be-linked struct. * to-be-linked struct. struct list is required for both the head of the
* * list and for each list node.
* Example:
* struct foo {
* int a;
* void *b;
* struct list *mylist;
* }
* *
* Position and name of the struct list field is irrelevant. * Position and name of the struct list field is irrelevant.
* There are no requirements that elements of a list are of the same type. * There are no requirements that elements of a list are of the same type.
@ -118,7 +113,7 @@ struct list {
* Initialize the list as an empty list. * Initialize the list as an empty list.
* *
* Example: * Example:
* list_init(&foo->mylist); * list_init(&bar->list_of_foos);
* *
* @param The list to initialized. * @param The list to initialized.
*/ */
@ -140,7 +135,8 @@ __list_add(struct list *entry,
} }
/** /**
* Insert a new element after the given list head. * Insert a new element after the given list head. The new element does not
* need to be initialised as empty list.
* The list changes from: * The list changes from:
* head some element ... * head some element ...
* to * to
@ -148,7 +144,7 @@ __list_add(struct list *entry,
* *
* Example: * Example:
* struct foo *newfoo = malloc(...); * struct foo *newfoo = malloc(...);
* list_add(&newfoo->mylist, &foo->mylist); * list_add(&newfoo->entry, &bar->list_of_foos);
* *
* @param entry The new element to prepend to the list. * @param entry The new element to prepend to the list.
* @param head The existing list. * @param head The existing list.
@ -159,6 +155,28 @@ list_add(struct list *entry, struct list *head)
__list_add(entry, head, head->next); __list_add(entry, head, head->next);
} }
/**
* Append a new element to the end of the list given with this list head.
*
* The list changes from:
* head some element ... lastelement
* to
* head some element ... lastelement new element
*
* Example:
* struct foo *newfoo = malloc(...);
* list_append(&newfoo->entry, &bar->list_of_foos);
*
* @param entry The new element to prepend to the list.
* @param head The existing list.
*/
static inline void
list_append(struct list *entry, struct list *head)
{
__list_add(entry, head->prev, head);
}
static inline void static inline void
__list_del(struct list *prev, struct list *next) __list_del(struct list *prev, struct list *next)
{ {
@ -176,7 +194,7 @@ __list_del(struct list *prev, struct list *next)
* the list but rather reset the list as empty list. * the list but rather reset the list as empty list.
* *
* Example: * Example:
* list_del(&newfoo->mylist); * list_del(&foo->entry);
* *
* @param entry The element to remove. * @param entry The element to remove.
*/ */
@ -191,7 +209,7 @@ list_del(struct list *entry)
* Check if the list is empty. * Check if the list is empty.
* *
* Example: * Example:
* list_is_empty(&foo->mylist); * list_is_empty(&bar->list_of_foos);
* *
* @return True if the list contains one or more elements or False otherwise. * @return True if the list contains one or more elements or False otherwise.
*/ */
@ -206,7 +224,7 @@ list_is_empty(struct list *head)
* *
* Example: * Example:
* struct foo* f; * struct foo* f;
* f = container_of(&foo->mylist, struct foo, mylist); * f = container_of(&foo->entry, struct foo, entry);
* assert(f == foo); * assert(f == foo);
* *
* @param ptr Pointer to the struct list. * @param ptr Pointer to the struct list.
@ -230,7 +248,7 @@ list_is_empty(struct list *head)
* *
* Example: * Example:
* struct foo *first; * struct foo *first;
* first = list_first_entry(&foo->mylist, struct foo, mylist); * first = list_first_entry(&bar->list_of_foos, struct foo, list_of_foos);
* *
* @param ptr The list head * @param ptr The list head
* @param type Data type of the list element to retrieve * @param type Data type of the list element to retrieve
@ -240,6 +258,21 @@ list_is_empty(struct list *head)
#define list_first_entry(ptr, type, member) \ #define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member) list_entry((ptr)->next, type, member)
/**
* Retrieve the last list entry for the given listpointer.
*
* Example:
* struct foo *first;
* first = list_last_entry(&bar->list_of_foos, struct foo, list_of_foos);
*
* @param ptr The list head
* @param type Data type of the list element to retrieve
* @param member Member name of the struct list field in the list element.
* @return A pointer to the last list element.
*/
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
#define __container_of(ptr, sample, member) \ #define __container_of(ptr, sample, member) \
(void *)((char *)(ptr) \ (void *)((char *)(ptr) \
- ((char *)&(sample)->member - (char *)(sample))) - ((char *)&(sample)->member - (char *)(sample)))
@ -248,7 +281,7 @@ list_is_empty(struct list *head)
* *
* Example: * Example:
* struct foo *iterator; * struct foo *iterator;
* list_for_each_entry(iterator, &foo->mylist, mylist) { * list_for_each_entry(iterator, &bar->list_of_foos, entry) {
* [modify iterator] * [modify iterator]
* } * }
* *

View File

@ -359,11 +359,18 @@ typedef struct _CharInfo *CharInfoPtr; /* also in fonts/include/font.h */
extern _X_EXPORT unsigned long globalSerialNumber; extern _X_EXPORT unsigned long globalSerialNumber;
extern _X_EXPORT unsigned long serverGeneration; extern _X_EXPORT unsigned long serverGeneration;
#define BUG_WARN(cond) \ /* Don't use this directly, use BUG_WARN or BUG_WARN_MSG instead */
#define __BUG_WARN_MSG(cond, with_msg, ...) \
do { if (cond) { \ do { if (cond) { \
ErrorF("BUG: triggered 'if (" #cond ")'\nBUG: %s:%d in %s()\n", \ ErrorF("BUG: triggered 'if (" #cond ")'\nBUG: %s:%d in %s()\n", \
__FILE__, __LINE__, __func__); \ __FILE__, __LINE__, __func__); \
if (with_msg) ErrorF(__VA_ARGS__); \
xorg_backtrace(); \ xorg_backtrace(); \
} } while(0) } } while(0)
#define BUG_WARN_MSG(cond, msg, ...) \
__BUG_WARN_MSG(cond, 1, msg, __VA_ARGS__)
#define BUG_WARN(cond) __BUG_WARN_MSG(cond, 0, NULL)
#endif /* MISC_H */ #endif /* MISC_H */

View File

@ -1674,8 +1674,75 @@ mieq_test(void) {
mieqFini(); mieqFini();
} }
/* Simple check that we're replaying events in-order */
static void
process_input_proc(InternalEvent *ev, DeviceIntPtr device)
{
static int last_evtype = -1;
if (ev->any.header == 0xac)
last_evtype = -1;
assert(ev->any.type == ++last_evtype);
}
static void
dix_enqueue_events(void) {
#define NEVENTS 5
DeviceIntRec dev;
InternalEvent ev[NEVENTS];
SpriteInfoRec spriteInfo;
SpriteRec sprite;
QdEventPtr qe;
int i;
memset(&dev, 0, sizeof(dev));
dev.public.processInputProc = process_input_proc;
memset(&spriteInfo, 0, sizeof(spriteInfo));
memset(&sprite, 0, sizeof(sprite));
dev.spriteInfo = &spriteInfo;
spriteInfo.sprite = &sprite;
InitEvents();
assert(list_is_empty(&syncEvents.pending));
/* this way PlayReleasedEvents really runs through all events in the
* queue */
inputInfo.devices = &dev;
/* to reset process_input_proc */
ev[0].any.header = 0xac;
for (i = 0; i < NEVENTS; i++)
{
ev[i].any.length = sizeof(*ev);
ev[i].any.type = i;
EnqueueEvent(&ev[i], &dev);
assert(!list_is_empty(&syncEvents.pending));
qe = list_last_entry(&syncEvents.pending, QdEventRec, next);
assert(memcmp(qe->event, &ev[i], ev[i].any.length) == 0);
qe = list_first_entry(&syncEvents.pending, QdEventRec, next);
assert(memcmp(qe->event, &ev[0], ev[i].any.length) == 0);
}
/* calls process_input_proc */
dev.deviceGrab.sync.frozen = 1;
PlayReleasedEvents();
assert(!list_is_empty(&syncEvents.pending));
dev.deviceGrab.sync.frozen = 0;
PlayReleasedEvents();
assert(list_is_empty(&syncEvents.pending));
inputInfo.devices = NULL;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
dix_enqueue_events();
dix_double_fp_conversion(); dix_double_fp_conversion();
dix_input_valuator_masks(); dix_input_valuator_masks();
dix_input_attributes(); dix_input_attributes();

View File

@ -88,6 +88,42 @@ test_list_add(void)
assert(memcmp(c, &child[2], sizeof(struct child)) == 0); assert(memcmp(c, &child[2], sizeof(struct child)) == 0);
}; };
static void
test_list_append(void)
{
struct parent parent = {0};
struct child child[3];
struct child *c;
int i;
list_init(&parent.children);
list_append(&child[0].node, &parent.children);
assert(!list_is_empty(&parent.children));
c = list_first_entry(&parent.children, struct child, node);
assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
c = list_last_entry(&parent.children, struct child, node);
assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
list_append(&child[1].node, &parent.children);
c = list_first_entry(&parent.children, struct child, node);
assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
c = list_last_entry(&parent.children, struct child, node);
assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
list_append(&child[2].node, &parent.children);
c = list_first_entry(&parent.children, struct child, node);
assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
c = list_last_entry(&parent.children, struct child, node);
assert(memcmp(c, &child[2], sizeof(struct child)) == 0);
i = 0;
list_for_each_entry(c, &parent.children, node) {
assert(memcmp(c, &child[i++], sizeof(struct child)) == 0);
}
};
static void static void
test_list_del(void) test_list_del(void)
{ {
@ -325,6 +361,7 @@ int main(int argc, char** argv)
{ {
test_list_init(); test_list_init();
test_list_add(); test_list_add();
test_list_append();
test_list_del(); test_list_del();
test_list_for_each(); test_list_for_each();

View File

@ -10,7 +10,8 @@ noinst_PROGRAMS = \
protocol-xipassivegrabdevice \ protocol-xipassivegrabdevice \
protocol-xiquerypointer \ protocol-xiquerypointer \
protocol-xiwarppointer \ protocol-xiwarppointer \
protocol-eventconvert protocol-eventconvert \
xi2
TESTS=$(noinst_PROGRAMS) TESTS=$(noinst_PROGRAMS)
TESTS_ENVIRONMENT = $(XORG_MALLOC_DEBUG_ENV) TESTS_ENVIRONMENT = $(XORG_MALLOC_DEBUG_ENV)
@ -34,6 +35,7 @@ protocol_xiquerypointer_LDADD=$(TEST_LDADD)
protocol_xipassivegrabdevice_LDADD=$(TEST_LDADD) protocol_xipassivegrabdevice_LDADD=$(TEST_LDADD)
protocol_xiwarppointer_LDADD=$(TEST_LDADD) protocol_xiwarppointer_LDADD=$(TEST_LDADD)
protocol_eventconvert_LDADD=$(TEST_LDADD) protocol_eventconvert_LDADD=$(TEST_LDADD)
xi2_LDADD=$(TEST_LDADD)
protocol_xiqueryversion_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient protocol_xiqueryversion_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient
protocol_xiquerydevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient protocol_xiquerydevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient
@ -44,6 +46,7 @@ protocol_xigetclientpointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-w
protocol_xipassivegrabdevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,GrabButton -Wl,-wrap,dixLookupWindow -Wl,-wrap,WriteToClient protocol_xipassivegrabdevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,GrabButton -Wl,-wrap,dixLookupWindow -Wl,-wrap,WriteToClient
protocol_xiquerypointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow protocol_xiquerypointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow
protocol_xiwarppointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow protocol_xiwarppointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow
xi2_LDFLAGS=$(AM_LDFLAGS)
protocol_xiqueryversion_SOURCES=$(COMMON_SOURCES) protocol-xiqueryversion.c protocol_xiqueryversion_SOURCES=$(COMMON_SOURCES) protocol-xiqueryversion.c
protocol_xiquerydevice_SOURCES=$(COMMON_SOURCES) protocol-xiquerydevice.c protocol_xiquerydevice_SOURCES=$(COMMON_SOURCES) protocol-xiquerydevice.c

129
test/xi2/xi2.c Normal file
View File

@ -0,0 +1,129 @@
/**
* Copyright © 2011 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdint.h>
#include "inpututils.h"
#include "inputstr.h"
#include "assert.h"
static void xi2mask_test(void)
{
XI2Mask *xi2mask = NULL,
*mergemask = NULL;
unsigned char *mask;
DeviceIntRec dev;
int i;
/* size >= nmasks * 2 for the test cases below */
xi2mask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2);
assert(xi2mask);
assert(xi2mask->nmasks > 0);
assert(xi2mask->mask_size > 0);
assert(xi2mask_mask_size(xi2mask) == xi2mask->mask_size);
assert(xi2mask_num_masks(xi2mask) == xi2mask->nmasks);
mask = calloc(1, xi2mask_mask_size(xi2mask));
/* ensure zeros */
for (i = 0; i < xi2mask_num_masks(xi2mask); i++) {
const unsigned char *m = xi2mask_get_one_mask(xi2mask, i);
assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0);
}
/* set various bits */
for (i = 0; i < xi2mask_num_masks(xi2mask); i++) {
const unsigned char *m;
xi2mask_set(xi2mask, i, i);
dev.id = i;
assert(xi2mask_isset(xi2mask, &dev, i));
m = xi2mask_get_one_mask(xi2mask, i);
SetBit(mask, i);
assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0);
ClearBit(mask, i);
}
/* ensure zeros one-by-one */
for (i = 0; i < xi2mask_num_masks(xi2mask); i++) {
const unsigned char *m = xi2mask_get_one_mask(xi2mask, i);
assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) != 0);
xi2mask_zero(xi2mask, i);
assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0);
}
/* re-set, zero all */
for (i = 0; i < xi2mask_num_masks(xi2mask); i++)
xi2mask_set(xi2mask, i, i);
xi2mask_zero(xi2mask, -1);
for (i = 0; i < xi2mask_num_masks(xi2mask); i++) {
const unsigned char *m = xi2mask_get_one_mask(xi2mask, i);
assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0);
}
for (i = 0; i < xi2mask_num_masks(xi2mask); i++) {
const unsigned char *m;
SetBit(mask, i);
xi2mask_set_one_mask(xi2mask, i, mask, xi2mask_mask_size(xi2mask));
m = xi2mask_get_one_mask(xi2mask, i);
assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0);
ClearBit(mask, i);
}
mergemask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2);
for (i = 0; i < xi2mask_num_masks(mergemask); i++) {
dev.id = i;
xi2mask_set(mergemask, i, i * 2);
}
/* xi2mask still has all i bits set, should now also have all i * 2 bits */
xi2mask_merge(xi2mask, mergemask);
for (i = 0; i < xi2mask_num_masks(mergemask); i++) {
const unsigned char *m = xi2mask_get_one_mask(xi2mask, i);
SetBit(mask, i);
SetBit(mask, i * 2);
assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0);
ClearBit(mask, i);
ClearBit(mask, i * 2);
}
xi2mask_free(&xi2mask);
assert(xi2mask == NULL);
xi2mask_free(&mergemask);
assert(mergemask == NULL);
free(mask);
}
int main(int argc, char** argv)
{
xi2mask_test();
return 0;
}

View File

@ -179,9 +179,9 @@ CursorDisplayCursor (DeviceIntPtr pDev,
ev.type = XFixesEventBase + XFixesCursorNotify; ev.type = XFixesEventBase + XFixesCursorNotify;
ev.subtype = XFixesDisplayCursorNotify; ev.subtype = XFixesDisplayCursorNotify;
ev.window = e->pWindow->drawable.id; ev.window = e->pWindow->drawable.id;
ev.cursorSerial = pCursor->serialNumber; ev.cursorSerial = pCursor ? pCursor->serialNumber : 0;
ev.timestamp = currentTime.milliseconds; ev.timestamp = currentTime.milliseconds;
ev.name = pCursor->name; ev.name = pCursor ? pCursor->name : None;
WriteEventsToClient (e->pClient, 1, (xEvent *) &ev); WriteEventsToClient (e->pClient, 1, (xEvent *) &ev);
} }
} }