diff options
author | Peter Hutterer <peter@cs.unisa.edu.au> | 2008-05-30 15:20:35 +0930 |
---|---|---|
committer | Peter Hutterer <peter@cs.unisa.edu.au> | 2008-05-31 17:42:06 +0930 |
commit | 105d28652d1fb80dd8ce8511e2605dccc8812e99 (patch) | |
tree | dff131287bb580e6a6658efa72811c91d4dc3cab /Xext/xtest.c | |
parent | 341a61b608873c77b1a17fe7d145ed3ad716e5a3 (diff) |
Xext: use GPE/GKE from XTestFakeInput #16145
This commit fixes two problems:
1) XTFI used to assemble the event itself, then passed it to the device. It's
much easier to just pass the variables into GPE/GKE and let the DIX do the
rest.
2) XTFI would pass the VCP/VCK as default device to event processing. As a
result, updating LEDs would be updated on the VCK, not on the actual keyboard.
Instead, we now pass the events through the last-used SD, thus toggling the
LEDs on the last keyboard that sent through this MD.
Also some cleanup in XTFI to merge validity checks a bit closer together
rather than having several different sections.
This breaks XTestFakeMotion with Xinerama though.
X.Org Bug 16145 <http://bugs.freedesktop.org/show_bug.cgi?id=16145>
Diffstat (limited to 'Xext/xtest.c')
-rw-r--r-- | Xext/xtest.c | 310 |
1 files changed, 109 insertions, 201 deletions
diff --git a/Xext/xtest.c b/Xext/xtest.c index 9bd26ba03..ad70aa8e4 100644 --- a/Xext/xtest.c +++ b/Xext/xtest.c @@ -42,6 +42,7 @@ #include "scrnintstr.h" #include "dixevents.h" #include "sleepuntil.h" +#include "mi.h" #define _XTEST_SERVER_ #include <X11/extensions/XTest.h> #include <X11/extensions/xteststr.h> @@ -164,8 +165,13 @@ ProcXTestFakeInput(client) WindowPtr root; Bool extension = FALSE; deviceValuator *dv = NULL; - int base; - int *values; + int valuators[MAX_VALUATORS] = {0}; + int numValuators = 0; + int firstValuator; + EventListPtr events; + int nevents; + int i; + int base = 0; nev = (stuff->length << 2) - sizeof(xReq); if ((nev % sizeof(xEvent)) || !nev) @@ -177,6 +183,18 @@ ProcXTestFakeInput(client) if (type >= EXTENSION_EVENT_BASE) { + extension = TRUE; + + /* check device */ + rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client, + DixWriteAccess); + if (rc != Success) + { + client->errorValue = stuff->deviceid & 0177; + return rc; + } + + /* check type */ type -= DeviceValuator; switch (type) { case XI_DeviceKeyPress: @@ -191,12 +209,31 @@ ProcXTestFakeInput(client) client->errorValue = ev->u.u.type; return BadValue; } + + /* check validity */ if (nev == 1 && type == XI_DeviceMotionNotify) return BadLength; /* DevMotion must be followed by DevValuator */ + if (type == XI_DeviceMotionNotify) - base = ((deviceValuator *)(ev+1))->first_valuator; - else - base = 0; + { + firstValuator = ((deviceValuator *)(ev+1))->first_valuator; + if (firstValuator > dev->valuator->numAxes) + { + client->errorValue = ev->u.u.type; + return BadValue; + } + } else + firstValuator = 0; + + if (nev == 1 && type == XI_DeviceMotionNotify && !dev->valuator) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + + + /* check validity of valuator events */ + base = firstValuator; for (n = 1; n < nev; n++) { dv = (deviceValuator *)(ev + n); @@ -210,17 +247,32 @@ ProcXTestFakeInput(client) client->errorValue = dv->first_valuator; return BadValue; } - if (!dv->num_valuators || dv->num_valuators > 6) + switch(dv->num_valuators) + { + case 6: valuators[base + 5] = dv->valuator5; + case 5: valuators[base + 4] = dv->valuator4; + case 4: valuators[base + 3] = dv->valuator3; + case 3: valuators[base + 2] = dv->valuator2; + case 2: valuators[base + 1] = dv->valuator1; + case 1: valuators[base] = dv->valuator0; + break; + default: + client->errorValue = dv->num_valuators; + return BadValue; + } + + base += dv->num_valuators; + numValuators += dv->num_valuators; + + if (firstValuator + numValuators > dev->valuator->numAxes) { client->errorValue = dv->num_valuators; return BadValue; } - base += dv->num_valuators; } type = type - XI_DeviceKeyPress + KeyPress; - extension = TRUE; - } - else + + } else { if (nev != 1) return BadLength; @@ -228,34 +280,26 @@ ProcXTestFakeInput(client) { case KeyPress: case KeyRelease: - case MotionNotify: + dev = PickKeyboard(client); + break; case ButtonPress: case ButtonRelease: + dev = PickPointer(client); + break; + case MotionNotify: + dev = PickPointer(client); + valuators[0] = ev->u.keyButtonPointer.rootX; + valuators[1] = ev->u.keyButtonPointer.rootY; + numValuators = 2; + firstValuator = 0; break; default: client->errorValue = ev->u.u.type; return BadValue; } - ev->u.u.type += (DeviceValuator - 1); - if (ev->u.u.type == DeviceMotionNotify) - { - /* fake up valuator */ - xEvent *ne = xalloc(2 * sizeof(xEvent)); - if (ne) { - memcpy(ne, ev, sizeof(xEvent)); - memcpy(&ne[1], ev, sizeof(xEvent)); - ev = ne; - - dv = (deviceValuator*)(ne + 1); - dv->type = DeviceValuator; - dv->first_valuator = 0; - dv->num_valuators = 2; - dv->valuator0 = ev->u.keyButtonPointer.rootX; - dv->valuator1 = ev->u.keyButtonPointer.rootY; - nev = 2; - } - } + if (dev->u.lastSlave) + dev = dev->u.lastSlave; } /* If the event has a time set, wait for it to pass */ @@ -288,37 +332,10 @@ ProcXTestFakeInput(client) return Success; } - if (extension) - { - rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client, - DixWriteAccess); - if (rc != Success) - { - client->errorValue = stuff->deviceid & 0177; - return rc; - } - if (nev > 1) - { - dv = (deviceValuator *)(ev + 1); - if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes) - { - client->errorValue = dv->first_valuator; - return BadValue; - } - if (dv->first_valuator + dv->num_valuators > - dev->valuator->numAxes) - { - client->errorValue = dv->num_valuators; - return BadValue; - } - } - } switch (type) { case KeyPress: case KeyRelease: - if (!extension) - dev = PickKeyboard(client); if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode || ev->u.u.detail > dev->key->curKeySyms.maxKeyCode) { @@ -327,66 +344,13 @@ ProcXTestFakeInput(client) } break; case MotionNotify: - if (extension) - { - if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } - /* detail is True for relative coordinates */ - if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute) - { - values = dev->valuator->axisVal + dv->first_valuator; - for (n = 1; n < nev; n++) - { - dv = (deviceValuator *)(ev + n); - switch (dv->num_valuators) - { - case 6: - dv->valuator5 += values[5]; - case 5: - dv->valuator4 += values[4]; - case 4: - dv->valuator3 += values[3]; - case 3: - dv->valuator2 += values[2]; - case 2: - dv->valuator1 += values[1]; - case 1: - dv->valuator0 += values[0]; - } - values += 6; - } - } - - /* For XI events, the actual event is mostly unset. Since we - * want to update the sprite nontheless, we need to fake up - * sane values for the event. */ - - ev->u.keyButtonPointer.root = None; - dv = (deviceValuator*)(ev + 1); - if (dv->num_valuators && dv->first_valuator == 0) - ev->u.keyButtonPointer.rootX = dv->valuator0; - else - ev->u.keyButtonPointer.rootX = 0; - - /* XXX: AFAIK, XI requires always sending _all_ valuators, - * i.e. you can't just send vals 3 - 7. (whot) */ - if (dv->num_valuators > 1 && dv->first_valuator == 0) - ev->u.keyButtonPointer.rootY = dv->valuator1; - else - ev->u.keyButtonPointer.rootY = 0; - } - - if (!dev) - dev = PickPointer(client); - if (ev->u.keyButtonPointer.root == None) + /* broken lib, XI events have root uninitialized */ + if (extension || ev->u.keyButtonPointer.root == None) root = GetCurrentRootWindow(dev); else { - rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client, - DixGetAttrAccess); + rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, + client, DixGetAttrAccess); if (rc != Success) return rc; if (root->parent) @@ -395,91 +359,23 @@ ProcXTestFakeInput(client) return BadValue; } } - if (ev->u.u.detail == xTrue) - { - int x, y; - if (!extension || !dev->valuator->mode == Absolute) - { - /* if Absolute, rootX already has the final coords. */ - GetSpritePosition(dev, &x, &y); - ev->u.keyButtonPointer.rootX += x; - ev->u.keyButtonPointer.rootY += y; - } - } - else if (ev->u.u.detail != xFalse) + if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) { client->errorValue = ev->u.u.detail; return BadValue; } -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - ScreenPtr pScreen = root->drawable.pScreen; - BoxRec box; - int i; - int x = ev->u.keyButtonPointer.rootX + panoramiXdataPtr[0].x; - int y = ev->u.keyButtonPointer.rootY + panoramiXdataPtr[0].y; - if (!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], - x, y, &box)) { - FOR_NSCREENS(i) { - if (i == pScreen->myNum) continue; - if (POINT_IN_REGION(pScreen, - &XineramaScreenRegions[i], - x, y, &box)) { - root = WindowTable[i]; - x -= panoramiXdataPtr[i].x; - y -= panoramiXdataPtr[i].y; - ev->u.keyButtonPointer.rootX = x; - ev->u.keyButtonPointer.rootY = y; - break; - } - } - } - } -#endif + /* FIXME: Xinerama! */ - if (ev->u.keyButtonPointer.rootX < 0) - ev->u.keyButtonPointer.rootX = 0; - else if (ev->u.keyButtonPointer.rootX >= root->drawable.width) - ev->u.keyButtonPointer.rootX = root->drawable.width - 1; - if (ev->u.keyButtonPointer.rootY < 0) - ev->u.keyButtonPointer.rootY = 0; - else if (ev->u.keyButtonPointer.rootY >= root->drawable.height) - ev->u.keyButtonPointer.rootY = root->drawable.height - 1; - -#ifdef PANORAMIX - if ((!noPanoramiXExtension - && root->drawable.pScreen->myNum - != XineramaGetCursorScreen(dev)) - || (noPanoramiXExtension && root != GetCurrentRootWindow(dev))) - -#else - if (root != GetCurrentRootWindow(dev)) -#endif - { - NewCurrentScreen(dev, root->drawable.pScreen, - ev->u.keyButtonPointer.rootX, - ev->u.keyButtonPointer.rootY); - return client->noClientException; - } - /* Only update sprite for MDs and floating SDs */ - if (dev->isMaster || (!dev->isMaster && !dev->u.master)) - { - (*root->drawable.pScreen->SetCursorPosition) - (dev, root->drawable.pScreen, - ev->u.keyButtonPointer.rootX, - ev->u.keyButtonPointer.rootY, FALSE); - } - dev->last.valuators[0] = ev->u.keyButtonPointer.rootX; - dev->last.valuators[1] = ev->u.keyButtonPointer.rootY; break; case ButtonPress: case ButtonRelease: if (!extension) + { dev = PickPointer(client); - - ev->u.keyButtonPointer.rootX = dev->last.valuators[0]; - ev->u.keyButtonPointer.rootY = dev->last.valuators[1]; + if (dev->u.lastSlave) + dev = dev->u.lastSlave; + } if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) { client->errorValue = ev->u.u.detail; @@ -489,19 +385,31 @@ ProcXTestFakeInput(client) } if (screenIsSaved == SCREEN_SAVER_ON) dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); - ev->u.keyButtonPointer.time = currentTime.milliseconds; - - if (!dev->isMaster && dev->u.master) - { /* duplicate and route through master */ - xEvent *master_event = NULL; - CopyGetMasterEvent(dev->u.master, ev, &master_event, nev); - (*dev->public.processInputProc)(ev, dev, nev); - (*dev->public.processInputProc)(master_event, dev->u.master, nev); - xfree(master_event); - } else - (*dev->public.processInputProc)(ev, dev, nev); - if (!extension && type == MotionNotify) - xfree(ev); + + GetEventList(&events); + switch(type) { + case MotionNotify: + nevents = GetPointerEvents(events, dev, type, 0, + (ev->u.u.detail == xFalse) ? POINTER_ABSOLUTE : 0, + firstValuator, numValuators, valuators); + break; + case ButtonPress: + case ButtonRelease: + nevents = GetPointerEvents(events, dev, type, ev->u.u.detail, + POINTER_ABSOLUTE, firstValuator, + numValuators, valuators); + break; + case KeyPress: + case KeyRelease: + nevents = GetKeyboardEvents(events, dev, type, ev->u.u.detail); + break; + } + + OsBlockSignals(); + for (i = 0; i < nevents; i++) + mieqEnqueue(dev, events->event); + OsReleaseSignals(); + return client->noClientException; } |