diff options
author | Keith Packard <keithp@keithp.com> | 2012-04-15 21:05:30 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2012-04-15 21:05:30 -0700 |
commit | 80fefc42f5e67e6b4a4b440d8991bee7e5f38359 (patch) | |
tree | a51c4a5e2b9f4e511ef458016fdd5810d8014ccc | |
parent | 9779b904c7c0b49c74054c22c420012c40595cdc (diff) | |
parent | 12188c8a8a537b38b1ca4cf8c0de5447e19c886a (diff) |
Merge remote-tracking branch 'whot/for-keith'
-rw-r--r-- | Xi/exevents.c | 86 | ||||
-rw-r--r-- | Xi/xiquerydevice.c | 2 | ||||
-rw-r--r-- | dix/events.c | 3 | ||||
-rw-r--r-- | dix/getevents.c | 2 | ||||
-rw-r--r-- | hw/xfree86/common/xf86Events.c | 8 | ||||
-rw-r--r-- | hw/xfree86/common/xf86Xinput.h | 3 |
6 files changed, 96 insertions, 8 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index ff2224094..c05c22604 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1111,6 +1111,48 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource) } /** + * Find the oldest touch that still has a pointer emulation client. + * + * Pointer emulation can only be performed for the oldest touch. Otherwise, the + * order of events seen by the client will be wrong. This function helps us find + * the next touch to be emulated. + * + * @param dev The device to find touches for. + */ +static TouchPointInfoPtr +FindOldestPointerEmulatedTouch(DeviceIntPtr dev) +{ + TouchPointInfoPtr oldest = NULL; + int i; + + for (i = 0; i < dev->touch->num_touches; i++) { + TouchPointInfoPtr ti = dev->touch->touches + i; + int j; + + if (!ti->active || !ti->emulate_pointer) + continue; + + for (j = 0; j < ti->num_listeners; j++) { + if (ti->listeners[j].type == LISTENER_POINTER_GRAB || + ti->listeners[j].type == LISTENER_POINTER_REGULAR) + break; + } + if (j == ti->num_listeners) + continue; + + if (!oldest) { + oldest = ti; + continue; + } + + if (oldest->client_id - ti->client_id < UINT_MAX / 2) + oldest = ti; + } + + return oldest; +} + +/** * If the current owner has rejected the event, deliver the * TouchOwnership/TouchBegin to the next item in the sprite stack. */ @@ -1123,8 +1165,16 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, ti->listeners[0].state == LISTENER_EARLY_ACCEPT) DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ti->listeners[0].listener); - else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) + else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) { + /* We can't punt to a pointer listener unless all older pointer + * emulated touches have been seen already. */ + if ((ti->listeners[0].type == LISTENER_POINTER_GRAB || + ti->listeners[0].type == LISTENER_POINTER_REGULAR) && + ti != FindOldestPointerEmulatedTouch(dev)) + return; + TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener); + } /* If we've just removed the last grab and the touch has physically * ended, send a TouchEnd event too and finalise the touch. */ @@ -1139,6 +1189,25 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, } /** + * Check the oldest touch to see if it needs to be replayed to its pointer + * owner. + * + * Touch event propagation is paused if it hits a pointer listener while an + * older touch with a pointer listener is waiting on accept or reject. This + * function will restart propagation of a paused touch if needed. + * + * @param dev The device to check touches for. + */ +static void +CheckOldestTouch(DeviceIntPtr dev) +{ + TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev); + + if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN) + TouchPuntToNextOwner(dev, oldest, NULL); +} + +/** * Process a touch rejection. * * @param sourcedev The source device of the touch sequence. @@ -1169,6 +1238,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource, * finish, then we can just kill it now. */ if (ti->num_listeners == 1 && ti->pending_finish) { TouchEndTouch(sourcedev, ti); + CheckOldestTouch(sourcedev); return; } @@ -1184,6 +1254,8 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource, * the TouchOwnership or TouchBegin event to the new owner. */ if (ev && ti->num_listeners > 0 && was_owner) TouchPuntToNextOwner(sourcedev, ti, ev); + + CheckOldestTouch(sourcedev); } /** @@ -1389,8 +1461,11 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, if (ev->any.type == ET_TouchEnd && !dev->button->buttonsDown && - dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) + dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { (*dev->deviceGrab.DeactivateGrab) (dev); + CheckOldestTouch(dev); + return Success; + } } } else { @@ -1755,6 +1830,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, listener->type == LISTENER_POINTER_GRAB) { rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, xi2mask); + + if (ti->num_listeners > 1) { + ev->any.type = ET_TouchUpdate; + ev->device_event.flags |= TOUCH_PENDING_END; + ti->pending_finish = TRUE; + } + goto out; } diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c index 749bc24c9..15c8b2a7b 100644 --- a/Xi/xiquerydevice.c +++ b/Xi/xiquerydevice.c @@ -430,7 +430,7 @@ ListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch) { touch->type = XITouchClass; touch->length = sizeof(xXITouchInfo) >> 2; - touch->sourceid = touch->sourceid; + touch->sourceid = dev->touch->sourceid; touch->mode = dev->touch->mode; touch->num_touches = dev->touch->num_touches; diff --git a/dix/events.c b/dix/events.c index 447094757..b9f9cfa3c 100644 --- a/dix/events.c +++ b/dix/events.c @@ -5098,8 +5098,7 @@ ProcQueryPointer(ClientPtr client) memset(&rep, 0, sizeof(xQueryPointerReply)); rep.type = X_Reply; rep.sequenceNumber = client->sequence; - rep.mask = mouse->button ? (mouse->button->state) : 0; - rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state); + rep.mask = event_get_corestate(mouse, keyboard); rep.length = 0; rep.root = (GetCurrentRootWindow(mouse))->drawable.id; rep.rootX = pSprite->hot.x; diff --git a/dix/getevents.c b/dix/getevents.c index 3093786c3..23bbe065c 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -848,7 +848,7 @@ scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask, ScreenPtr scr = miPointerGetScreen(dev); double x, y; - BUG_WARN(!dev->valuator || dev->valuator->numAxes < 2); + BUG_WARN(dev->valuator && dev->valuator->numAxes < 2); if (!dev->valuator || dev->valuator->numAxes < 2) { /* if we have no axes, last.valuators must be in screen coords * anyway */ diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c index 058057e92..5896f220c 100644 --- a/hw/xfree86/common/xf86Events.c +++ b/hw/xfree86/common/xf86Events.c @@ -449,6 +449,8 @@ xf86VTSwitch(void) xf86DisableInputHandler(ih); for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) { if (pInfo->dev) { + if (!pInfo->dev->enabled) + pInfo->flags |= XI86_DEVICE_DISABLED; xf86ReleaseKeys(pInfo->dev); ProcessInputEvents(); DisableDevice(pInfo->dev, TRUE); @@ -482,8 +484,9 @@ xf86VTSwitch(void) pInfo = xf86InputDevs; while (pInfo) { - if (pInfo->dev) + if (pInfo->dev && (pInfo->flags & XI86_DEVICE_DISABLED) == 0) EnableDevice(pInfo->dev, TRUE); + pInfo->flags &= ~XI86_DEVICE_DISABLED; pInfo = pInfo->next; } for (ih = InputHandlers; ih; ih = ih->next) @@ -537,8 +540,9 @@ xf86VTSwitch(void) pInfo = xf86InputDevs; while (pInfo) { - if (pInfo->dev) + if (pInfo->dev && (pInfo->flags & XI86_DEVICE_DISABLED) == 0) EnableDevice(pInfo->dev, TRUE); + pInfo->flags &= ~XI86_DEVICE_DISABLED; pInfo = pInfo->next; } diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h index 3731a34d5..1d4363a50 100644 --- a/hw/xfree86/common/xf86Xinput.h +++ b/hw/xfree86/common/xf86Xinput.h @@ -61,6 +61,9 @@ #define XI86_ALWAYS_CORE 0x04 /* device always controls the pointer */ /* the device sends Xinput and core pointer events */ #define XI86_SEND_CORE_EVENTS XI86_ALWAYS_CORE +/* 0x08 is reserved for legacy XI86_SEND_DRAG_EVENTS, do not use for now */ +/* server-internal only */ +#define XI86_DEVICE_DISABLED 0x10 /* device was disabled before vt switch */ /* This holds the input driver entry and module information. */ typedef struct _InputDriverRec { |