aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix')
-rw-r--r--xorg-server/dix/devices.c33
-rw-r--r--xorg-server/dix/events.c173
-rw-r--r--xorg-server/dix/getevents.c27
-rw-r--r--xorg-server/dix/grabs.c2
-rw-r--r--xorg-server/dix/inpututils.c155
5 files changed, 286 insertions, 104 deletions
diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c
index 0ccf25277..ab8a648a9 100644
--- a/xorg-server/dix/devices.c
+++ b/xorg-server/dix/devices.c
@@ -2406,7 +2406,6 @@ int
AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
{
ScreenPtr screen;
- DeviceIntPtr oldmaster;
if (!dev || IsMaster(dev))
return BadDevice;
@@ -2425,7 +2424,6 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
free(dev->spriteInfo->sprite);
}
- oldmaster = GetMaster(dev, MASTER_ATTACHED);
dev->master = master;
/* If device is set to floating, we need to create a sprite for it,
@@ -2484,16 +2482,22 @@ GetPairedDevice(DeviceIntPtr dev)
/**
- * Returns the right master for the type of event needed. If the event is a
- * keyboard event.
- * This function may be called with a master device as argument. If so, the
- * returned master is either the device itself or the paired master device.
- * If dev is a floating slave device, NULL is returned.
+ * Returns the requested master for this device.
+ * The return values are:
+ * - MASTER_ATTACHED: the master for this device or NULL for a floating
+ * slave.
+ * - MASTER_KEYBOARD: the master keyboard for this device or NULL for a
+ * floating slave
+ * - MASTER_POINTER: the master keyboard for this device or NULL for a
+ * floating slave
+ * - POINTER_OR_FLOAT: the master pointer for this device or the device for
+ * a floating slave
+ * - KEYBOARD_OR_FLOAT: the master keyboard for this device or the device for
+ * a floating slave
*
- * @type ::MASTER_KEYBOARD or ::MASTER_POINTER or ::MASTER_ATTACHED
- * @return The requested master device. In the case of MASTER_ATTACHED, this
- * is the directly attached master to this device, regardless of the type.
- * Otherwise, it is either the master keyboard or pointer for this device.
+ * @param which ::MASTER_KEYBOARD or ::MASTER_POINTER, ::MASTER_ATTACHED,
+ * ::POINTER_OR_FLOAT or ::KEYBOARD_OR_FLOAT.
+ * @return The requested master device
*/
DeviceIntPtr
GetMaster(DeviceIntPtr dev, int which)
@@ -2502,12 +2506,15 @@ GetMaster(DeviceIntPtr dev, int which)
if (IsMaster(dev))
master = dev;
- else
+ else {
master = dev->master;
+ if (!master && (which == POINTER_OR_FLOAT || which == KEYBOARD_OR_FLOAT))
+ return dev;
+ }
if (master && which != MASTER_ATTACHED)
{
- if (which == MASTER_KEYBOARD)
+ if (which == MASTER_KEYBOARD || which == KEYBOARD_OR_FLOAT)
{
if (master->type != MASTER_KEYBOARD)
master = GetPairedDevice(master);
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 8a4c6b9ac..fbe4fc953 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -408,6 +408,24 @@ static const Mask default_filter[128] =
CantBeFiltered /* MappingNotify */
};
+static inline Mask
+GetEventFilterMask(DeviceIntPtr dev, int evtype)
+{
+ return filters[dev ? dev->id : 0][evtype];
+}
+
+static inline Mask
+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.
@@ -429,14 +447,28 @@ GetEventFilter(DeviceIntPtr dev, xEvent *event)
int evtype = 0;
if (event->u.u.type != GenericEvent)
- return filters[dev ? dev->id : 0][event->u.u.type];
+ return GetEventFilterMask(dev, event->u.u.type);
else if ((evtype = xi2_get_type(event)))
- return (1 << (evtype % 8));
+ return GetXI2EventFilterMask(evtype);
ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
return 0;
}
/**
+ * Return the single byte of the device's XI2 mask that contains the mask
+ * for the event_type.
+ */
+static int
+GetXI2MaskByte(unsigned char xi2mask[][XI2MASKSIZE], DeviceIntPtr dev, int event_type)
+{
+ int byte = GetXI2EventFilterOffset(event_type);
+ return xi2mask[dev->id][byte] |
+ xi2mask[XIAllDevices][byte] |
+ (IsMaster(dev) ? xi2mask[XIAllMasterDevices][byte] : 0);
+}
+
+
+/**
* Return the windows complete XI2 mask for the given XI2 event type.
*/
Mask
@@ -452,9 +484,7 @@ GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
evtype = ((xGenericEvent*)ev)->evtype;
filter = GetEventFilter(dev, ev);
- return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) ||
- inputMasks->xi2mask[XIAllDevices][evtype/8] ||
- (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev)));
+ return (GetXI2MaskByte(inputMasks->xi2mask, dev, evtype) & filter);
}
Mask
@@ -465,10 +495,7 @@ GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
/* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
if ((evtype = xi2_get_type(event)))
{
- int byte = evtype / 8;
- return (other->xi2mask[dev->id][byte] |
- other->xi2mask[XIAllDevices][byte] |
- (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0));
+ return GetXI2MaskByte(other->xi2mask, dev, evtype);
} else if (core_get_type(event) != 0)
return other->mask[XIAllDevices];
else
@@ -680,9 +707,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
BoxRec box;
int x = *px, y = *py;
int incx = 1, incy = 1;
- SpritePtr pSprite;
- pSprite = pDev->spriteInfo->sprite;
if (RegionContainsPoint(shape, x, y, &box))
return;
box = *RegionExtents(shape);
@@ -2478,44 +2503,45 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
int filter = 0;
int type;
OtherInputMasks *inputMasks = wOtherInputMasks(win);
- xEvent ev;
-
- /* XXX: this makes me gag */
- type = GetXI2Type(event);
- ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/
- ((xGenericEvent*)&ev)->extension = IReqCode;
- ((xGenericEvent*)&ev)->evtype = type;
- filter = GetEventFilter(dev, &ev);
- if (type && inputMasks &&
- ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
- ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
- (inputMasks->xi2mask[dev->id][type/8] & filter)))
- rc |= EVENT_XI2_MASK;
-
- type = GetXIType(event);
- ev.u.u.type = type;
- filter = GetEventFilter(dev, &ev);
-
- /* Check for XI mask */
- if (type && inputMasks &&
- (inputMasks->deliverableEvents[dev->id] & filter) &&
- (inputMasks->inputEvents[dev->id] & filter))
- rc |= EVENT_XI1_MASK;
-
- /* Check for XI DontPropagate mask */
- if (type && inputMasks &&
- (inputMasks->dontPropagateMask[dev->id] & filter))
- rc |= EVENT_DONT_PROPAGATE_MASK;
-
- /* Check for core mask */
- type = GetCoreType(event);
- if (type && (win->deliverableEvents & filter) &&
- ((wOtherEventMasks(win) | win->eventMask) & filter))
- rc |= EVENT_CORE_MASK;
-
- /* Check for core DontPropagate mask */
- if (type && (filter & wDontPropagateMask(win)))
- rc |= EVENT_DONT_PROPAGATE_MASK;
+
+ if ((type = GetXI2Type(event)) != 0)
+ {
+ filter = GetXI2EventFilterMask(type);
+
+ if (inputMasks &&
+ (GetXI2MaskByte(inputMasks->xi2mask, dev, type) & filter))
+ rc |= EVENT_XI2_MASK;
+ }
+
+ if ((type = GetXIType(event)) != 0)
+ {
+ filter = GetEventFilterMask(dev, type);
+
+ /* Check for XI mask */
+ if (inputMasks &&
+ (inputMasks->deliverableEvents[dev->id] & filter) &&
+ (inputMasks->inputEvents[dev->id] & filter))
+ rc |= EVENT_XI1_MASK;
+
+ /* Check for XI DontPropagate mask */
+ if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
+ rc |= EVENT_DONT_PROPAGATE_MASK;
+
+ }
+
+ if ((type = GetCoreType(event)) != 0)
+ {
+ filter = GetEventFilterMask(dev, type);
+
+ /* Check for core mask */
+ if ((win->deliverableEvents & filter) &&
+ ((wOtherEventMasks(win) | win->eventMask) & filter))
+ rc |= EVENT_CORE_MASK;
+
+ /* Check for core DontPropagate mask */
+ if (filter & wDontPropagateMask(win))
+ rc |= EVENT_DONT_PROPAGATE_MASK;
+ }
return rc;
}
@@ -3351,16 +3377,21 @@ XineramaWarpPointer(ClientPtr client)
{
WindowPtr dest = NULL;
int x, y, rc;
- SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
+ DeviceIntPtr dev;
+ SpritePtr pSprite;
REQUEST(xWarpPointerReq);
-
if (stuff->dstWid != None) {
rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
if (rc != Success)
return rc;
}
+
+ /* Post through the XTest device */
+ dev = PickPointer(client);
+ dev = GetXTestDevice(dev);
+ pSprite = dev->spriteInfo->sprite;
x = pSprite->hotPhys.x;
y = pSprite->hotPhys.y;
@@ -3410,9 +3441,9 @@ XineramaWarpPointer(ClientPtr client)
else if (y >= pSprite->physLimits.y2)
y = pSprite->physLimits.y2 - 1;
if (pSprite->hotShape)
- ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
+ ConfineToShape(dev, pSprite->hotShape, &x, &y);
- XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
+ XineramaSetCursorPosition(dev, x, y, TRUE);
return Success;
}
@@ -3430,7 +3461,7 @@ ProcWarpPointer(ClientPtr client)
WindowPtr dest = NULL;
int x, y, rc;
ScreenPtr newScreen;
- DeviceIntPtr dev, tmp;
+ DeviceIntPtr dev, tmp, xtest_dev = NULL;
SpritePtr pSprite;
REQUEST(xWarpPointerReq);
@@ -3443,11 +3474,13 @@ ProcWarpPointer(ClientPtr client)
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
if (rc != Success)
return rc;
+ if (IsXTestDevice(tmp, dev))
+ xtest_dev = tmp;
}
}
- if (dev->lastSlave)
- dev = dev->lastSlave;
+ /* Use the XTest device to actually move the pointer */
+ dev = xtest_dev;
pSprite = dev->spriteInfo->sprite;
#ifdef PANORAMIX
@@ -3678,7 +3711,7 @@ CheckPassiveGrabsOnWindow(
if (tempGrab.type < GenericEvent)
{
grab->device = device;
- grab->modifierDevice = GetPairedDevice(device);
+ grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
}
for (other = inputInfo.devices; other; other = other->next)
@@ -4063,9 +4096,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
if (rc == Success)
{
int evtype = xi2_get_type(xi2);
- mask = grab->xi2mask[XIAllDevices][evtype/8] |
- grab->xi2mask[XIAllMasterDevices][evtype/8] |
- grab->xi2mask[thisDev->id][evtype/8];
+ mask = GetXI2MaskByte(grab->xi2mask, thisDev, evtype);
/* try XI2 event */
FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
/* XXX: XACE */
@@ -4544,9 +4575,7 @@ DeviceEnterLeaveEvent(
if (grab)
{
Mask mask;
- mask = grab->xi2mask[XIAllDevices][type/8] |
- grab->xi2mask[XIAllMasterDevices][type/8] |
- grab->xi2mask[mouse->id][type/8];
+ mask = GetXI2MaskByte(grab->xi2mask, mouse, type);
TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
filter, grab);
} else {
@@ -4765,7 +4794,6 @@ ProcGrabPointer(ClientPtr client)
WindowPtr confineTo;
CursorPtr oldCursor;
REQUEST(xGrabPointerReq);
- TimeStamp time;
int rc;
REQUEST_SIZE_MATCH(xGrabPointerReq);
@@ -4811,7 +4839,6 @@ ProcGrabPointer(ClientPtr client)
if (oldCursor && rep.status == GrabSuccess)
FreeCursor (oldCursor, (Cursor)0);
- time = ClientTimeToServerTime(stuff->time);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
@@ -5224,6 +5251,8 @@ CloseDownEvents(void)
InputEventList = NULL;
}
+#define SEND_EVENT_BIT 0x80
+
/**
* Server-side protocol handling for SendEvent request.
*
@@ -5241,6 +5270,16 @@ ProcSendEvent(ClientPtr client)
REQUEST_SIZE_MATCH(xSendEventReq);
+ /* libXext and other extension libraries may set the bit indicating
+ * that this event came from a SendEvent request so remove it
+ * since otherwise the event type may fail the range checks
+ * and cause an invalid BadValue error to be returned.
+ *
+ * This is safe to do since we later add the SendEvent bit (0x80)
+ * back in once we send the event to the client */
+
+ stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
+
/* The client's event type must be a core event type or one defined by an
extension. */
@@ -5298,7 +5337,7 @@ ProcSendEvent(ClientPtr client)
client->errorValue = stuff->propagate;
return BadValue;
}
- stuff->event.u.u.type |= 0x80;
+ stuff->event.u.u.type |= SEND_EVENT_BIT;
if (stuff->propagate)
{
for (;pWin; pWin = pWin->parent)
@@ -5360,7 +5399,7 @@ ProcUngrabKey(ClientPtr client)
tempGrab.window = pWin;
tempGrab.modifiersDetail.exact = stuff->modifiers;
tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.modifierDevice = GetPairedDevice(keybd);
+ tempGrab.modifierDevice = keybd;
tempGrab.type = KeyPress;
tempGrab.grabtype = GRABTYPE_CORE;
tempGrab.detail.exact = stuff->key;
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index a12462a4a..be2840c47 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -154,17 +154,6 @@ key_autorepeats(DeviceIntPtr pDev, int key_code)
}
static void
-init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
-{
- memset(event, 0, sizeof(DeviceEvent));
- event->header = ET_Internal;
- event->length = sizeof(DeviceEvent);
- event->time = ms;
- event->deviceid = dev->id;
- event->sourceid = dev->id;
-}
-
-static void
init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
{
memset(event, 0, sizeof(RawDeviceEvent));
@@ -414,7 +403,6 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
Time current;
/* The size of a single motion event. */
int size;
- int dflt;
AxisInfo from, *to; /* for scaling */
INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
INT16 *corebuf;
@@ -502,13 +490,6 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
else if (j == 1 && (from.max_value < from.min_value))
from.max_value = pScreen->height;
- if (j == 0 && (to->max_value < to->min_value))
- dflt = pScreen->width;
- else if (j == 1 && (to->max_value < to->min_value))
- dflt = pScreen->height;
- else
- dflt = 0;
-
/* scale from stored range into current range */
coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
memcpy(ocbuf, &coord, sizeof(INT32));
@@ -1014,7 +995,7 @@ GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
set_raw_valuators(raw, &mask, raw->valuators.data);
event = &events->device_event;
- init_event(pDev, event, ms);
+ init_device_event(event, pDev, ms);
event->detail.key = key_code;
if (type == KeyPress) {
@@ -1236,7 +1217,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
clipValuators(pDev, &mask);
event = &events->device_event;
- init_event(pDev, event, ms);
+ init_device_event(event, pDev, ms);
if (type == MotionNotify) {
event->type = ET_Motion;
@@ -1329,7 +1310,7 @@ GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type, const Val
events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
event = &events->device_event;
- init_event(pDev, event, GetTimeInMillis());
+ init_device_event(event, pDev, GetTimeInMillis());
event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
clipValuators(pDev, &mask);
@@ -1365,7 +1346,7 @@ PostSyntheticMotion(DeviceIntPtr pDev,
#endif
memset(&ev, 0, sizeof(DeviceEvent));
- init_event(pDev, &ev, time);
+ init_device_event(&ev, pDev, time);
ev.root_x = x;
ev.root_y = y;
ev.type = ET_Motion;
diff --git a/xorg-server/dix/grabs.c b/xorg-server/dix/grabs.c
index 85ca9eee0..c28356d9b 100644
--- a/xorg-server/dix/grabs.c
+++ b/xorg-server/dix/grabs.c
@@ -479,7 +479,7 @@ AddPassiveGrabToList(ClientPtr client, GrabPtr pGrab)
for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
{
- if (GrabMatchesSecond(pGrab, grab, FALSE))
+ if (GrabMatchesSecond(pGrab, grab, (pGrab->grabtype == GRABTYPE_CORE)))
{
if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
{
diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c
index 49e175822..7aeb1e516 100644
--- a/xorg-server/dix/inpututils.c
+++ b/xorg-server/dix/inpututils.c
@@ -584,3 +584,158 @@ void verify_internal_event(const InternalEvent *ev)
FatalError("Wrong event type %d. Aborting server\n", ev->any.header);
}
}
+
+/**
+ * Initializes the given event to zero (or default values), for the given
+ * device.
+ */
+void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms)
+{
+ memset(event, 0, sizeof(DeviceEvent));
+ event->header = ET_Internal;
+ event->length = sizeof(DeviceEvent);
+ event->time = ms;
+ event->deviceid = dev->id;
+ event->sourceid = dev->id;
+}
+
+/**
+ * Delete the element with the key from the list, freeing all memory
+ * associated with the element..
+ */
+static void
+input_option_free(InputOption *o)
+{
+ free(o->key);
+ free(o->value);
+ free(o);
+}
+
+/*
+ * Create a new InputOption with the key/value pair provided.
+ * If a list is provided, the new options is added to the list and the list
+ * is returned.
+ *
+ * If a new option is added to a list that already contains that option, the
+ * previous option is overwritten.
+ *
+ * @param list The list to add to.
+ * @param key Option key, will be copied.
+ * @param value Option value, will be copied.
+ *
+ * @return If list is not NULL, the list with the new option added. If list
+ * is NULL, a new option list with one element. On failure, NULL is
+ * returned.
+ */
+InputOption*
+input_option_new(InputOption* list, const char *key, const char *value)
+{
+ InputOption *opt = NULL;
+
+ if (!key)
+ return NULL;
+
+ if (list)
+ {
+ nt_list_for_each_entry(opt, list, next)
+ {
+ if (strcmp(input_option_get_key(opt), key) == 0)
+ {
+ input_option_set_value(opt, value);
+ return list;
+ }
+ }
+ }
+
+ opt = calloc(1, sizeof(InputOption));
+ if (!opt)
+ return NULL;
+
+ nt_list_init(opt, next);
+ input_option_set_key(opt, key);
+ input_option_set_value(opt, value);
+
+ if (list)
+ {
+ nt_list_append(opt, list, InputOption, next);
+ return list;
+ } else
+ return opt;
+}
+
+InputOption*
+input_option_free_element(InputOption *list, const char *key)
+{
+ InputOption *element;
+
+ nt_list_for_each_entry(element, list, next) {
+ if (strcmp(input_option_get_key(element), key) == 0) {
+ nt_list_del(element, list, InputOption, next);
+ input_option_free(element);
+ break;
+ }
+ }
+ return list;
+}
+
+/**
+ * Free the list pointed at by opt.
+ */
+void
+input_option_free_list(InputOption **opt)
+{
+ InputOption *element, *tmp;
+
+ nt_list_for_each_entry_safe(element, tmp, *opt, next) {
+ nt_list_del(element, *opt, InputOption, next);
+ input_option_free(element);
+ }
+ *opt = NULL;
+}
+
+
+/**
+ * Find the InputOption with the given option name.
+ *
+ * @return The InputOption or NULL if not present.
+ */
+InputOption*
+input_option_find(InputOption *list, const char *key)
+{
+ InputOption *element;
+
+ nt_list_for_each_entry(element, list, next) {
+ if (strcmp(input_option_get_key(element), key) == 0)
+ return element;
+ }
+
+ return NULL;
+}
+
+const char*
+input_option_get_key(const InputOption *opt)
+{
+ return opt->key;
+}
+
+const char*
+input_option_get_value(const InputOption *opt)
+{
+ return opt->value;
+}
+
+void
+input_option_set_key(InputOption *opt, const char *key)
+{
+ free(opt->key);
+ if (key)
+ opt->key = strdup(key);
+}
+
+void
+input_option_set_value(InputOption *opt, const char *value)
+{
+ free(opt->value);
+ if (value)
+ opt->value = strdup(value);
+}