static void send_property_event(DeviceIntPtr dev, Atom property, int what) { devicePropertyNotify event; xXIPropertyEvent xi2; int state; if (what == XIPropertyDeleted) state = PropertyDelete; else state = PropertyNewValue; event.type = DevicePropertyNotify; event.deviceid = dev->id; event.state = state; event.atom = property; event.time = currentTime.milliseconds; SendEventToAllWindows(dev, DevicePropertyNotifyMask, (xEvent *) &event, 1); xi2.type = GenericEvent; xi2.extension = IReqCode; xi2.length = 0; xi2.evtype = XI_PropertyEvent; xi2.deviceid = dev->id; xi2.time = currentTime.milliseconds; xi2.property = property; xi2.what = what; SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent *) &xi2), (xEvent *) &xi2, 1); }
static void do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) { int i; xEvent core_mn; deviceMappingNotify xi_mn; /* The map in ButtonClassRec refers to button numbers, whereas the * protocol is zero-indexed. Sigh. */ memcpy(&(dev->button->map[1]), map, len); core_mn.u.u.type = MappingNotify; core_mn.u.mappingNotify.request = MappingPointer; /* 0 is the server client. */ for (i = 1; i < currentMaxClients; i++) { /* Don't send irrelevant events to naïve clients. */ if (!clients[i] || clients[i]->clientState != ClientStateRunning) continue; if (!XIShouldNotify(clients[i], dev)) continue; core_mn.u.u.sequenceNumber = clients[i]->sequence; WriteEventsToClient(clients[i], 1, &core_mn); } xi_mn.type = DeviceMappingNotify; xi_mn.request = MappingPointer; xi_mn.deviceid = dev->id; xi_mn.time = GetTimeInMillis(); SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1); }
/* * This function sends out two kinds of notification: * - Core mapping notify events sent to clients for whom kbd is the * current core ('picked') keyboard _and_ have not explicitly * selected for XKB mapping notify events; * - Xi mapping events, sent unconditionally to all clients who have * explicitly selected for them (including those who have explicitly * selected for XKB mapping notify events!). */ static void XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed, int first_key, int num_keys) { int i; int keymap_changed = 0; int modmap_changed = 0; CARD32 time = GetTimeInMillis(); if (xkb_event == XkbNewKeyboardNotify) { if (changed & XkbNKN_KeycodesMask) { keymap_changed = 1; modmap_changed = 1; } } else if (xkb_event == XkbMapNotify) { if (changed & XkbKeySymsMask) keymap_changed = 1; if (changed & XkbModifierMapMask) modmap_changed = 1; } if (!keymap_changed && !modmap_changed) return; /* 0 is serverClient. */ for (i = 1; i < currentMaxClients; i++) { if (!clients[i] || clients[i]->clientState != ClientStateRunning) continue; /* XKB allows clients to restrict the MappingNotify events sent to * them. This was broken for three years. Sorry. */ if (xkb_event == XkbMapNotify && (clients[i]->xkbClientFlags & _XkbClientInitialized) && !(clients[i]->mapNotifyMask & changed)) continue; /* Emulate previous server behaviour: any client which has activated * XKB will not receive core events emulated from a NewKeyboardNotify * at all. */ if (xkb_event == XkbNewKeyboardNotify && (clients[i]->xkbClientFlags & _XkbClientInitialized)) continue; /* Don't send core events to clients who don't know about us. */ if (!XIShouldNotify(clients[i], kbd)) continue; if (keymap_changed) { xEvent core_mn; core_mn.u.u.type = MappingNotify; core_mn.u.mappingNotify.request = MappingKeyboard; /* Clip the keycode range to what the client knows about, so it * doesn't freak out. */ if (first_key >= clients[i]->minKC) core_mn.u.mappingNotify.firstKeyCode = first_key; else core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC; if (first_key + num_keys - 1 <= clients[i]->maxKC) core_mn.u.mappingNotify.count = num_keys; else core_mn.u.mappingNotify.count = clients[i]->maxKC - clients[i]->minKC + 1; WriteEventsToClient(clients[i], 1, &core_mn); } if (modmap_changed) { xEvent core_mn; core_mn.u.mappingNotify.request = MappingModifier; core_mn.u.mappingNotify.firstKeyCode = 0; core_mn.u.mappingNotify.count = 0; core_mn.u.u.type = MappingNotify; WriteEventsToClient(clients[i], 1, &core_mn); } } /* Hmm, maybe we can accidentally generate Xi events for core devices * here? Clients might be upset, but that seems better than the * alternative of stale keymaps. -ds */ if (keymap_changed) { deviceMappingNotify xi_mn; xi_mn.type = DeviceMappingNotify; xi_mn.deviceid = kbd->id; xi_mn.request = MappingKeyboard; xi_mn.firstKeyCode = first_key; xi_mn.count = num_keys; xi_mn.time = time; SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1); } if (modmap_changed) { deviceMappingNotify xi_mn; xi_mn.type = DeviceMappingNotify; xi_mn.deviceid = kbd->id; xi_mn.request = MappingModifier; xi_mn.firstKeyCode = 0; xi_mn.count = 0; xi_mn.time = time; SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1); } }
int ProcXChangeDeviceControl(ClientPtr client) { unsigned len; int i, status, ret = BadValue; DeviceIntPtr dev; xDeviceResolutionCtl *r; xChangeDeviceControlReply rep; AxisInfoPtr a; CARD32 *resolution; xDeviceEnableCtl *e; REQUEST(xChangeDeviceControlReq); REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq); len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq)); ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); if (ret != Success) goto out; rep = (xChangeDeviceControlReply) { .repType = X_Reply, .RepType = X_ChangeDeviceControl, .sequenceNumber = client->sequence, .length = 0 }; switch (stuff->control) { case DEVICE_RESOLUTION: r = (xDeviceResolutionCtl *) &stuff[1]; if ((len < bytes_to_int32(sizeof(xDeviceResolutionCtl))) || (len != bytes_to_int32(sizeof(xDeviceResolutionCtl)) + r->num_valuators)) { ret = BadLength; goto out; } if (!dev->valuator) { ret = BadMatch; goto out; } if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) { rep.status = AlreadyGrabbed; ret = Success; goto out; } resolution = (CARD32 *) (r + 1); if (r->first_valuator + r->num_valuators > dev->valuator->numAxes) { ret = BadValue; goto out; } status = ChangeDeviceControl(client, dev, (xDeviceCtl *) r); if (status == Success) { a = &dev->valuator->axes[r->first_valuator]; for (i = 0; i < r->num_valuators; i++) if (*(resolution + i) < (a + i)->min_resolution || *(resolution + i) > (a + i)->max_resolution) return BadValue; for (i = 0; i < r->num_valuators; i++) (a++)->resolution = *resolution++; ret = Success; } else if (status == DeviceBusy) { rep.status = DeviceBusy; ret = Success; } else { ret = BadMatch; } break; case DEVICE_ABS_CALIB: case DEVICE_ABS_AREA: /* Calibration is now done through properties, and never had any effect * on anything (in the open-source world). Thus, be honest. */ ret = BadMatch; break; case DEVICE_CORE: /* Sorry, no device core switching no more. If you want a device to * send core events, attach it to a master device */ ret = BadMatch; break; case DEVICE_ENABLE: e = (xDeviceEnableCtl *) &stuff[1]; status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e); if (status == Success) { if (e->enable) EnableDevice(dev, TRUE); else DisableDevice(dev, TRUE); ret = Success; } else if (status == DeviceBusy) { rep.status = DeviceBusy; ret = Success; } else { ret = BadMatch; } break; default: ret = BadValue; } out: if (ret == Success) { devicePresenceNotify dpn = { .type = DevicePresenceNotify, .time = currentTime.milliseconds, .devchange = DeviceControlChanged, .deviceid = dev->id, .control = stuff->control }; SendEventToAllWindows(dev, DevicePresenceNotifyMask, (xEvent *) &dpn, 1); WriteReplyToClient(client, sizeof(xChangeDeviceControlReply), &rep); } return ret; } /*********************************************************************** * * This procedure writes the reply for the xChangeDeviceControl function, * if the client and server have a different byte ordering. * */ void SRepXChangeDeviceControl(ClientPtr client, int size, xChangeDeviceControlReply * rep) { swaps(&rep->sequenceNumber); swapl(&rep->length); WriteToClient(client, size, rep); }