int ProcXUngrabDeviceButton(ClientPtr client) { DeviceIntPtr dev; DeviceIntPtr mdev; WindowPtr pWin; GrabPtr temporaryGrab; int rc; REQUEST(xUngrabDeviceButtonReq); REQUEST_SIZE_MATCH(xUngrabDeviceButtonReq); rc = dixLookupDevice(&dev, stuff->grabbed_device, client, DixGrabAccess); if (rc != Success) return rc; if (dev->button == NULL) return BadMatch; if (stuff->modifier_device != UseXKeyboard) { rc = dixLookupDevice(&mdev, stuff->modifier_device, client, DixReadAccess); if (rc != Success) return BadDevice; if (mdev->key == NULL) return BadMatch; } else mdev = PickKeyboard(client); rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); if (rc != Success) return rc; if ((stuff->modifiers != AnyModifier) && (stuff->modifiers & ~AllModifiersMask)) return BadValue; temporaryGrab = AllocGrab(); if (!temporaryGrab) return BadAlloc; temporaryGrab->resource = client->clientAsMask; temporaryGrab->device = dev; temporaryGrab->window = pWin; temporaryGrab->type = DeviceButtonPress; temporaryGrab->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; }
int ProcXUngrabDeviceKey(ClientPtr client) { DeviceIntPtr dev; DeviceIntPtr mdev; WindowPtr pWin; GrabRec temporaryGrab; int rc; REQUEST(xUngrabDeviceKeyReq); REQUEST_SIZE_MATCH(xUngrabDeviceKeyReq); rc = dixLookupDevice(&dev, stuff->grabbed_device, client, DixGrabAccess); if (rc != Success) return rc; if (dev->key == NULL) return BadMatch; if (stuff->modifier_device != UseXKeyboard) { rc = dixLookupDevice(&mdev, stuff->modifier_device, client, DixReadAccess); if (rc != Success) return BadDevice; if (mdev->key == NULL) return BadMatch; } else mdev = PickKeyboard(client); rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); if (rc != Success) return rc; if (((stuff->key > dev->key->curKeySyms.maxKeyCode) || (stuff->key < dev->key->curKeySyms.minKeyCode)) && (stuff->key != AnyKey)) return BadValue; if ((stuff->modifiers != AnyModifier) && (stuff->modifiers & ~AllModifiersMask)) return BadValue; temporaryGrab.resource = client->clientAsMask; temporaryGrab.device = dev; temporaryGrab.window = pWin; temporaryGrab.type = DeviceKeyPress; temporaryGrab.modifierDevice = mdev; temporaryGrab.modifiersDetail.exact = stuff->modifiers; temporaryGrab.modifiersDetail.pMask = NULL; temporaryGrab.detail.exact = stuff->key; temporaryGrab.detail.pMask = NULL; DeletePassiveGrabFromList(&temporaryGrab); return Success; }
static int ProcXTestFakeInput(ClientPtr client) { REQUEST(xXTestFakeInputReq); int nev, n, type, rc; xEvent *ev; DeviceIntPtr dev = NULL; WindowPtr root; Bool extension = FALSE; ValuatorMask mask; int valuators[MAX_VALUATORS] = { 0 }; int numValuators = 0; int firstValuator = 0; int nevents = 0; int i; int base = 0; int flags = 0; int need_ptr_update = 1; nev = (stuff->length << 2) - sizeof(xReq); if ((nev % sizeof(xEvent)) || !nev) return BadLength; nev /= sizeof(xEvent); UpdateCurrentTime(); ev = (xEvent *) &((xReq *) stuff)[1]; type = ev->u.u.type & 0177; 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: case XI_DeviceKeyRelease: if (!dev->key) { client->errorValue = ev->u.u.type; return BadValue; } break; case XI_DeviceButtonPress: case XI_DeviceButtonRelease: if (!dev->button) { client->errorValue = ev->u.u.type; return BadValue; } break; case XI_DeviceMotionNotify: if (!dev->valuator) { client->errorValue = ev->u.u.type; return BadValue; } break; case XI_ProximityIn: case XI_ProximityOut: if (!dev->proximity) { client->errorValue = ev->u.u.type; return BadValue; } break; default: 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) { firstValuator = ((deviceValuator *) (ev + 1))->first_valuator; if (firstValuator > dev->valuator->numAxes) { client->errorValue = ev->u.u.type; return BadValue; } if (ev->u.u.detail == xFalse) flags |= POINTER_ABSOLUTE; } else { firstValuator = 0; flags |= POINTER_ABSOLUTE; } if (nev > 1 && !dev->valuator) { client->errorValue = firstValuator; return BadValue; } /* check validity of valuator events */ base = firstValuator; for (n = 1; n < nev; n++) { deviceValuator *dv = (deviceValuator *) (ev + n); if (dv->type != DeviceValuator) { client->errorValue = dv->type; return BadValue; } if (dv->first_valuator != base) { client->errorValue = dv->first_valuator; return BadValue; } 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; } } type = type - XI_DeviceKeyPress + KeyPress; } else { if (nev != 1) return BadLength; switch (type) { case KeyPress: case KeyRelease: 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; if (ev->u.u.detail == xFalse) flags = POINTER_ABSOLUTE | POINTER_DESKTOP; break; default: client->errorValue = ev->u.u.type; return BadValue; } /* Technically the protocol doesn't allow for BadAccess here but * this can only happen when all MDs are disabled. */ if (!dev) return BadAccess; dev = GetXTestDevice(dev); } /* If the event has a time set, wait for it to pass */ if (ev->u.keyButtonPointer.time) { TimeStamp activateTime; CARD32 ms; activateTime = currentTime; ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; if (ms < activateTime.milliseconds) activateTime.months++; activateTime.milliseconds = ms; ev->u.keyButtonPointer.time = 0; /* see mbuf.c:QueueDisplayRequest (from the deprecated Multibuffer * extension) for code similar to this */ if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) { return BadAlloc; } /* swap the request back so we can simply re-execute it */ if (client->swapped) { (void) XTestSwapFakeInput(client, (xReq *) stuff); swaps(&stuff->length); } ResetCurrentRequest(client); client->sequence--; return Success; } switch (type) { case KeyPress: case KeyRelease: if (!dev->key) return BadDevice; if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code || ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code) { client->errorValue = ev->u.u.detail; return BadValue; } need_ptr_update = 0; break; case MotionNotify: if (!dev->valuator) return BadDevice; if (!(extension || ev->u.keyButtonPointer.root == None)) { rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client, DixGetAttrAccess); if (rc != Success) return rc; if (root->parent) { client->errorValue = ev->u.keyButtonPointer.root; return BadValue; } /* Add the root window's offset to the valuators */ if ((flags & POINTER_ABSOLUTE) && firstValuator <= 1 && numValuators > 0) { if (firstValuator == 0) valuators[0] += root->drawable.pScreen->x; if (firstValuator < 2 && firstValuator + numValuators > 1) valuators[1 - firstValuator] += root->drawable.pScreen->y; } } if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) { client->errorValue = ev->u.u.detail; return BadValue; } /* FIXME: Xinerama! */ break; case ButtonPress: case ButtonRelease: if (!dev->button) return BadDevice; if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) { client->errorValue = ev->u.u.detail; return BadValue; } break; } if (screenIsSaved == SCREEN_SAVER_ON) dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); switch (type) { case MotionNotify: valuator_mask_set_range(&mask, firstValuator, numValuators, valuators); nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, &mask); break; case ButtonPress: case ButtonRelease: valuator_mask_set_range(&mask, firstValuator, numValuators, valuators); nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail, flags, &mask); break; case KeyPress: case KeyRelease: nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail); break; } for (i = 0; i < nevents; i++) mieqProcessDeviceEvent(dev, &xtest_evlist[i], miPointerGetScreen(inputInfo.pointer)); if (need_ptr_update) miPointerUpdateSprite(dev); return Success; }