devices.c revision 91d321ac
1706f2543Smrg/************************************************************ 2706f2543Smrg 3706f2543SmrgCopyright 1987, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included in 12706f2543Smrgall copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20706f2543Smrg 21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 23706f2543Smrgin this Software without prior written authorization from The Open Group. 24706f2543Smrg 25706f2543Smrg 26706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 27706f2543Smrg 28706f2543Smrg All Rights Reserved 29706f2543Smrg 30706f2543SmrgPermission to use, copy, modify, and distribute this software and its 31706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 32706f2543Smrgprovided that the above copyright notice appear in all copies and that 33706f2543Smrgboth that copyright notice and this permission notice appear in 34706f2543Smrgsupporting documentation, and that the name of Digital not be 35706f2543Smrgused in advertising or publicity pertaining to distribution of the 36706f2543Smrgsoftware without specific, written prior permission. 37706f2543Smrg 38706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44706f2543SmrgSOFTWARE. 45706f2543Smrg 46706f2543Smrg********************************************************/ 47706f2543Smrg 48706f2543Smrg 49706f2543Smrg 50706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 51706f2543Smrg#include <dix-config.h> 52706f2543Smrg#endif 53706f2543Smrg 54706f2543Smrg#include <X11/X.h> 55706f2543Smrg#include "misc.h" 56706f2543Smrg#include "resource.h" 57706f2543Smrg#include <X11/Xproto.h> 58706f2543Smrg#include <X11/Xatom.h> 59706f2543Smrg#include "windowstr.h" 60706f2543Smrg#include "inputstr.h" 61706f2543Smrg#include "scrnintstr.h" 62706f2543Smrg#include "cursorstr.h" 63706f2543Smrg#include "dixstruct.h" 64706f2543Smrg#include "ptrveloc.h" 65706f2543Smrg#include "site.h" 66706f2543Smrg#include "xkbsrv.h" 67706f2543Smrg#include "privates.h" 68706f2543Smrg#include "xace.h" 69706f2543Smrg#include "mi.h" 70706f2543Smrg 71706f2543Smrg#include "dispatch.h" 72706f2543Smrg#include "swaprep.h" 73706f2543Smrg#include "dixevents.h" 74706f2543Smrg#include "mipointer.h" 75706f2543Smrg#include "eventstr.h" 76706f2543Smrg 77706f2543Smrg#include <X11/extensions/XI.h> 78706f2543Smrg#include <X11/extensions/XI2.h> 79706f2543Smrg#include <X11/extensions/XIproto.h> 80706f2543Smrg#include <math.h> 81706f2543Smrg#include <pixman.h> 82706f2543Smrg#include "exglobals.h" 83706f2543Smrg#include "exevents.h" 84706f2543Smrg#include "xiquerydevice.h" /* for SizeDeviceClasses */ 85706f2543Smrg#include "xiproperty.h" 86706f2543Smrg#include "enterleave.h" /* for EnterWindow() */ 87706f2543Smrg#include "xserver-properties.h" 88706f2543Smrg#include "xichangehierarchy.h" /* For XISendDeviceHierarchyEvent */ 89706f2543Smrg 90706f2543Smrg/** @file 91706f2543Smrg * This file handles input device-related stuff. 92706f2543Smrg */ 93706f2543Smrg 94706f2543Smrgstatic void RecalculateMasterButtons(DeviceIntPtr slave); 95706f2543Smrg 96706f2543Smrgstatic void 97706f2543SmrgDeviceSetTransform(DeviceIntPtr dev, float *transform) 98706f2543Smrg{ 99706f2543Smrg struct pixman_f_transform scale; 100706f2543Smrg double sx, sy; 101706f2543Smrg int x, y; 102706f2543Smrg 103706f2543Smrg /** 104706f2543Smrg * calculate combined transformation matrix: 105706f2543Smrg * 106706f2543Smrg * M = InvScale * Transform * Scale 107706f2543Smrg * 108706f2543Smrg * So we can later transform points using M * p 109706f2543Smrg * 110706f2543Smrg * Where: 111706f2543Smrg * Scale scales coordinates into 0..1 range 112706f2543Smrg * Transform is the user supplied (affine) transform 113706f2543Smrg * InvScale scales coordinates back up into their native range 114706f2543Smrg */ 115706f2543Smrg sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value; 116706f2543Smrg sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value; 117706f2543Smrg 118706f2543Smrg /* invscale */ 119706f2543Smrg pixman_f_transform_init_scale(&scale, sx, sy); 120706f2543Smrg scale.m[0][2] = dev->valuator->axes[0].min_value; 121706f2543Smrg scale.m[1][2] = dev->valuator->axes[1].min_value; 122706f2543Smrg 123706f2543Smrg /* transform */ 124706f2543Smrg for (y=0; y<3; y++) 125706f2543Smrg for (x=0; x<3; x++) 126706f2543Smrg dev->transform.m[y][x] = *transform++; 127706f2543Smrg 128706f2543Smrg pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform); 129706f2543Smrg 130706f2543Smrg /* scale */ 131706f2543Smrg pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy); 132706f2543Smrg scale.m[0][2] = -dev->valuator->axes[0].min_value / sx; 133706f2543Smrg scale.m[1][2] = -dev->valuator->axes[1].min_value / sy; 134706f2543Smrg 135706f2543Smrg pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale); 136706f2543Smrg} 137706f2543Smrg 138706f2543Smrg/** 139706f2543Smrg * DIX property handler. 140706f2543Smrg */ 141706f2543Smrgstatic int 142706f2543SmrgDeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, 143706f2543Smrg BOOL checkonly) 144706f2543Smrg{ 145706f2543Smrg if (property == XIGetKnownProperty(XI_PROP_ENABLED)) 146706f2543Smrg { 147706f2543Smrg if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1) 148706f2543Smrg return BadValue; 149706f2543Smrg 150706f2543Smrg /* Don't allow disabling of VCP/VCK */ 151706f2543Smrg if ((dev == inputInfo.pointer || dev == inputInfo.keyboard) && 152706f2543Smrg !(*(CARD8*)prop->data)) 153706f2543Smrg return BadAccess; 154706f2543Smrg 155706f2543Smrg if (!checkonly) 156706f2543Smrg { 157706f2543Smrg if ((*((CARD8*)prop->data)) && !dev->enabled) 158706f2543Smrg EnableDevice(dev, TRUE); 159706f2543Smrg else if (!(*((CARD8*)prop->data)) && dev->enabled) 160706f2543Smrg DisableDevice(dev, TRUE); 161706f2543Smrg } 162706f2543Smrg } else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM)) 163706f2543Smrg { 164706f2543Smrg float *f = (float*)prop->data; 165706f2543Smrg int i; 166706f2543Smrg 167706f2543Smrg if (prop->format != 32 || prop->size != 9 || 168706f2543Smrg prop->type != XIGetKnownProperty(XATOM_FLOAT)) 169706f2543Smrg return BadValue; 170706f2543Smrg 171706f2543Smrg for (i=0; i<9; i++) 172706f2543Smrg if (!isfinite(f[i])) 173706f2543Smrg return BadValue; 174706f2543Smrg 175706f2543Smrg if (!checkonly) 176706f2543Smrg DeviceSetTransform(dev, f); 177706f2543Smrg } 178706f2543Smrg 179706f2543Smrg return Success; 180706f2543Smrg} 181706f2543Smrg 182706f2543Smrg/* Pair the keyboard to the pointer device. Keyboard events will follow the 183706f2543Smrg * pointer sprite. Only applicable for master devices. 184706f2543Smrg * If the client is set, the request to pair comes from some client. In this 185706f2543Smrg * case, we need to check for access. If the client is NULL, it's from an 186706f2543Smrg * internal automatic pairing, we must always permit this. 187706f2543Smrg */ 188706f2543Smrgstatic int 189706f2543SmrgPairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd) 190706f2543Smrg{ 191706f2543Smrg if (!ptr) 192706f2543Smrg return BadDevice; 193706f2543Smrg 194706f2543Smrg /* Don't allow pairing for slave devices */ 195706f2543Smrg if (!IsMaster(ptr) || !IsMaster(kbd)) 196706f2543Smrg return BadDevice; 197706f2543Smrg 198706f2543Smrg if (ptr->spriteInfo->paired) 199706f2543Smrg return BadDevice; 200706f2543Smrg 201706f2543Smrg if (kbd->spriteInfo->spriteOwner) 202706f2543Smrg { 203706f2543Smrg free(kbd->spriteInfo->sprite); 204706f2543Smrg kbd->spriteInfo->sprite = NULL; 205706f2543Smrg kbd->spriteInfo->spriteOwner = FALSE; 206706f2543Smrg } 207706f2543Smrg 208706f2543Smrg kbd->spriteInfo->sprite = ptr->spriteInfo->sprite; 209706f2543Smrg kbd->spriteInfo->paired = ptr; 210706f2543Smrg ptr->spriteInfo->paired = kbd; 211706f2543Smrg return Success; 212706f2543Smrg} 213706f2543Smrg 214706f2543Smrg 215706f2543Smrg/** 216706f2543Smrg * Find and return the next unpaired MD pointer device. 217706f2543Smrg */ 218706f2543Smrgstatic DeviceIntPtr 219706f2543SmrgNextFreePointerDevice(void) 220706f2543Smrg{ 221706f2543Smrg DeviceIntPtr dev; 222706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) 223706f2543Smrg if (IsMaster(dev) && 224706f2543Smrg dev->spriteInfo->spriteOwner && 225706f2543Smrg !dev->spriteInfo->paired) 226706f2543Smrg return dev; 227706f2543Smrg return NULL; 228706f2543Smrg} 229706f2543Smrg 230706f2543Smrg/** 231706f2543Smrg * Create a new input device and init it to sane values. The device is added 232706f2543Smrg * to the server's off_devices list. 233706f2543Smrg * 234706f2543Smrg * @param deviceProc Callback for device control function (switch dev on/off). 235706f2543Smrg * @return The newly created device. 236706f2543Smrg */ 237706f2543SmrgDeviceIntPtr 238706f2543SmrgAddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) 239706f2543Smrg{ 240706f2543Smrg DeviceIntPtr dev, *prev; /* not a typo */ 241706f2543Smrg DeviceIntPtr devtmp; 242706f2543Smrg int devid; 243706f2543Smrg char devind[MAXDEVICES]; 244706f2543Smrg BOOL enabled; 245706f2543Smrg float transform[9]; 246706f2543Smrg 247706f2543Smrg /* Find next available id, 0 and 1 are reserved */ 248706f2543Smrg memset(devind, 0, sizeof(char)*MAXDEVICES); 249706f2543Smrg for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next) 250706f2543Smrg devind[devtmp->id]++; 251706f2543Smrg for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next) 252706f2543Smrg devind[devtmp->id]++; 253706f2543Smrg for (devid = 2; devid < MAXDEVICES && devind[devid]; devid++) 254706f2543Smrg ; 255706f2543Smrg 256706f2543Smrg if (devid >= MAXDEVICES) 257706f2543Smrg return (DeviceIntPtr)NULL; 258706f2543Smrg dev = _dixAllocateObjectWithPrivates(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), 259706f2543Smrg sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), 260706f2543Smrg offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE); 261706f2543Smrg if (!dev) 262706f2543Smrg return (DeviceIntPtr)NULL; 263706f2543Smrg dev->id = devid; 264706f2543Smrg dev->public.processInputProc = ProcessOtherEvent; 265706f2543Smrg dev->public.realInputProc = ProcessOtherEvent; 266706f2543Smrg dev->public.enqueueInputProc = EnqueueEvent; 267706f2543Smrg dev->deviceProc = deviceProc; 268706f2543Smrg dev->startup = autoStart; 269706f2543Smrg 270706f2543Smrg /* device grab defaults */ 271706f2543Smrg dev->deviceGrab.grabTime = currentTime; 272706f2543Smrg dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; 273706f2543Smrg dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; 274706f2543Smrg 275706f2543Smrg XkbSetExtension(dev, ProcessKeyboardEvent); 276706f2543Smrg 277706f2543Smrg dev->coreEvents = TRUE; 278706f2543Smrg 279706f2543Smrg /* sprite defaults */ 280706f2543Smrg dev->spriteInfo = (SpriteInfoPtr)&dev[1]; 281706f2543Smrg 282706f2543Smrg /* security creation/labeling check 283706f2543Smrg */ 284706f2543Smrg if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) { 285706f2543Smrg free(dev); 286706f2543Smrg return NULL; 287706f2543Smrg } 288706f2543Smrg 289706f2543Smrg inputInfo.numDevices++; 290706f2543Smrg 291706f2543Smrg for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next) 292706f2543Smrg ; 293706f2543Smrg *prev = dev; 294706f2543Smrg dev->next = NULL; 295706f2543Smrg 296706f2543Smrg enabled = FALSE; 297706f2543Smrg XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), 298706f2543Smrg XA_INTEGER, 8, PropModeReplace, 1, &enabled, 299706f2543Smrg FALSE); 300706f2543Smrg XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE); 301706f2543Smrg 302706f2543Smrg /* unity matrix */ 303706f2543Smrg memset(transform, 0, sizeof(transform)); 304706f2543Smrg transform[0] = transform[4] = transform[8] = 1.0f; 305706f2543Smrg 306706f2543Smrg XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), 307706f2543Smrg XIGetKnownProperty(XATOM_FLOAT), 32, 308706f2543Smrg PropModeReplace, 9, transform, FALSE); 309706f2543Smrg XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), 310706f2543Smrg FALSE); 311706f2543Smrg 312706f2543Smrg XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL); 313706f2543Smrg 314706f2543Smrg return dev; 315706f2543Smrg} 316706f2543Smrg 317706f2543Smrgvoid 318706f2543SmrgSendDevicePresenceEvent(int deviceid, int type) 319706f2543Smrg{ 320706f2543Smrg DeviceIntRec dummyDev; 321706f2543Smrg devicePresenceNotify ev; 322706f2543Smrg 323706f2543Smrg memset(&dummyDev, 0, sizeof(DeviceIntRec)); 324706f2543Smrg ev.type = DevicePresenceNotify; 325706f2543Smrg ev.time = currentTime.milliseconds; 326706f2543Smrg ev.devchange = type; 327706f2543Smrg ev.deviceid = deviceid; 328706f2543Smrg dummyDev.id = XIAllDevices; 329706f2543Smrg SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, 330706f2543Smrg (xEvent*)&ev, 1); 331706f2543Smrg} 332706f2543Smrg 333706f2543Smrg/** 334706f2543Smrg * Enable the device through the driver, add the device to the device list. 335706f2543Smrg * Switch device ON through the driver and push it onto the global device 336706f2543Smrg * list. Initialize the DIX sprite or pair the device. All clients are 337706f2543Smrg * notified about the device being enabled. 338706f2543Smrg * 339706f2543Smrg * A master pointer device needs to be enabled before a master keyboard 340706f2543Smrg * device. 341706f2543Smrg * 342706f2543Smrg * @param The device to be enabled. 343706f2543Smrg * @param sendevent True if an XI2 event should be sent. 344706f2543Smrg * @return TRUE on success or FALSE otherwise. 345706f2543Smrg */ 346706f2543SmrgBool 347706f2543SmrgEnableDevice(DeviceIntPtr dev, BOOL sendevent) 348706f2543Smrg{ 349706f2543Smrg DeviceIntPtr *prev; 350706f2543Smrg int ret; 351706f2543Smrg DeviceIntPtr other; 352706f2543Smrg BOOL enabled; 353706f2543Smrg int flags[MAXDEVICES] = {0}; 354706f2543Smrg 355706f2543Smrg for (prev = &inputInfo.off_devices; 356706f2543Smrg *prev && (*prev != dev); 357706f2543Smrg prev = &(*prev)->next) 358706f2543Smrg ; 359706f2543Smrg 360706f2543Smrg if (!dev->spriteInfo->sprite) 361706f2543Smrg { 362706f2543Smrg if (IsMaster(dev)) 363706f2543Smrg { 364706f2543Smrg /* Sprites appear on first root window, so we can hardcode it */ 365706f2543Smrg if (dev->spriteInfo->spriteOwner) 366706f2543Smrg { 367706f2543Smrg InitializeSprite(dev, screenInfo.screens[0]->root); 368706f2543Smrg /* mode doesn't matter */ 369706f2543Smrg EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor); 370706f2543Smrg } 371706f2543Smrg else if ((other = NextFreePointerDevice()) == NULL) 372706f2543Smrg { 373706f2543Smrg ErrorF("[dix] cannot find pointer to pair with. " 374706f2543Smrg "This is a bug.\n"); 375706f2543Smrg return FALSE; 376706f2543Smrg } else 377706f2543Smrg PairDevices(NULL, other, dev); 378706f2543Smrg } else 379706f2543Smrg { 380706f2543Smrg if (dev->coreEvents) 381706f2543Smrg other = (IsPointerDevice(dev)) ? inputInfo.pointer : 382706f2543Smrg inputInfo.keyboard; 383706f2543Smrg else 384706f2543Smrg other = NULL; /* auto-float non-core devices */ 385706f2543Smrg AttachDevice(NULL, dev, other); 386706f2543Smrg } 387706f2543Smrg } 388706f2543Smrg 389706f2543Smrg if ((*prev != dev) || !dev->inited || 390706f2543Smrg ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) { 391706f2543Smrg ErrorF("[dix] couldn't enable device %d\n", dev->id); 392706f2543Smrg return FALSE; 393706f2543Smrg } 394706f2543Smrg dev->enabled = TRUE; 395706f2543Smrg *prev = dev->next; 396706f2543Smrg 397706f2543Smrg for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next) 398706f2543Smrg ; 399706f2543Smrg *prev = dev; 400706f2543Smrg dev->next = NULL; 401706f2543Smrg 402706f2543Smrg enabled = TRUE; 403706f2543Smrg XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), 404706f2543Smrg XA_INTEGER, 8, PropModeReplace, 1, &enabled, 405706f2543Smrg TRUE); 406706f2543Smrg 407706f2543Smrg SendDevicePresenceEvent(dev->id, DeviceEnabled); 408706f2543Smrg if (sendevent) 409706f2543Smrg { 410706f2543Smrg flags[dev->id] |= XIDeviceEnabled; 411706f2543Smrg XISendDeviceHierarchyEvent(flags); 412706f2543Smrg } 413706f2543Smrg 414706f2543Smrg RecalculateMasterButtons(dev); 415706f2543Smrg 416706f2543Smrg return TRUE; 417706f2543Smrg} 418706f2543Smrg 419706f2543Smrg/** 420706f2543Smrg * Switch a device off through the driver and push it onto the off_devices 421706f2543Smrg * list. A device will not send events while disabled. All clients are 422706f2543Smrg * notified about the device being disabled. 423706f2543Smrg * 424706f2543Smrg * Master keyboard devices have to be disabled before master pointer devices 425706f2543Smrg * otherwise things turn bad. 426706f2543Smrg * 427706f2543Smrg * @param sendevent True if an XI2 event should be sent. 428706f2543Smrg * @return TRUE on success or FALSE otherwise. 429706f2543Smrg */ 430706f2543SmrgBool 431706f2543SmrgDisableDevice(DeviceIntPtr dev, BOOL sendevent) 432706f2543Smrg{ 433706f2543Smrg DeviceIntPtr *prev, other; 434706f2543Smrg BOOL enabled; 43591d321acSmrg BOOL dev_in_devices_list = FALSE; 436706f2543Smrg int flags[MAXDEVICES] = {0}; 437706f2543Smrg 43891d321acSmrg for (other = inputInfo.devices; other; other = other->next) { 43991d321acSmrg if (other == dev) { 44091d321acSmrg dev_in_devices_list = TRUE; 44191d321acSmrg break; 44291d321acSmrg } 44391d321acSmrg } 44491d321acSmrg 44591d321acSmrg if (!dev_in_devices_list) 446706f2543Smrg return FALSE; 447706f2543Smrg 448706f2543Smrg /* float attached devices */ 449706f2543Smrg if (IsMaster(dev)) 450706f2543Smrg { 451706f2543Smrg for (other = inputInfo.devices; other; other = other->next) 452706f2543Smrg { 453706f2543Smrg if (other->u.master == dev) 454706f2543Smrg { 455706f2543Smrg AttachDevice(NULL, other, NULL); 456706f2543Smrg flags[other->id] |= XISlaveDetached; 457706f2543Smrg } 458706f2543Smrg } 459706f2543Smrg } 460706f2543Smrg else 461706f2543Smrg { 462706f2543Smrg for (other = inputInfo.devices; other; other = other->next) 463706f2543Smrg { 464706f2543Smrg if (IsMaster(other) && other->u.lastSlave == dev) 465706f2543Smrg other->u.lastSlave = NULL; 466706f2543Smrg } 467706f2543Smrg } 468706f2543Smrg 469706f2543Smrg if (IsMaster(dev) && dev->spriteInfo->sprite) 470706f2543Smrg { 471706f2543Smrg for (other = inputInfo.devices; other; other = other->next) 472706f2543Smrg { 473706f2543Smrg if (other->spriteInfo->paired == dev) 474706f2543Smrg { 475706f2543Smrg ErrorF("[dix] cannot disable device, still paired. " 476706f2543Smrg "This is a bug. \n"); 477706f2543Smrg return FALSE; 478706f2543Smrg } 479706f2543Smrg } 480706f2543Smrg } 481706f2543Smrg 482706f2543Smrg (void)(*dev->deviceProc)(dev, DEVICE_OFF); 483706f2543Smrg dev->enabled = FALSE; 484706f2543Smrg 485706f2543Smrg /* now that the device is disabled, we can reset the signal handler's 486706f2543Smrg * last.slave */ 487706f2543Smrg OsBlockSignals(); 488706f2543Smrg for (other = inputInfo.devices; other; other = other->next) 489706f2543Smrg { 490706f2543Smrg if (other->last.slave == dev) 491706f2543Smrg other->last.slave = NULL; 492706f2543Smrg } 493706f2543Smrg OsReleaseSignals(); 494706f2543Smrg 495706f2543Smrg LeaveWindow(dev); 496706f2543Smrg SetFocusOut(dev); 497706f2543Smrg 49891d321acSmrg for (prev = &inputInfo.devices; 49991d321acSmrg *prev && (*prev != dev); prev = &(*prev)->next); 50091d321acSmrg 501706f2543Smrg *prev = dev->next; 502706f2543Smrg dev->next = inputInfo.off_devices; 503706f2543Smrg inputInfo.off_devices = dev; 504706f2543Smrg 505706f2543Smrg enabled = FALSE; 506706f2543Smrg XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), 507706f2543Smrg XA_INTEGER, 8, PropModeReplace, 1, &enabled, 508706f2543Smrg TRUE); 509706f2543Smrg 510706f2543Smrg SendDevicePresenceEvent(dev->id, DeviceDisabled); 511706f2543Smrg if (sendevent) 512706f2543Smrg { 513706f2543Smrg flags[dev->id] = XIDeviceDisabled; 514706f2543Smrg XISendDeviceHierarchyEvent(flags); 515706f2543Smrg } 516706f2543Smrg 517706f2543Smrg RecalculateMasterButtons(dev); 518706f2543Smrg 519706f2543Smrg return TRUE; 520706f2543Smrg} 521706f2543Smrg 522706f2543Smrg/** 523706f2543Smrg * Initialise a new device through the driver and tell all clients about the 524706f2543Smrg * new device. 525706f2543Smrg * 526706f2543Smrg * Must be called before EnableDevice. 527706f2543Smrg * The device will NOT send events until it is enabled! 528706f2543Smrg * 529706f2543Smrg * @param sendevent True if an XI2 event should be sent. 530706f2543Smrg * @return Success or an error code on failure. 531706f2543Smrg */ 532706f2543Smrgint 533706f2543SmrgActivateDevice(DeviceIntPtr dev, BOOL sendevent) 534706f2543Smrg{ 535706f2543Smrg int ret = Success; 536706f2543Smrg ScreenPtr pScreen = screenInfo.screens[0]; 537706f2543Smrg 538706f2543Smrg if (!dev || !dev->deviceProc) 539706f2543Smrg return BadImplementation; 540706f2543Smrg 541706f2543Smrg ret = (*dev->deviceProc) (dev, DEVICE_INIT); 542706f2543Smrg dev->inited = (ret == Success); 543706f2543Smrg if (!dev->inited) 544706f2543Smrg return ret; 545706f2543Smrg 546706f2543Smrg /* Initialize memory for sprites. */ 547706f2543Smrg if (IsMaster(dev) && dev->spriteInfo->spriteOwner) 548706f2543Smrg if (!pScreen->DeviceCursorInitialize(dev, pScreen)) 549706f2543Smrg ret = BadAlloc; 550706f2543Smrg 551706f2543Smrg SendDevicePresenceEvent(dev->id, DeviceAdded); 552706f2543Smrg if (sendevent) 553706f2543Smrg { 554706f2543Smrg int flags[MAXDEVICES] = {0}; 555706f2543Smrg flags[dev->id] = XISlaveAdded; 556706f2543Smrg XISendDeviceHierarchyEvent(flags); 557706f2543Smrg } 558706f2543Smrg return ret; 559706f2543Smrg} 560706f2543Smrg 561706f2543Smrg/** 562706f2543Smrg * Ring the bell. 563706f2543Smrg * The actual task of ringing the bell is the job of the DDX. 564706f2543Smrg */ 565706f2543Smrgstatic void 566706f2543SmrgCoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something) 567706f2543Smrg{ 568706f2543Smrg KeybdCtrl *ctrl = arg; 569706f2543Smrg 570706f2543Smrg DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration); 571706f2543Smrg} 572706f2543Smrg 573706f2543Smrgstatic void 574706f2543SmrgCoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl) 575706f2543Smrg{ 576706f2543Smrg return; 577706f2543Smrg} 578706f2543Smrg 579706f2543Smrg/** 580706f2543Smrg * Device control function for the Virtual Core Keyboard. 581706f2543Smrg */ 582706f2543Smrgint 583706f2543SmrgCoreKeyboardProc(DeviceIntPtr pDev, int what) 584706f2543Smrg{ 585706f2543Smrg 586706f2543Smrg switch (what) { 587706f2543Smrg case DEVICE_INIT: 588706f2543Smrg if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell, 589706f2543Smrg CoreKeyboardCtl)) 590706f2543Smrg { 591706f2543Smrg ErrorF("Keyboard initialization failed. This could be a missing " 592706f2543Smrg "or incorrect setup of xkeyboard-config.\n"); 593706f2543Smrg return BadValue; 594706f2543Smrg } 595706f2543Smrg return Success; 596706f2543Smrg 597706f2543Smrg case DEVICE_ON: 598706f2543Smrg case DEVICE_OFF: 599706f2543Smrg return Success; 600706f2543Smrg 601706f2543Smrg case DEVICE_CLOSE: 602706f2543Smrg return Success; 603706f2543Smrg } 604706f2543Smrg 605706f2543Smrg return BadMatch; 606706f2543Smrg} 607706f2543Smrg 608706f2543Smrg/** 609706f2543Smrg * Device control function for the Virtual Core Pointer. 610706f2543Smrg */ 611706f2543Smrgint 612706f2543SmrgCorePointerProc(DeviceIntPtr pDev, int what) 613706f2543Smrg{ 614706f2543Smrg#define NBUTTONS 10 615706f2543Smrg#define NAXES 2 616706f2543Smrg BYTE map[NBUTTONS + 1]; 617706f2543Smrg int i = 0; 618706f2543Smrg Atom btn_labels[NBUTTONS] = {0}; 619706f2543Smrg Atom axes_labels[NAXES] = {0}; 620706f2543Smrg 621706f2543Smrg switch (what) { 622706f2543Smrg case DEVICE_INIT: 623706f2543Smrg for (i = 1; i <= NBUTTONS; i++) 624706f2543Smrg map[i] = i; 625706f2543Smrg 626706f2543Smrg btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 627706f2543Smrg btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 628706f2543Smrg btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 629706f2543Smrg btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 630706f2543Smrg btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 631706f2543Smrg btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 632706f2543Smrg btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 633706f2543Smrg /* don't know about the rest */ 634706f2543Smrg 635706f2543Smrg axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 636706f2543Smrg axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 637706f2543Smrg 638706f2543Smrg if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels, 639706f2543Smrg (PtrCtrlProcPtr)NoopDDA, 640706f2543Smrg GetMotionHistorySize(), NAXES, axes_labels)) 641706f2543Smrg { 642706f2543Smrg ErrorF("Could not initialize device '%s'. Out of memory.\n", 643706f2543Smrg pDev->name); 644706f2543Smrg return BadAlloc; /* IPDS only fails on allocs */ 645706f2543Smrg } 646706f2543Smrg pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 647706f2543Smrg pDev->last.valuators[0] = pDev->valuator->axisVal[0]; 648706f2543Smrg pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 649706f2543Smrg pDev->last.valuators[1] = pDev->valuator->axisVal[1]; 650706f2543Smrg break; 651706f2543Smrg 652706f2543Smrg case DEVICE_CLOSE: 653706f2543Smrg break; 654706f2543Smrg 655706f2543Smrg default: 656706f2543Smrg break; 657706f2543Smrg } 658706f2543Smrg 659706f2543Smrg return Success; 660706f2543Smrg 661706f2543Smrg#undef NBUTTONS 662706f2543Smrg#undef NAXES 663706f2543Smrg} 664706f2543Smrg 665706f2543Smrg/** 666706f2543Smrg * Initialise the two core devices, VCP and VCK (see events.c). 667706f2543Smrg * Both devices are not tied to physical devices, but guarantee that there is 668706f2543Smrg * always a keyboard and a pointer present and keep the protocol semantics. 669706f2543Smrg * 670706f2543Smrg * Note that the server MUST have two core devices at all times, even if there 671706f2543Smrg * is no physical device connected. 672706f2543Smrg */ 673706f2543Smrgvoid 674706f2543SmrgInitCoreDevices(void) 675706f2543Smrg{ 676706f2543Smrg if (AllocDevicePair(serverClient, "Virtual core", 677706f2543Smrg &inputInfo.pointer, &inputInfo.keyboard, 678706f2543Smrg CorePointerProc, CoreKeyboardProc, 679706f2543Smrg TRUE) != Success) 680706f2543Smrg FatalError("Failed to allocate core devices"); 681706f2543Smrg 682706f2543Smrg if (ActivateDevice(inputInfo.pointer, TRUE) != Success || 683706f2543Smrg ActivateDevice(inputInfo.keyboard, TRUE) != Success) 684706f2543Smrg FatalError("Failed to activate core devices."); 685706f2543Smrg if (!EnableDevice(inputInfo.pointer, TRUE) || 686706f2543Smrg !EnableDevice(inputInfo.keyboard, TRUE)) 687706f2543Smrg FatalError("Failed to enable core devices."); 688706f2543Smrg 689706f2543Smrg InitXTestDevices(); 690706f2543Smrg} 691706f2543Smrg 692706f2543Smrg/** 693706f2543Smrg * Activate all switched-off devices and then enable all those devices. 694706f2543Smrg * 695706f2543Smrg * Will return an error if no core keyboard or core pointer is present. 696706f2543Smrg * In theory this should never happen if you call InitCoreDevices() first. 697706f2543Smrg * 698706f2543Smrg * InitAndStartDevices needs to be called AFTER the windows are initialized. 699706f2543Smrg * Devices will start sending events after InitAndStartDevices() has 700706f2543Smrg * completed. 701706f2543Smrg * 702706f2543Smrg * @return Success or error code on failure. 703706f2543Smrg */ 704706f2543Smrgint 705706f2543SmrgInitAndStartDevices(void) 706706f2543Smrg{ 707706f2543Smrg DeviceIntPtr dev, next; 708706f2543Smrg 709706f2543Smrg for (dev = inputInfo.off_devices; dev; dev = dev->next) { 710706f2543Smrg DebugF("(dix) initialising device %d\n", dev->id); 711706f2543Smrg if (!dev->inited) 712706f2543Smrg ActivateDevice(dev, TRUE); 713706f2543Smrg } 714706f2543Smrg 715706f2543Smrg /* enable real devices */ 716706f2543Smrg for (dev = inputInfo.off_devices; dev; dev = next) 717706f2543Smrg { 718706f2543Smrg DebugF("(dix) enabling device %d\n", dev->id); 719706f2543Smrg next = dev->next; 720706f2543Smrg if (dev->inited && dev->startup) 721706f2543Smrg EnableDevice(dev, TRUE); 722706f2543Smrg } 723706f2543Smrg 724706f2543Smrg return Success; 725706f2543Smrg} 726706f2543Smrg 727706f2543Smrg/** 728706f2543Smrg * Free the given device class and reset the pointer to NULL. 729706f2543Smrg */ 730706f2543Smrgstatic void 731706f2543SmrgFreeDeviceClass(int type, pointer *class) 732706f2543Smrg{ 733706f2543Smrg if (!(*class)) 734706f2543Smrg return; 735706f2543Smrg 736706f2543Smrg switch(type) 737706f2543Smrg { 738706f2543Smrg case KeyClass: 739706f2543Smrg { 740706f2543Smrg KeyClassPtr* k = (KeyClassPtr*)class; 741706f2543Smrg if ((*k)->xkbInfo) 742706f2543Smrg { 743706f2543Smrg XkbFreeInfo((*k)->xkbInfo); 744706f2543Smrg (*k)->xkbInfo = NULL; 745706f2543Smrg } 746706f2543Smrg free((*k)); 747706f2543Smrg break; 748706f2543Smrg } 749706f2543Smrg case ButtonClass: 750706f2543Smrg { 751706f2543Smrg ButtonClassPtr *b = (ButtonClassPtr*)class; 752706f2543Smrg free((*b)->xkb_acts); 753706f2543Smrg free((*b)); 754706f2543Smrg break; 755706f2543Smrg } 756706f2543Smrg case ValuatorClass: 757706f2543Smrg { 758706f2543Smrg ValuatorClassPtr *v = (ValuatorClassPtr*)class; 759706f2543Smrg 760706f2543Smrg free((*v)->motion); 761706f2543Smrg free((*v)); 762706f2543Smrg break; 763706f2543Smrg } 764706f2543Smrg case FocusClass: 765706f2543Smrg { 766706f2543Smrg FocusClassPtr *f = (FocusClassPtr*)class; 767706f2543Smrg free((*f)->trace); 768706f2543Smrg free((*f)); 769706f2543Smrg break; 770706f2543Smrg } 771706f2543Smrg case ProximityClass: 772706f2543Smrg { 773706f2543Smrg ProximityClassPtr *p = (ProximityClassPtr*)class; 774706f2543Smrg free((*p)); 775706f2543Smrg break; 776706f2543Smrg } 777706f2543Smrg } 778706f2543Smrg *class = NULL; 779706f2543Smrg} 780706f2543Smrg 781706f2543Smrgstatic void 782706f2543SmrgFreeFeedbackClass(int type, pointer *class) 783706f2543Smrg{ 784706f2543Smrg if (!(*class)) 785706f2543Smrg return; 786706f2543Smrg 787706f2543Smrg switch(type) 788706f2543Smrg { 789706f2543Smrg case KbdFeedbackClass: 790706f2543Smrg { 791706f2543Smrg KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class; 792706f2543Smrg KbdFeedbackPtr k, knext; 793706f2543Smrg for (k = (*kbdfeed); k; k = knext) { 794706f2543Smrg knext = k->next; 795706f2543Smrg if (k->xkb_sli) 796706f2543Smrg XkbFreeSrvLedInfo(k->xkb_sli); 797706f2543Smrg free(k); 798706f2543Smrg } 799706f2543Smrg break; 800706f2543Smrg } 801706f2543Smrg case PtrFeedbackClass: 802706f2543Smrg { 803706f2543Smrg PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class; 804706f2543Smrg PtrFeedbackPtr p, pnext; 805706f2543Smrg 806706f2543Smrg for (p = (*ptrfeed); p; p = pnext) { 807706f2543Smrg pnext = p->next; 808706f2543Smrg free(p); 809706f2543Smrg } 810706f2543Smrg break; 811706f2543Smrg } 812706f2543Smrg case IntegerFeedbackClass: 813706f2543Smrg { 814706f2543Smrg IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class; 815706f2543Smrg IntegerFeedbackPtr i, inext; 816706f2543Smrg 817706f2543Smrg for (i = (*intfeed); i; i = inext) { 818706f2543Smrg inext = i->next; 819706f2543Smrg free(i); 820706f2543Smrg } 821706f2543Smrg break; 822706f2543Smrg } 823706f2543Smrg case StringFeedbackClass: 824706f2543Smrg { 825706f2543Smrg StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class; 826706f2543Smrg StringFeedbackPtr s, snext; 827706f2543Smrg 828706f2543Smrg for (s = (*stringfeed); s; s = snext) { 829706f2543Smrg snext = s->next; 830706f2543Smrg free(s->ctrl.symbols_supported); 831706f2543Smrg free(s->ctrl.symbols_displayed); 832706f2543Smrg free(s); 833706f2543Smrg } 834706f2543Smrg break; 835706f2543Smrg } 836706f2543Smrg case BellFeedbackClass: 837706f2543Smrg { 838706f2543Smrg BellFeedbackPtr *bell = (BellFeedbackPtr*)class; 839706f2543Smrg BellFeedbackPtr b, bnext; 840706f2543Smrg 841706f2543Smrg for (b = (*bell); b; b = bnext) { 842706f2543Smrg bnext = b->next; 843706f2543Smrg free(b); 844706f2543Smrg } 845706f2543Smrg break; 846706f2543Smrg } 847706f2543Smrg case LedFeedbackClass: 848706f2543Smrg { 849706f2543Smrg LedFeedbackPtr *leds = (LedFeedbackPtr*)class; 850706f2543Smrg LedFeedbackPtr l, lnext; 851706f2543Smrg 852706f2543Smrg for (l = (*leds); l; l = lnext) { 853706f2543Smrg lnext = l->next; 854706f2543Smrg if (l->xkb_sli) 855706f2543Smrg XkbFreeSrvLedInfo(l->xkb_sli); 856706f2543Smrg free(l); 857706f2543Smrg } 858706f2543Smrg break; 859706f2543Smrg } 860706f2543Smrg } 861706f2543Smrg *class = NULL; 862706f2543Smrg} 863706f2543Smrg 864706f2543Smrgstatic void 865706f2543SmrgFreeAllDeviceClasses(ClassesPtr classes) 866706f2543Smrg{ 867706f2543Smrg if (!classes) 868706f2543Smrg return; 869706f2543Smrg 870706f2543Smrg FreeDeviceClass(KeyClass, (pointer)&classes->key); 871706f2543Smrg FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator); 872706f2543Smrg FreeDeviceClass(ButtonClass, (pointer)&classes->button); 873706f2543Smrg FreeDeviceClass(FocusClass, (pointer)&classes->focus); 874706f2543Smrg FreeDeviceClass(ProximityClass, (pointer)&classes->proximity); 875706f2543Smrg 876706f2543Smrg FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed); 877706f2543Smrg FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed); 878706f2543Smrg FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed); 879706f2543Smrg FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed); 880706f2543Smrg FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell); 881706f2543Smrg FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds); 882706f2543Smrg 883706f2543Smrg} 884706f2543Smrg 885706f2543Smrg/** 886706f2543Smrg * Close down a device and free all resources. 887706f2543Smrg * Once closed down, the driver will probably not expect you that you'll ever 888706f2543Smrg * enable it again and free associated structs. If you want the device to just 889706f2543Smrg * be disabled, DisableDevice(). 890706f2543Smrg * Don't call this function directly, use RemoveDevice() instead. 891706f2543Smrg */ 892706f2543Smrgstatic void 893706f2543SmrgCloseDevice(DeviceIntPtr dev) 894706f2543Smrg{ 895706f2543Smrg ScreenPtr screen = screenInfo.screens[0]; 896706f2543Smrg ClassesPtr classes; 897706f2543Smrg int j; 898706f2543Smrg 899706f2543Smrg if (!dev) 900706f2543Smrg return; 901706f2543Smrg 902706f2543Smrg XIDeleteAllDeviceProperties(dev); 903706f2543Smrg 904706f2543Smrg if (dev->inited) 905706f2543Smrg (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); 906706f2543Smrg 907706f2543Smrg /* free sprite memory */ 908706f2543Smrg if (IsMaster(dev) && dev->spriteInfo->sprite) 909706f2543Smrg screen->DeviceCursorCleanup(dev, screen); 910706f2543Smrg 911706f2543Smrg /* free acceleration info */ 912706f2543Smrg if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc) 913706f2543Smrg dev->valuator->accelScheme.AccelCleanupProc(dev); 914706f2543Smrg 915706f2543Smrg while (dev->xkb_interest) 916706f2543Smrg XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); 917706f2543Smrg 918706f2543Smrg free(dev->name); 919706f2543Smrg 920706f2543Smrg classes = (ClassesPtr)&dev->key; 921706f2543Smrg FreeAllDeviceClasses(classes); 922706f2543Smrg 923706f2543Smrg if (IsMaster(dev)) 924706f2543Smrg { 925706f2543Smrg classes = dev->unused_classes; 926706f2543Smrg FreeAllDeviceClasses(classes); 927706f2543Smrg free(classes); 928706f2543Smrg } 929706f2543Smrg 930706f2543Smrg if (DevHasCursor(dev) && dev->spriteInfo->sprite) { 931706f2543Smrg if (dev->spriteInfo->sprite->current) 932706f2543Smrg FreeCursor(dev->spriteInfo->sprite->current, None); 933706f2543Smrg free(dev->spriteInfo->sprite->spriteTrace); 934706f2543Smrg free(dev->spriteInfo->sprite); 935706f2543Smrg } 936706f2543Smrg 937706f2543Smrg /* a client may have the device set as client pointer */ 938706f2543Smrg for (j = 0; j < currentMaxClients; j++) 939706f2543Smrg { 940706f2543Smrg if (clients[j] && clients[j]->clientPtr == dev) 941706f2543Smrg { 942706f2543Smrg clients[j]->clientPtr = NULL; 943706f2543Smrg clients[j]->clientPtr = PickPointer(clients[j]); 944706f2543Smrg } 945706f2543Smrg } 946706f2543Smrg 947706f2543Smrg free(dev->deviceGrab.sync.event); 948706f2543Smrg free(dev->config_info); /* Allocated in xf86ActivateDevice. */ 949706f2543Smrg dev->config_info = NULL; 950706f2543Smrg dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE); 951706f2543Smrg} 952706f2543Smrg 953706f2543Smrg/** 954706f2543Smrg * Shut down all devices of one list and free all resources. 955706f2543Smrg */ 956706f2543Smrgstatic 957706f2543Smrgvoid 958706f2543SmrgCloseDeviceList(DeviceIntPtr *listHead) 959706f2543Smrg{ 960706f2543Smrg /* Used to mark devices that we tried to free */ 961706f2543Smrg Bool freedIds[MAXDEVICES]; 962706f2543Smrg DeviceIntPtr dev; 963706f2543Smrg int i; 964706f2543Smrg 965706f2543Smrg if (listHead == NULL) 966706f2543Smrg return; 967706f2543Smrg 968706f2543Smrg for (i = 0; i < MAXDEVICES; i++) 969706f2543Smrg freedIds[i] = FALSE; 970706f2543Smrg 971706f2543Smrg dev = *listHead; 972706f2543Smrg while (dev != NULL) 973706f2543Smrg { 974706f2543Smrg freedIds[dev->id] = TRUE; 975706f2543Smrg DeleteInputDeviceRequest(dev); 976706f2543Smrg 977706f2543Smrg dev = *listHead; 978706f2543Smrg while (dev != NULL && freedIds[dev->id]) 979706f2543Smrg dev = dev->next; 980706f2543Smrg } 981706f2543Smrg} 982706f2543Smrg 983706f2543Smrg/** 984706f2543Smrg * Shut down all devices, free all resources, etc. 985706f2543Smrg * Only useful if you're shutting down the server! 986706f2543Smrg */ 987706f2543Smrgvoid 988706f2543SmrgCloseDownDevices(void) 989706f2543Smrg{ 990706f2543Smrg DeviceIntPtr dev; 991706f2543Smrg 992706f2543Smrg OsBlockSignals(); 993706f2543Smrg 994706f2543Smrg /* Float all SDs before closing them. Note that at this point resources 995706f2543Smrg * (e.g. cursors) have been freed already, so we can't just call 996706f2543Smrg * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master 997706f2543Smrg * to NULL and pretend nothing happened. 998706f2543Smrg */ 999706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) 1000706f2543Smrg { 1001706f2543Smrg if (!IsMaster(dev) && dev->u.master) 1002706f2543Smrg dev->u.master = NULL; 1003706f2543Smrg } 1004706f2543Smrg 1005706f2543Smrg CloseDeviceList(&inputInfo.devices); 1006706f2543Smrg CloseDeviceList(&inputInfo.off_devices); 1007706f2543Smrg 1008706f2543Smrg CloseDevice(inputInfo.pointer); 1009706f2543Smrg CloseDevice(inputInfo.keyboard); 1010706f2543Smrg 1011706f2543Smrg inputInfo.devices = NULL; 1012706f2543Smrg inputInfo.off_devices = NULL; 1013706f2543Smrg inputInfo.keyboard = NULL; 1014706f2543Smrg inputInfo.pointer = NULL; 1015706f2543Smrg XkbDeleteRulesDflts(); 1016706f2543Smrg 1017706f2543Smrg OsReleaseSignals(); 1018706f2543Smrg} 1019706f2543Smrg 1020706f2543Smrg/** 1021706f2543Smrg * Remove the cursor sprite for all devices. This needs to be done before any 1022706f2543Smrg * resources are freed or any device is deleted. 1023706f2543Smrg */ 1024706f2543Smrgvoid 1025706f2543SmrgUndisplayDevices(void) 1026706f2543Smrg{ 1027706f2543Smrg DeviceIntPtr dev; 1028706f2543Smrg ScreenPtr screen = screenInfo.screens[0]; 1029706f2543Smrg 1030706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) 1031706f2543Smrg screen->DisplayCursor(dev, screen, NullCursor); 1032706f2543Smrg} 1033706f2543Smrg 1034706f2543Smrg/** 1035706f2543Smrg * Remove a device from the device list, closes it and thus frees all 1036706f2543Smrg * resources. 1037706f2543Smrg * Removes both enabled and disabled devices and notifies all devices about 1038706f2543Smrg * the removal of the device. 1039706f2543Smrg * 1040706f2543Smrg * No PresenceNotify is sent for device that the client never saw. This can 1041706f2543Smrg * happen if a malloc fails during the addition of master devices. If 1042706f2543Smrg * dev->init is FALSE it means the client never received a DeviceAdded event, 1043706f2543Smrg * so let's not send a DeviceRemoved event either. 1044706f2543Smrg * 1045706f2543Smrg * @param sendevent True if an XI2 event should be sent. 1046706f2543Smrg */ 1047706f2543Smrgint 1048706f2543SmrgRemoveDevice(DeviceIntPtr dev, BOOL sendevent) 1049706f2543Smrg{ 1050706f2543Smrg DeviceIntPtr prev,tmp,next; 1051706f2543Smrg int ret = BadMatch; 1052706f2543Smrg ScreenPtr screen = screenInfo.screens[0]; 1053706f2543Smrg int deviceid; 1054706f2543Smrg int initialized; 1055706f2543Smrg int flags[MAXDEVICES] = {0}; 1056706f2543Smrg 1057706f2543Smrg DebugF("(dix) removing device %d\n", dev->id); 1058706f2543Smrg 1059706f2543Smrg if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer) 1060706f2543Smrg return BadImplementation; 1061706f2543Smrg 1062706f2543Smrg initialized = dev->inited; 1063706f2543Smrg deviceid = dev->id; 1064706f2543Smrg 1065706f2543Smrg if (initialized) 1066706f2543Smrg { 1067706f2543Smrg if (DevHasCursor(dev)) 1068706f2543Smrg screen->DisplayCursor(dev, screen, NullCursor); 1069706f2543Smrg 1070706f2543Smrg DisableDevice(dev, sendevent); 1071706f2543Smrg flags[dev->id] = XIDeviceDisabled; 1072706f2543Smrg } 1073706f2543Smrg 1074706f2543Smrg prev = NULL; 1075706f2543Smrg for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { 1076706f2543Smrg next = tmp->next; 1077706f2543Smrg if (tmp == dev) { 1078706f2543Smrg 1079706f2543Smrg if (prev==NULL) 1080706f2543Smrg inputInfo.devices = next; 1081706f2543Smrg else 1082706f2543Smrg prev->next = next; 1083706f2543Smrg 1084706f2543Smrg flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved; 1085706f2543Smrg CloseDevice(tmp); 1086706f2543Smrg ret = Success; 1087706f2543Smrg } 1088706f2543Smrg } 1089706f2543Smrg 1090706f2543Smrg prev = NULL; 1091706f2543Smrg for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) { 1092706f2543Smrg next = tmp->next; 1093706f2543Smrg if (tmp == dev) { 1094706f2543Smrg flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved; 1095706f2543Smrg CloseDevice(tmp); 1096706f2543Smrg 1097706f2543Smrg if (prev == NULL) 1098706f2543Smrg inputInfo.off_devices = next; 1099706f2543Smrg else 1100706f2543Smrg prev->next = next; 1101706f2543Smrg 1102706f2543Smrg ret = Success; 1103706f2543Smrg } 1104706f2543Smrg } 1105706f2543Smrg 1106706f2543Smrg if (ret == Success && initialized) { 1107706f2543Smrg inputInfo.numDevices--; 1108706f2543Smrg SendDevicePresenceEvent(deviceid, DeviceRemoved); 1109706f2543Smrg if (sendevent) 1110706f2543Smrg XISendDeviceHierarchyEvent(flags); 1111706f2543Smrg } 1112706f2543Smrg 1113706f2543Smrg return ret; 1114706f2543Smrg} 1115706f2543Smrg 1116706f2543Smrgint 1117706f2543SmrgNumMotionEvents(void) 1118706f2543Smrg{ 1119706f2543Smrg /* only called to fill data in initial connection reply. 1120706f2543Smrg * VCP is ok here, it is the only fixed device we have. */ 1121706f2543Smrg return inputInfo.pointer->valuator->numMotionEvents; 1122706f2543Smrg} 1123706f2543Smrg 1124706f2543Smrgint 1125706f2543SmrgdixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode) 1126706f2543Smrg{ 1127706f2543Smrg DeviceIntPtr dev; 1128706f2543Smrg int rc; 1129706f2543Smrg *pDev = NULL; 1130706f2543Smrg 1131706f2543Smrg for (dev=inputInfo.devices; dev; dev=dev->next) { 1132706f2543Smrg if (dev->id == id) 1133706f2543Smrg goto found; 1134706f2543Smrg } 1135706f2543Smrg for (dev=inputInfo.off_devices; dev; dev=dev->next) { 1136706f2543Smrg if (dev->id == id) 1137706f2543Smrg goto found; 1138706f2543Smrg } 1139706f2543Smrg return BadDevice; 1140706f2543Smrg 1141706f2543Smrgfound: 1142706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 1143706f2543Smrg if (rc == Success) 1144706f2543Smrg *pDev = dev; 1145706f2543Smrg return rc; 1146706f2543Smrg} 1147706f2543Smrg 1148706f2543Smrgvoid 1149706f2543SmrgQueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode) 1150706f2543Smrg{ 1151706f2543Smrg if (inputInfo.keyboard) { 1152706f2543Smrg *minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code; 1153706f2543Smrg *maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code; 1154706f2543Smrg } 1155706f2543Smrg} 1156706f2543Smrg 1157706f2543Smrg/* Notably, this function does not expand the destination's keycode range, or 1158706f2543Smrg * notify clients. */ 1159706f2543SmrgBool 1160706f2543SmrgSetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) 1161706f2543Smrg{ 1162706f2543Smrg int i, j; 1163706f2543Smrg KeySym *tmp; 1164706f2543Smrg int rowDif = src->minKeyCode - dst->minKeyCode; 1165706f2543Smrg 1166706f2543Smrg /* if keysym map size changes, grow map first */ 1167706f2543Smrg if (src->mapWidth < dst->mapWidth) { 1168706f2543Smrg for (i = src->minKeyCode; i <= src->maxKeyCode; i++) { 1169706f2543Smrg#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c)) 1170706f2543Smrg#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c)) 1171706f2543Smrg for (j = 0; j < src->mapWidth; j++) 1172706f2543Smrg dst->map[DI(i, j)] = src->map[SI(i, j)]; 1173706f2543Smrg for (j = src->mapWidth; j < dst->mapWidth; j++) 1174706f2543Smrg dst->map[DI(i, j)] = NoSymbol; 1175706f2543Smrg#undef SI 1176706f2543Smrg#undef DI 1177706f2543Smrg } 1178706f2543Smrg return TRUE; 1179706f2543Smrg } 1180706f2543Smrg else if (src->mapWidth > dst->mapWidth) { 1181706f2543Smrg i = sizeof(KeySym) * src->mapWidth * 1182706f2543Smrg (dst->maxKeyCode - dst->minKeyCode + 1); 1183706f2543Smrg tmp = calloc(sizeof(KeySym), i); 1184706f2543Smrg if (!tmp) 1185706f2543Smrg return FALSE; 1186706f2543Smrg 1187706f2543Smrg if (dst->map) { 1188706f2543Smrg for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) 1189706f2543Smrg memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth], 1190706f2543Smrg dst->mapWidth * sizeof(KeySym)); 1191706f2543Smrg free(dst->map); 1192706f2543Smrg } 1193706f2543Smrg dst->mapWidth = src->mapWidth; 1194706f2543Smrg dst->map = tmp; 1195706f2543Smrg } 1196706f2543Smrg else if (!dst->map) { 1197706f2543Smrg i = sizeof(KeySym) * src->mapWidth * 1198706f2543Smrg (dst->maxKeyCode - dst->minKeyCode + 1); 1199706f2543Smrg tmp = calloc(sizeof(KeySym), i); 1200706f2543Smrg if (!tmp) 1201706f2543Smrg return FALSE; 1202706f2543Smrg 1203706f2543Smrg dst->map = tmp; 1204706f2543Smrg dst->mapWidth = src->mapWidth; 1205706f2543Smrg } 1206706f2543Smrg 1207706f2543Smrg memmove(&dst->map[rowDif * dst->mapWidth], src->map, 1208706f2543Smrg (src->maxKeyCode - src->minKeyCode + 1) * 1209706f2543Smrg dst->mapWidth * sizeof(KeySym)); 1210706f2543Smrg 1211706f2543Smrg return TRUE; 1212706f2543Smrg} 1213706f2543Smrg 1214706f2543SmrgBool 1215706f2543SmrgInitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels, 1216706f2543Smrg CARD8 *map) 1217706f2543Smrg{ 1218706f2543Smrg ButtonClassPtr butc; 1219706f2543Smrg int i; 1220706f2543Smrg 1221706f2543Smrg butc = calloc(1, sizeof(ButtonClassRec)); 1222706f2543Smrg if (!butc) 1223706f2543Smrg return FALSE; 1224706f2543Smrg butc->numButtons = numButtons; 1225706f2543Smrg butc->sourceid = dev->id; 1226706f2543Smrg for (i = 1; i <= numButtons; i++) 1227706f2543Smrg butc->map[i] = map[i]; 1228706f2543Smrg for (i = numButtons + 1; i < MAP_LENGTH; i++) 1229706f2543Smrg butc->map[i] = i; 1230706f2543Smrg memcpy(butc->labels, labels, numButtons * sizeof(Atom)); 1231706f2543Smrg dev->button = butc; 1232706f2543Smrg return TRUE; 1233706f2543Smrg} 1234706f2543Smrg 1235706f2543Smrg/** 1236706f2543Smrg * Allocate a valuator class and set up the pointers for the axis values 1237706f2543Smrg * appropriately. 1238706f2543Smrg * 1239706f2543Smrg * @param src If non-NULL, the memory is reallocated from src. If NULL, the 1240706f2543Smrg * memory is calloc'd. 1241706f2543Smrg * @parma numAxes Number of axes to allocate. 1242706f2543Smrg * @return The allocated valuator struct. 1243706f2543Smrg */ 1244706f2543SmrgValuatorClassPtr 1245706f2543SmrgAllocValuatorClass(ValuatorClassPtr src, int numAxes) 1246706f2543Smrg{ 1247706f2543Smrg ValuatorClassPtr v; 1248706f2543Smrg /* force alignment with double */ 1249706f2543Smrg union align_u { ValuatorClassRec valc; double d; } *align; 1250706f2543Smrg int size; 1251706f2543Smrg 1252706f2543Smrg size = sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo)); 1253706f2543Smrg align = (union align_u *) realloc(src, size); 1254706f2543Smrg 1255706f2543Smrg if (!align) 1256706f2543Smrg return NULL; 1257706f2543Smrg 1258706f2543Smrg if (!src) 1259706f2543Smrg memset(align, 0, size); 1260706f2543Smrg 1261706f2543Smrg v = &align->valc; 1262706f2543Smrg v->numAxes = numAxes; 1263706f2543Smrg v->axisVal = (double*)(align + 1); 1264706f2543Smrg v->axes = (AxisInfoPtr)(v->axisVal + numAxes); 1265706f2543Smrg 1266706f2543Smrg return v; 1267706f2543Smrg} 1268706f2543Smrg 1269706f2543SmrgBool 1270706f2543SmrgInitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels, 1271706f2543Smrg int numMotionEvents, int mode) 1272706f2543Smrg{ 1273706f2543Smrg int i; 1274706f2543Smrg ValuatorClassPtr valc; 1275706f2543Smrg 1276706f2543Smrg if (!dev) 1277706f2543Smrg return FALSE; 1278706f2543Smrg 1279706f2543Smrg if (numAxes > MAX_VALUATORS) 1280706f2543Smrg { 1281706f2543Smrg LogMessage(X_WARNING, 1282706f2543Smrg "Device '%s' has %d axes, only using first %d.\n", 1283706f2543Smrg dev->name, numAxes, MAX_VALUATORS); 1284706f2543Smrg numAxes = MAX_VALUATORS; 1285706f2543Smrg } 1286706f2543Smrg 1287706f2543Smrg valc = AllocValuatorClass(NULL, numAxes); 1288706f2543Smrg if (!valc) 1289706f2543Smrg return FALSE; 1290706f2543Smrg 1291706f2543Smrg valc->sourceid = dev->id; 1292706f2543Smrg valc->motion = NULL; 1293706f2543Smrg valc->first_motion = 0; 1294706f2543Smrg valc->last_motion = 0; 1295706f2543Smrg 1296706f2543Smrg valc->numMotionEvents = numMotionEvents; 1297706f2543Smrg valc->motionHintWindow = NullWindow; 1298706f2543Smrg 1299706f2543Smrg if (mode & OutOfProximity) 1300706f2543Smrg InitProximityClassDeviceStruct(dev); 1301706f2543Smrg 1302706f2543Smrg dev->valuator = valc; 1303706f2543Smrg 1304706f2543Smrg AllocateMotionHistory(dev); 1305706f2543Smrg 1306706f2543Smrg for (i=0; i<numAxes; i++) { 1307706f2543Smrg InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1308706f2543Smrg 0, 0, 0, mode); 1309706f2543Smrg valc->axisVal[i]=0; 1310706f2543Smrg } 1311706f2543Smrg 1312706f2543Smrg dev->last.numValuators = numAxes; 1313706f2543Smrg 1314706f2543Smrg if (IsMaster(dev) || /* do not accelerate master or xtest devices */ 1315706f2543Smrg IsXTestDevice(dev, NULL)) 1316706f2543Smrg InitPointerAccelerationScheme(dev, PtrAccelNoOp); 1317706f2543Smrg else 1318706f2543Smrg InitPointerAccelerationScheme(dev, PtrAccelDefault); 1319706f2543Smrg return TRUE; 1320706f2543Smrg} 1321706f2543Smrg 1322706f2543Smrg/* global list of acceleration schemes */ 1323706f2543SmrgValuatorAccelerationRec pointerAccelerationScheme[] = { 1324706f2543Smrg {PtrAccelNoOp, NULL, NULL, NULL}, 1325706f2543Smrg {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup}, 1326706f2543Smrg {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL}, 1327706f2543Smrg {-1, NULL, NULL, NULL} /* terminator */ 1328706f2543Smrg}; 1329706f2543Smrg 1330706f2543Smrg/** 1331706f2543Smrg * install an acceleration scheme. returns TRUE on success, and should not 1332706f2543Smrg * change anything if unsuccessful. 1333706f2543Smrg */ 1334706f2543SmrgBool 1335706f2543SmrgInitPointerAccelerationScheme(DeviceIntPtr dev, 1336706f2543Smrg int scheme) 1337706f2543Smrg{ 1338706f2543Smrg int x, i = -1; 1339706f2543Smrg void* data = NULL; 1340706f2543Smrg ValuatorClassPtr val; 1341706f2543Smrg 1342706f2543Smrg val = dev->valuator; 1343706f2543Smrg 1344706f2543Smrg if(!val) 1345706f2543Smrg return FALSE; 1346706f2543Smrg 1347706f2543Smrg if(IsMaster(dev) && scheme != PtrAccelNoOp) 1348706f2543Smrg return FALSE; 1349706f2543Smrg 1350706f2543Smrg for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) { 1351706f2543Smrg if(pointerAccelerationScheme[x].number == scheme){ 1352706f2543Smrg i = x; 1353706f2543Smrg break; 1354706f2543Smrg } 1355706f2543Smrg } 1356706f2543Smrg 1357706f2543Smrg if(-1 == i) 1358706f2543Smrg return FALSE; 1359706f2543Smrg 1360706f2543Smrg if (val->accelScheme.AccelCleanupProc) 1361706f2543Smrg val->accelScheme.AccelCleanupProc(dev); 1362706f2543Smrg 1363706f2543Smrg /* init scheme-specific data */ 1364706f2543Smrg switch(scheme){ 1365706f2543Smrg case PtrAccelPredictable: 1366706f2543Smrg { 1367706f2543Smrg DeviceVelocityPtr s; 1368706f2543Smrg s = malloc(sizeof(DeviceVelocityRec)); 1369706f2543Smrg if(!s) 1370706f2543Smrg return FALSE; 1371706f2543Smrg InitVelocityData(s); 1372706f2543Smrg data = s; 1373706f2543Smrg break; 1374706f2543Smrg } 1375706f2543Smrg default: 1376706f2543Smrg break; 1377706f2543Smrg } 1378706f2543Smrg 1379706f2543Smrg val->accelScheme = pointerAccelerationScheme[i]; 1380706f2543Smrg val->accelScheme.accelData = data; 1381706f2543Smrg 1382706f2543Smrg /* post-init scheme */ 1383706f2543Smrg switch(scheme){ 1384706f2543Smrg case PtrAccelPredictable: 1385706f2543Smrg InitializePredictableAccelerationProperties(dev); 1386706f2543Smrg break; 1387706f2543Smrg 1388706f2543Smrg default: 1389706f2543Smrg break; 1390706f2543Smrg } 1391706f2543Smrg 1392706f2543Smrg return TRUE; 1393706f2543Smrg} 1394706f2543Smrg 1395706f2543SmrgBool 1396706f2543SmrgInitAbsoluteClassDeviceStruct(DeviceIntPtr dev) 1397706f2543Smrg{ 1398706f2543Smrg AbsoluteClassPtr abs; 1399706f2543Smrg 1400706f2543Smrg abs = malloc(sizeof(AbsoluteClassRec)); 1401706f2543Smrg if (!abs) 1402706f2543Smrg return FALSE; 1403706f2543Smrg 1404706f2543Smrg /* we don't do anything sensible with these, but should */ 1405706f2543Smrg abs->min_x = NO_AXIS_LIMITS; 1406706f2543Smrg abs->min_y = NO_AXIS_LIMITS; 1407706f2543Smrg abs->max_x = NO_AXIS_LIMITS; 1408706f2543Smrg abs->max_y = NO_AXIS_LIMITS; 1409706f2543Smrg abs->flip_x = 0; 1410706f2543Smrg abs->flip_y = 0; 1411706f2543Smrg abs->rotation = 0; 1412706f2543Smrg abs->button_threshold = 0; 1413706f2543Smrg 1414706f2543Smrg abs->offset_x = 0; 1415706f2543Smrg abs->offset_y = 0; 1416706f2543Smrg abs->width = NO_AXIS_LIMITS; 1417706f2543Smrg abs->height = NO_AXIS_LIMITS; 1418706f2543Smrg abs->following = 0; 1419706f2543Smrg abs->screen = 0; 1420706f2543Smrg 1421706f2543Smrg abs->sourceid = dev->id; 1422706f2543Smrg 1423706f2543Smrg dev->absolute = abs; 1424706f2543Smrg 1425706f2543Smrg return TRUE; 1426706f2543Smrg} 1427706f2543Smrg 1428706f2543SmrgBool 1429706f2543SmrgInitFocusClassDeviceStruct(DeviceIntPtr dev) 1430706f2543Smrg{ 1431706f2543Smrg FocusClassPtr focc; 1432706f2543Smrg 1433706f2543Smrg focc = malloc(sizeof(FocusClassRec)); 1434706f2543Smrg if (!focc) 1435706f2543Smrg return FALSE; 1436706f2543Smrg focc->win = PointerRootWin; 1437706f2543Smrg focc->revert = None; 1438706f2543Smrg focc->time = currentTime; 1439706f2543Smrg focc->trace = (WindowPtr *)NULL; 1440706f2543Smrg focc->traceSize = 0; 1441706f2543Smrg focc->traceGood = 0; 1442706f2543Smrg focc->sourceid = dev->id; 1443706f2543Smrg dev->focus = focc; 1444706f2543Smrg return TRUE; 1445706f2543Smrg} 1446706f2543Smrg 1447706f2543SmrgBool 1448706f2543SmrgInitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) 1449706f2543Smrg{ 1450706f2543Smrg PtrFeedbackPtr feedc; 1451706f2543Smrg 1452706f2543Smrg feedc = malloc(sizeof(PtrFeedbackClassRec)); 1453706f2543Smrg if (!feedc) 1454706f2543Smrg return FALSE; 1455706f2543Smrg feedc->CtrlProc = controlProc; 1456706f2543Smrg feedc->ctrl = defaultPointerControl; 1457706f2543Smrg feedc->ctrl.id = 0; 1458706f2543Smrg if ( (feedc->next = dev->ptrfeed) ) 1459706f2543Smrg feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1; 1460706f2543Smrg dev->ptrfeed = feedc; 1461706f2543Smrg (*controlProc)(dev, &feedc->ctrl); 1462706f2543Smrg return TRUE; 1463706f2543Smrg} 1464706f2543Smrg 1465706f2543Smrg 1466706f2543Smrgstatic LedCtrl defaultLedControl = { 1467706f2543Smrg DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; 1468706f2543Smrg 1469706f2543Smrgstatic BellCtrl defaultBellControl = { 1470706f2543Smrg DEFAULT_BELL, 1471706f2543Smrg DEFAULT_BELL_PITCH, 1472706f2543Smrg DEFAULT_BELL_DURATION, 1473706f2543Smrg 0}; 1474706f2543Smrg 1475706f2543Smrgstatic IntegerCtrl defaultIntegerControl = { 1476706f2543Smrg DEFAULT_INT_RESOLUTION, 1477706f2543Smrg DEFAULT_INT_MIN_VALUE, 1478706f2543Smrg DEFAULT_INT_MAX_VALUE, 1479706f2543Smrg DEFAULT_INT_DISPLAYED, 1480706f2543Smrg 0}; 1481706f2543Smrg 1482706f2543SmrgBool 1483706f2543SmrgInitStringFeedbackClassDeviceStruct ( 1484706f2543Smrg DeviceIntPtr dev, StringCtrlProcPtr controlProc, 1485706f2543Smrg int max_symbols, int num_symbols_supported, KeySym *symbols) 1486706f2543Smrg{ 1487706f2543Smrg int i; 1488706f2543Smrg StringFeedbackPtr feedc; 1489706f2543Smrg 1490706f2543Smrg feedc = malloc(sizeof(StringFeedbackClassRec)); 1491706f2543Smrg if (!feedc) 1492706f2543Smrg return FALSE; 1493706f2543Smrg feedc->CtrlProc = controlProc; 1494706f2543Smrg feedc->ctrl.num_symbols_supported = num_symbols_supported; 1495706f2543Smrg feedc->ctrl.num_symbols_displayed = 0; 1496706f2543Smrg feedc->ctrl.max_symbols = max_symbols; 1497706f2543Smrg feedc->ctrl.symbols_supported = malloc(sizeof (KeySym) * num_symbols_supported); 1498706f2543Smrg feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols); 1499706f2543Smrg if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) 1500706f2543Smrg { 1501706f2543Smrg free(feedc->ctrl.symbols_supported); 1502706f2543Smrg free(feedc->ctrl.symbols_displayed); 1503706f2543Smrg free(feedc); 1504706f2543Smrg return FALSE; 1505706f2543Smrg } 1506706f2543Smrg for (i=0; i<num_symbols_supported; i++) 1507706f2543Smrg *(feedc->ctrl.symbols_supported+i) = *symbols++; 1508706f2543Smrg for (i=0; i<max_symbols; i++) 1509706f2543Smrg *(feedc->ctrl.symbols_displayed+i) = (KeySym) 0; 1510706f2543Smrg feedc->ctrl.id = 0; 1511706f2543Smrg if ( (feedc->next = dev->stringfeed) ) 1512706f2543Smrg feedc->ctrl.id = dev->stringfeed->ctrl.id + 1; 1513706f2543Smrg dev->stringfeed = feedc; 1514706f2543Smrg (*controlProc)(dev, &feedc->ctrl); 1515706f2543Smrg return TRUE; 1516706f2543Smrg} 1517706f2543Smrg 1518706f2543SmrgBool 1519706f2543SmrgInitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, 1520706f2543Smrg BellCtrlProcPtr controlProc) 1521706f2543Smrg{ 1522706f2543Smrg BellFeedbackPtr feedc; 1523706f2543Smrg 1524706f2543Smrg feedc = malloc(sizeof(BellFeedbackClassRec)); 1525706f2543Smrg if (!feedc) 1526706f2543Smrg return FALSE; 1527706f2543Smrg feedc->CtrlProc = controlProc; 1528706f2543Smrg feedc->BellProc = bellProc; 1529706f2543Smrg feedc->ctrl = defaultBellControl; 1530706f2543Smrg feedc->ctrl.id = 0; 1531706f2543Smrg if ( (feedc->next = dev->bell) ) 1532706f2543Smrg feedc->ctrl.id = dev->bell->ctrl.id + 1; 1533706f2543Smrg dev->bell = feedc; 1534706f2543Smrg (*controlProc)(dev, &feedc->ctrl); 1535706f2543Smrg return TRUE; 1536706f2543Smrg} 1537706f2543Smrg 1538706f2543SmrgBool 1539706f2543SmrgInitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc) 1540706f2543Smrg{ 1541706f2543Smrg LedFeedbackPtr feedc; 1542706f2543Smrg 1543706f2543Smrg feedc = malloc(sizeof(LedFeedbackClassRec)); 1544706f2543Smrg if (!feedc) 1545706f2543Smrg return FALSE; 1546706f2543Smrg feedc->CtrlProc = controlProc; 1547706f2543Smrg feedc->ctrl = defaultLedControl; 1548706f2543Smrg feedc->ctrl.id = 0; 1549706f2543Smrg if ( (feedc->next = dev->leds) ) 1550706f2543Smrg feedc->ctrl.id = dev->leds->ctrl.id + 1; 1551706f2543Smrg feedc->xkb_sli= NULL; 1552706f2543Smrg dev->leds = feedc; 1553706f2543Smrg (*controlProc)(dev, &feedc->ctrl); 1554706f2543Smrg return TRUE; 1555706f2543Smrg} 1556706f2543Smrg 1557706f2543SmrgBool 1558706f2543SmrgInitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc) 1559706f2543Smrg{ 1560706f2543Smrg IntegerFeedbackPtr feedc; 1561706f2543Smrg 1562706f2543Smrg feedc = malloc(sizeof(IntegerFeedbackClassRec)); 1563706f2543Smrg if (!feedc) 1564706f2543Smrg return FALSE; 1565706f2543Smrg feedc->CtrlProc = controlProc; 1566706f2543Smrg feedc->ctrl = defaultIntegerControl; 1567706f2543Smrg feedc->ctrl.id = 0; 1568706f2543Smrg if ( (feedc->next = dev->intfeed) ) 1569706f2543Smrg feedc->ctrl.id = dev->intfeed->ctrl.id + 1; 1570706f2543Smrg dev->intfeed = feedc; 1571706f2543Smrg (*controlProc)(dev, &feedc->ctrl); 1572706f2543Smrg return TRUE; 1573706f2543Smrg} 1574706f2543Smrg 1575706f2543SmrgBool 1576706f2543SmrgInitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_labels, 1577706f2543Smrg PtrCtrlProcPtr controlProc, int numMotionEvents, 1578706f2543Smrg int numAxes, Atom *axes_labels) 1579706f2543Smrg{ 1580706f2543Smrg DeviceIntPtr dev = (DeviceIntPtr)device; 1581706f2543Smrg 1582706f2543Smrg return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) && 1583706f2543Smrg InitValuatorClassDeviceStruct(dev, numAxes, axes_labels, 1584706f2543Smrg numMotionEvents, Relative) && 1585706f2543Smrg InitPtrFeedbackClassDeviceStruct(dev, controlProc)); 1586706f2543Smrg} 1587706f2543Smrg 1588706f2543Smrg/* 1589706f2543Smrg * Check if the given buffer contains elements between low (inclusive) and 1590706f2543Smrg * high (inclusive) only. 1591706f2543Smrg * 1592706f2543Smrg * @return TRUE if the device map is invalid, FALSE otherwise. 1593706f2543Smrg */ 1594706f2543SmrgBool 1595706f2543SmrgBadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval) 1596706f2543Smrg{ 1597706f2543Smrg int i; 1598706f2543Smrg 1599706f2543Smrg for (i = 0; i < length; i++) 1600706f2543Smrg if (buff[i]) /* only check non-zero elements */ 1601706f2543Smrg { 1602706f2543Smrg if ((low > buff[i]) || (high < buff[i])) 1603706f2543Smrg { 1604706f2543Smrg *errval = buff[i]; 1605706f2543Smrg return TRUE; 1606706f2543Smrg } 1607706f2543Smrg } 1608706f2543Smrg return FALSE; 1609706f2543Smrg} 1610706f2543Smrg 1611706f2543Smrgint 1612706f2543SmrgProcSetModifierMapping(ClientPtr client) 1613706f2543Smrg{ 1614706f2543Smrg xSetModifierMappingReply rep; 1615706f2543Smrg int rc; 1616706f2543Smrg REQUEST(xSetModifierMappingReq); 1617706f2543Smrg REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); 1618706f2543Smrg 1619706f2543Smrg if (client->req_len != ((stuff->numKeyPerModifier << 1) + 1620706f2543Smrg bytes_to_int32(sizeof(xSetModifierMappingReq)))) 1621706f2543Smrg return BadLength; 1622706f2543Smrg 1623706f2543Smrg rep.type = X_Reply; 1624706f2543Smrg rep.length = 0; 1625706f2543Smrg rep.sequenceNumber = client->sequence; 1626706f2543Smrg 1627706f2543Smrg rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1], 1628706f2543Smrg stuff->numKeyPerModifier); 1629706f2543Smrg if (rc == MappingFailed || rc == -1) 1630706f2543Smrg return BadValue; 1631706f2543Smrg if (rc != Success && rc != MappingSuccess && rc != MappingFailed && 1632706f2543Smrg rc != MappingBusy) 1633706f2543Smrg return rc; 1634706f2543Smrg 1635706f2543Smrg rep.success = rc; 1636706f2543Smrg 1637706f2543Smrg WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); 1638706f2543Smrg return Success; 1639706f2543Smrg} 1640706f2543Smrg 1641706f2543Smrgint 1642706f2543SmrgProcGetModifierMapping(ClientPtr client) 1643706f2543Smrg{ 1644706f2543Smrg xGetModifierMappingReply rep; 1645706f2543Smrg int max_keys_per_mod = 0; 1646706f2543Smrg KeyCode *modkeymap = NULL; 1647706f2543Smrg REQUEST_SIZE_MATCH(xReq); 1648706f2543Smrg 1649706f2543Smrg generate_modkeymap(client, PickKeyboard(client), &modkeymap, 1650706f2543Smrg &max_keys_per_mod); 1651706f2543Smrg 1652706f2543Smrg memset(&rep, 0, sizeof(xGetModifierMappingReply)); 1653706f2543Smrg rep.type = X_Reply; 1654706f2543Smrg rep.numKeyPerModifier = max_keys_per_mod; 1655706f2543Smrg rep.sequenceNumber = client->sequence; 1656706f2543Smrg /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ 1657706f2543Smrg rep.length = max_keys_per_mod << 1; 1658706f2543Smrg 1659706f2543Smrg WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); 1660706f2543Smrg (void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap); 1661706f2543Smrg 1662706f2543Smrg free(modkeymap); 1663706f2543Smrg 1664706f2543Smrg return Success; 1665706f2543Smrg} 1666706f2543Smrg 1667706f2543Smrgint 1668706f2543SmrgProcChangeKeyboardMapping(ClientPtr client) 1669706f2543Smrg{ 1670706f2543Smrg REQUEST(xChangeKeyboardMappingReq); 1671706f2543Smrg unsigned len; 1672706f2543Smrg KeySymsRec keysyms; 1673706f2543Smrg DeviceIntPtr pDev, tmp; 1674706f2543Smrg int rc; 1675706f2543Smrg REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); 1676706f2543Smrg 1677706f2543Smrg len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq)); 1678706f2543Smrg if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) 1679706f2543Smrg return BadLength; 1680706f2543Smrg 1681706f2543Smrg pDev = PickKeyboard(client); 1682706f2543Smrg 1683706f2543Smrg if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) || 1684706f2543Smrg (stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) { 1685706f2543Smrg client->errorValue = stuff->firstKeyCode; 1686706f2543Smrg return BadValue; 1687706f2543Smrg 1688706f2543Smrg } 1689706f2543Smrg if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) > 1690706f2543Smrg pDev->key->xkbInfo->desc->max_key_code) || 1691706f2543Smrg (stuff->keySymsPerKeyCode == 0)) { 1692706f2543Smrg client->errorValue = stuff->keySymsPerKeyCode; 1693706f2543Smrg return BadValue; 1694706f2543Smrg } 1695706f2543Smrg 1696706f2543Smrg keysyms.minKeyCode = stuff->firstKeyCode; 1697706f2543Smrg keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; 1698706f2543Smrg keysyms.mapWidth = stuff->keySymsPerKeyCode; 1699706f2543Smrg keysyms.map = (KeySym *) &stuff[1]; 1700706f2543Smrg 1701706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); 1702706f2543Smrg if (rc != Success) 1703706f2543Smrg return rc; 1704706f2543Smrg 1705706f2543Smrg XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode, 1706706f2543Smrg stuff->keyCodes, NULL, client); 1707706f2543Smrg 1708706f2543Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 1709706f2543Smrg if (IsMaster(tmp) || tmp->u.master != pDev) 1710706f2543Smrg continue; 1711706f2543Smrg if (!tmp->key) 1712706f2543Smrg continue; 1713706f2543Smrg 1714706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); 1715706f2543Smrg if (rc != Success) 1716706f2543Smrg continue; 1717706f2543Smrg 1718706f2543Smrg XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode, 1719706f2543Smrg stuff->keyCodes, NULL, client); 1720706f2543Smrg } 1721706f2543Smrg 1722706f2543Smrg return Success; 1723706f2543Smrg} 1724706f2543Smrg 1725706f2543Smrgint 1726706f2543SmrgProcSetPointerMapping(ClientPtr client) 1727706f2543Smrg{ 1728706f2543Smrg BYTE *map; 1729706f2543Smrg int ret; 1730706f2543Smrg int i, j; 1731706f2543Smrg DeviceIntPtr ptr = PickPointer(client); 1732706f2543Smrg xSetPointerMappingReply rep; 1733706f2543Smrg REQUEST(xSetPointerMappingReq); 1734706f2543Smrg REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); 1735706f2543Smrg 1736706f2543Smrg if (client->req_len != 1737706f2543Smrg bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts)) 1738706f2543Smrg return BadLength; 1739706f2543Smrg rep.type = X_Reply; 1740706f2543Smrg rep.length = 0; 1741706f2543Smrg rep.sequenceNumber = client->sequence; 1742706f2543Smrg rep.success = MappingSuccess; 1743706f2543Smrg map = (BYTE *)&stuff[1]; 1744706f2543Smrg 1745706f2543Smrg /* So we're bounded here by the number of core buttons. This check 1746706f2543Smrg * probably wants disabling through XFixes. */ 1747706f2543Smrg /* MPX: With ClientPointer, we can return the right number of buttons. 1748706f2543Smrg * Let's just hope nobody changed ClientPointer between GetPointerMapping 1749706f2543Smrg * and SetPointerMapping 1750706f2543Smrg */ 1751706f2543Smrg if (stuff->nElts != ptr->button->numButtons) { 1752706f2543Smrg client->errorValue = stuff->nElts; 1753706f2543Smrg return BadValue; 1754706f2543Smrg } 1755706f2543Smrg 1756706f2543Smrg /* Core protocol specs don't allow for duplicate mappings; this check 1757706f2543Smrg * almost certainly wants disabling through XFixes too. */ 1758706f2543Smrg for (i = 0; i < stuff->nElts; i++) { 1759706f2543Smrg for (j = i + 1; j < stuff->nElts; j++) { 1760706f2543Smrg if (map[i] && map[i] == map[j]) { 1761706f2543Smrg client->errorValue = map[i]; 1762706f2543Smrg return BadValue; 1763706f2543Smrg } 1764706f2543Smrg } 1765706f2543Smrg } 1766706f2543Smrg 1767706f2543Smrg ret = ApplyPointerMapping(ptr, map, stuff->nElts, client); 1768706f2543Smrg if (ret == MappingBusy) 1769706f2543Smrg rep.success = ret; 1770706f2543Smrg else if (ret == -1) 1771706f2543Smrg return BadValue; 1772706f2543Smrg else if (ret != Success) 1773706f2543Smrg return ret; 1774706f2543Smrg 1775706f2543Smrg WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); 1776706f2543Smrg return Success; 1777706f2543Smrg} 1778706f2543Smrg 1779706f2543Smrgint 1780706f2543SmrgProcGetKeyboardMapping(ClientPtr client) 1781706f2543Smrg{ 1782706f2543Smrg xGetKeyboardMappingReply rep; 1783706f2543Smrg DeviceIntPtr kbd = PickKeyboard(client); 1784706f2543Smrg XkbDescPtr xkb; 1785706f2543Smrg KeySymsPtr syms; 1786706f2543Smrg int rc; 1787706f2543Smrg REQUEST(xGetKeyboardMappingReq); 1788706f2543Smrg REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); 1789706f2543Smrg 1790706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); 1791706f2543Smrg if (rc != Success) 1792706f2543Smrg return rc; 1793706f2543Smrg 1794706f2543Smrg xkb = kbd->key->xkbInfo->desc; 1795706f2543Smrg 1796706f2543Smrg if ((stuff->firstKeyCode < xkb->min_key_code) || 1797706f2543Smrg (stuff->firstKeyCode > xkb->max_key_code)) { 1798706f2543Smrg client->errorValue = stuff->firstKeyCode; 1799706f2543Smrg return BadValue; 1800706f2543Smrg } 1801706f2543Smrg if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) { 1802706f2543Smrg client->errorValue = stuff->count; 1803706f2543Smrg return BadValue; 1804706f2543Smrg } 1805706f2543Smrg 1806706f2543Smrg syms = XkbGetCoreMap(kbd); 1807706f2543Smrg if (!syms) 1808706f2543Smrg return BadAlloc; 1809706f2543Smrg 1810706f2543Smrg memset(&rep, 0, sizeof(xGetKeyboardMappingReply)); 1811706f2543Smrg rep.type = X_Reply; 1812706f2543Smrg rep.sequenceNumber = client->sequence; 1813706f2543Smrg rep.keySymsPerKeyCode = syms->mapWidth; 1814706f2543Smrg /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ 1815706f2543Smrg rep.length = syms->mapWidth * stuff->count; 1816706f2543Smrg WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep); 1817706f2543Smrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; 1818706f2543Smrg WriteSwappedDataToClient(client, 1819706f2543Smrg syms->mapWidth * stuff->count * sizeof(KeySym), 1820706f2543Smrg &syms->map[syms->mapWidth * (stuff->firstKeyCode - 1821706f2543Smrg syms->minKeyCode)]); 1822706f2543Smrg free(syms->map); 1823706f2543Smrg free(syms); 1824706f2543Smrg 1825706f2543Smrg return Success; 1826706f2543Smrg} 1827706f2543Smrg 1828706f2543Smrgint 1829706f2543SmrgProcGetPointerMapping(ClientPtr client) 1830706f2543Smrg{ 1831706f2543Smrg xGetPointerMappingReply rep; 1832706f2543Smrg /* Apps may get different values each time they call GetPointerMapping as 1833706f2543Smrg * the ClientPointer could change. */ 1834706f2543Smrg DeviceIntPtr ptr = PickPointer(client); 1835706f2543Smrg ButtonClassPtr butc = ptr->button; 1836706f2543Smrg int rc; 1837706f2543Smrg REQUEST_SIZE_MATCH(xReq); 1838706f2543Smrg 1839706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); 1840706f2543Smrg if (rc != Success) 1841706f2543Smrg return rc; 1842706f2543Smrg 1843706f2543Smrg rep.type = X_Reply; 1844706f2543Smrg rep.sequenceNumber = client->sequence; 1845706f2543Smrg rep.nElts = (butc) ? butc->numButtons : 0; 1846706f2543Smrg rep.length = ((unsigned)rep.nElts + (4-1))/4; 1847706f2543Smrg WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); 1848706f2543Smrg if (butc) 1849706f2543Smrg WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); 1850706f2543Smrg return Success; 1851706f2543Smrg} 1852706f2543Smrg 1853706f2543Smrgvoid 1854706f2543SmrgNoteLedState(DeviceIntPtr keybd, int led, Bool on) 1855706f2543Smrg{ 1856706f2543Smrg KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl; 1857706f2543Smrg if (on) 1858706f2543Smrg ctrl->leds |= ((Leds)1 << (led - 1)); 1859706f2543Smrg else 1860706f2543Smrg ctrl->leds &= ~((Leds)1 << (led - 1)); 1861706f2543Smrg} 1862706f2543Smrg 1863706f2543Smrgint 1864706f2543SmrgOnes(unsigned long mask) /* HACKMEM 169 */ 1865706f2543Smrg{ 1866706f2543Smrg unsigned long y; 1867706f2543Smrg 1868706f2543Smrg y = (mask >> 1) &033333333333; 1869706f2543Smrg y = mask - y - ((y >>1) & 033333333333); 1870706f2543Smrg return (((y + (y >> 3)) & 030707070707) % 077); 1871706f2543Smrg} 1872706f2543Smrg 1873706f2543Smrgstatic int 1874706f2543SmrgDoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, 1875706f2543Smrg BITS32 vmask) 1876706f2543Smrg{ 1877706f2543Smrg#define DO_ALL (-1) 1878706f2543Smrg KeybdCtrl ctrl; 1879706f2543Smrg int t; 1880706f2543Smrg int led = DO_ALL; 1881706f2543Smrg int key = DO_ALL; 1882706f2543Smrg BITS32 index2; 1883706f2543Smrg int mask = vmask, i; 1884706f2543Smrg XkbEventCauseRec cause; 1885706f2543Smrg 1886706f2543Smrg ctrl = keybd->kbdfeed->ctrl; 1887706f2543Smrg while (vmask) { 1888706f2543Smrg index2 = (BITS32) lowbit (vmask); 1889706f2543Smrg vmask &= ~index2; 1890706f2543Smrg switch (index2) { 1891706f2543Smrg case KBKeyClickPercent: 1892706f2543Smrg t = (INT8)*vlist; 1893706f2543Smrg vlist++; 1894706f2543Smrg if (t == -1) { 1895706f2543Smrg t = defaultKeyboardControl.click; 1896706f2543Smrg } 1897706f2543Smrg else if (t < 0 || t > 100) { 1898706f2543Smrg client->errorValue = t; 1899706f2543Smrg return BadValue; 1900706f2543Smrg } 1901706f2543Smrg ctrl.click = t; 1902706f2543Smrg break; 1903706f2543Smrg case KBBellPercent: 1904706f2543Smrg t = (INT8)*vlist; 1905706f2543Smrg vlist++; 1906706f2543Smrg if (t == -1) { 1907706f2543Smrg t = defaultKeyboardControl.bell; 1908706f2543Smrg } 1909706f2543Smrg else if (t < 0 || t > 100) { 1910706f2543Smrg client->errorValue = t; 1911706f2543Smrg return BadValue; 1912706f2543Smrg } 1913706f2543Smrg ctrl.bell = t; 1914706f2543Smrg break; 1915706f2543Smrg case KBBellPitch: 1916706f2543Smrg t = (INT16)*vlist; 1917706f2543Smrg vlist++; 1918706f2543Smrg if (t == -1) { 1919706f2543Smrg t = defaultKeyboardControl.bell_pitch; 1920706f2543Smrg } 1921706f2543Smrg else if (t < 0) { 1922706f2543Smrg client->errorValue = t; 1923706f2543Smrg return BadValue; 1924706f2543Smrg } 1925706f2543Smrg ctrl.bell_pitch = t; 1926706f2543Smrg break; 1927706f2543Smrg case KBBellDuration: 1928706f2543Smrg t = (INT16)*vlist; 1929706f2543Smrg vlist++; 1930706f2543Smrg if (t == -1) 1931706f2543Smrg t = defaultKeyboardControl.bell_duration; 1932706f2543Smrg else if (t < 0) { 1933706f2543Smrg client->errorValue = t; 1934706f2543Smrg return BadValue; 1935706f2543Smrg } 1936706f2543Smrg ctrl.bell_duration = t; 1937706f2543Smrg break; 1938706f2543Smrg case KBLed: 1939706f2543Smrg led = (CARD8)*vlist; 1940706f2543Smrg vlist++; 1941706f2543Smrg if (led < 1 || led > 32) { 1942706f2543Smrg client->errorValue = led; 1943706f2543Smrg return BadValue; 1944706f2543Smrg } 1945706f2543Smrg if (!(mask & KBLedMode)) 1946706f2543Smrg return BadMatch; 1947706f2543Smrg break; 1948706f2543Smrg case KBLedMode: 1949706f2543Smrg t = (CARD8)*vlist; 1950706f2543Smrg vlist++; 1951706f2543Smrg if (t == LedModeOff) { 1952706f2543Smrg if (led == DO_ALL) 1953706f2543Smrg ctrl.leds = 0x0; 1954706f2543Smrg else 1955706f2543Smrg ctrl.leds &= ~(((Leds)(1)) << (led - 1)); 1956706f2543Smrg } 1957706f2543Smrg else if (t == LedModeOn) { 1958706f2543Smrg if (led == DO_ALL) 1959706f2543Smrg ctrl.leds = ~0L; 1960706f2543Smrg else 1961706f2543Smrg ctrl.leds |= (((Leds)(1)) << (led - 1)); 1962706f2543Smrg } 1963706f2543Smrg else { 1964706f2543Smrg client->errorValue = t; 1965706f2543Smrg return BadValue; 1966706f2543Smrg } 1967706f2543Smrg 1968706f2543Smrg XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client); 1969706f2543Smrg XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))), 1970706f2543Smrg ctrl.leds, &cause); 1971706f2543Smrg ctrl.leds = keybd->kbdfeed->ctrl.leds; 1972706f2543Smrg 1973706f2543Smrg break; 1974706f2543Smrg case KBKey: 1975706f2543Smrg key = (KeyCode)*vlist; 1976706f2543Smrg vlist++; 1977706f2543Smrg if ((KeyCode)key < keybd->key->xkbInfo->desc->min_key_code || 1978706f2543Smrg (KeyCode)key > keybd->key->xkbInfo->desc->max_key_code) { 1979706f2543Smrg client->errorValue = key; 1980706f2543Smrg return BadValue; 1981706f2543Smrg } 1982706f2543Smrg if (!(mask & KBAutoRepeatMode)) 1983706f2543Smrg return BadMatch; 1984706f2543Smrg break; 1985706f2543Smrg case KBAutoRepeatMode: 1986706f2543Smrg i = (key >> 3); 1987706f2543Smrg mask = (1 << (key & 7)); 1988706f2543Smrg t = (CARD8)*vlist; 1989706f2543Smrg vlist++; 1990706f2543Smrg if (key != DO_ALL) 1991706f2543Smrg XkbDisableComputedAutoRepeats(keybd,key); 1992706f2543Smrg if (t == AutoRepeatModeOff) { 1993706f2543Smrg if (key == DO_ALL) 1994706f2543Smrg ctrl.autoRepeat = FALSE; 1995706f2543Smrg else 1996706f2543Smrg ctrl.autoRepeats[i] &= ~mask; 1997706f2543Smrg } 1998706f2543Smrg else if (t == AutoRepeatModeOn) { 1999706f2543Smrg if (key == DO_ALL) 2000706f2543Smrg ctrl.autoRepeat = TRUE; 2001706f2543Smrg else 2002706f2543Smrg ctrl.autoRepeats[i] |= mask; 2003706f2543Smrg } 2004706f2543Smrg else if (t == AutoRepeatModeDefault) { 2005706f2543Smrg if (key == DO_ALL) 2006706f2543Smrg ctrl.autoRepeat = defaultKeyboardControl.autoRepeat; 2007706f2543Smrg else 2008706f2543Smrg ctrl.autoRepeats[i] = 2009706f2543Smrg (ctrl.autoRepeats[i] & ~mask) | 2010706f2543Smrg (defaultKeyboardControl.autoRepeats[i] & mask); 2011706f2543Smrg } 2012706f2543Smrg else { 2013706f2543Smrg client->errorValue = t; 2014706f2543Smrg return BadValue; 2015706f2543Smrg } 2016706f2543Smrg break; 2017706f2543Smrg default: 2018706f2543Smrg client->errorValue = mask; 2019706f2543Smrg return BadValue; 2020706f2543Smrg } 2021706f2543Smrg } 2022706f2543Smrg keybd->kbdfeed->ctrl = ctrl; 2023706f2543Smrg 2024706f2543Smrg /* The XKB RepeatKeys control and core protocol global autorepeat */ 2025706f2543Smrg /* value are linked */ 2026706f2543Smrg XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat); 2027706f2543Smrg 2028706f2543Smrg return Success; 2029706f2543Smrg 2030706f2543Smrg#undef DO_ALL 2031706f2543Smrg} 2032706f2543Smrg 2033706f2543Smrg/** 2034706f2543Smrg * Changes kbd control on the ClientPointer and all attached SDs. 2035706f2543Smrg */ 2036706f2543Smrgint 2037706f2543SmrgProcChangeKeyboardControl (ClientPtr client) 2038706f2543Smrg{ 2039706f2543Smrg XID *vlist; 2040706f2543Smrg BITS32 vmask; 2041706f2543Smrg int ret = Success, error = Success; 2042706f2543Smrg DeviceIntPtr pDev = NULL, keyboard; 2043706f2543Smrg REQUEST(xChangeKeyboardControlReq); 2044706f2543Smrg 2045706f2543Smrg REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); 2046706f2543Smrg 2047706f2543Smrg vmask = stuff->mask; 2048706f2543Smrg vlist = (XID *)&stuff[1]; 2049706f2543Smrg 2050706f2543Smrg if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask)) 2051706f2543Smrg return BadLength; 2052706f2543Smrg 2053706f2543Smrg keyboard = PickKeyboard(client); 2054706f2543Smrg 2055706f2543Smrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 2056706f2543Smrg if ((pDev == keyboard || 2057706f2543Smrg (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard)) 2058706f2543Smrg && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { 2059706f2543Smrg ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); 2060706f2543Smrg if (ret != Success) 2061706f2543Smrg return ret; 2062706f2543Smrg } 2063706f2543Smrg } 2064706f2543Smrg 2065706f2543Smrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 2066706f2543Smrg if ((pDev == keyboard || 2067706f2543Smrg (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard)) 2068706f2543Smrg && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { 2069706f2543Smrg ret = DoChangeKeyboardControl(client, pDev, vlist, vmask); 2070706f2543Smrg if (ret != Success) 2071706f2543Smrg error = ret; 2072706f2543Smrg } 2073706f2543Smrg } 2074706f2543Smrg 2075706f2543Smrg return error; 2076706f2543Smrg} 2077706f2543Smrg 2078706f2543Smrgint 2079706f2543SmrgProcGetKeyboardControl (ClientPtr client) 2080706f2543Smrg{ 2081706f2543Smrg int rc, i; 2082706f2543Smrg DeviceIntPtr kbd = PickKeyboard(client); 2083706f2543Smrg KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl; 2084706f2543Smrg xGetKeyboardControlReply rep; 2085706f2543Smrg REQUEST_SIZE_MATCH(xReq); 2086706f2543Smrg 2087706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); 2088706f2543Smrg if (rc != Success) 2089706f2543Smrg return rc; 2090706f2543Smrg 2091706f2543Smrg rep.type = X_Reply; 2092706f2543Smrg rep.length = 5; 2093706f2543Smrg rep.sequenceNumber = client->sequence; 2094706f2543Smrg rep.globalAutoRepeat = ctrl->autoRepeat; 2095706f2543Smrg rep.keyClickPercent = ctrl->click; 2096706f2543Smrg rep.bellPercent = ctrl->bell; 2097706f2543Smrg rep.bellPitch = ctrl->bell_pitch; 2098706f2543Smrg rep.bellDuration = ctrl->bell_duration; 2099706f2543Smrg rep.ledMask = ctrl->leds; 2100706f2543Smrg for (i = 0; i < 32; i++) 2101706f2543Smrg rep.map[i] = ctrl->autoRepeats[i]; 2102706f2543Smrg WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); 2103706f2543Smrg return Success; 2104706f2543Smrg} 2105706f2543Smrg 2106706f2543Smrgint 2107706f2543SmrgProcBell(ClientPtr client) 2108706f2543Smrg{ 2109706f2543Smrg DeviceIntPtr dev, keybd = PickKeyboard(client); 2110706f2543Smrg int base = keybd->kbdfeed->ctrl.bell; 2111706f2543Smrg int newpercent; 2112706f2543Smrg int rc; 2113706f2543Smrg REQUEST(xBellReq); 2114706f2543Smrg REQUEST_SIZE_MATCH(xBellReq); 2115706f2543Smrg 2116706f2543Smrg if (stuff->percent < -100 || stuff->percent > 100) { 2117706f2543Smrg client->errorValue = stuff->percent; 2118706f2543Smrg return BadValue; 2119706f2543Smrg } 2120706f2543Smrg 2121706f2543Smrg newpercent = (base * stuff->percent) / 100; 2122706f2543Smrg if (stuff->percent < 0) 2123706f2543Smrg newpercent = base + newpercent; 2124706f2543Smrg else 2125706f2543Smrg newpercent = base - newpercent + stuff->percent; 2126706f2543Smrg 2127706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) { 2128706f2543Smrg if ((dev == keybd || 2129706f2543Smrg (!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) && 2130706f2543Smrg dev->kbdfeed && dev->kbdfeed->BellProc) { 2131706f2543Smrg 2132706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess); 2133706f2543Smrg if (rc != Success) 2134706f2543Smrg return rc; 2135706f2543Smrg XkbHandleBell(FALSE, FALSE, dev, newpercent, 2136706f2543Smrg &dev->kbdfeed->ctrl, 0, None, NULL, client); 2137706f2543Smrg } 2138706f2543Smrg } 2139706f2543Smrg 2140706f2543Smrg return Success; 2141706f2543Smrg} 2142706f2543Smrg 2143706f2543Smrgint 2144706f2543SmrgProcChangePointerControl(ClientPtr client) 2145706f2543Smrg{ 2146706f2543Smrg DeviceIntPtr dev, mouse = PickPointer(client); 2147706f2543Smrg PtrCtrl ctrl; /* might get BadValue part way through */ 2148706f2543Smrg int rc; 2149706f2543Smrg REQUEST(xChangePointerControlReq); 2150706f2543Smrg REQUEST_SIZE_MATCH(xChangePointerControlReq); 2151706f2543Smrg 2152706f2543Smrg ctrl = mouse->ptrfeed->ctrl; 2153706f2543Smrg if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) { 2154706f2543Smrg client->errorValue = stuff->doAccel; 2155706f2543Smrg return BadValue; 2156706f2543Smrg } 2157706f2543Smrg if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) { 2158706f2543Smrg client->errorValue = stuff->doThresh; 2159706f2543Smrg return BadValue; 2160706f2543Smrg } 2161706f2543Smrg if (stuff->doAccel) { 2162706f2543Smrg if (stuff->accelNum == -1) { 2163706f2543Smrg ctrl.num = defaultPointerControl.num; 2164706f2543Smrg } 2165706f2543Smrg else if (stuff->accelNum < 0) { 2166706f2543Smrg client->errorValue = stuff->accelNum; 2167706f2543Smrg return BadValue; 2168706f2543Smrg } 2169706f2543Smrg else { 2170706f2543Smrg ctrl.num = stuff->accelNum; 2171706f2543Smrg } 2172706f2543Smrg 2173706f2543Smrg if (stuff->accelDenum == -1) { 2174706f2543Smrg ctrl.den = defaultPointerControl.den; 2175706f2543Smrg } 2176706f2543Smrg else if (stuff->accelDenum <= 0) { 2177706f2543Smrg client->errorValue = stuff->accelDenum; 2178706f2543Smrg return BadValue; 2179706f2543Smrg } 2180706f2543Smrg else { 2181706f2543Smrg ctrl.den = stuff->accelDenum; 2182706f2543Smrg } 2183706f2543Smrg } 2184706f2543Smrg if (stuff->doThresh) { 2185706f2543Smrg if (stuff->threshold == -1) { 2186706f2543Smrg ctrl.threshold = defaultPointerControl.threshold; 2187706f2543Smrg } 2188706f2543Smrg else if (stuff->threshold < 0) { 2189706f2543Smrg client->errorValue = stuff->threshold; 2190706f2543Smrg return BadValue; 2191706f2543Smrg } 2192706f2543Smrg else { 2193706f2543Smrg ctrl.threshold = stuff->threshold; 2194706f2543Smrg } 2195706f2543Smrg } 2196706f2543Smrg 2197706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) { 2198706f2543Smrg if ((dev == mouse || 2199706f2543Smrg (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) && 2200706f2543Smrg dev->ptrfeed) { 2201706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); 2202706f2543Smrg if (rc != Success) 2203706f2543Smrg return rc; 2204706f2543Smrg } 2205706f2543Smrg } 2206706f2543Smrg 2207706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) { 2208706f2543Smrg if ((dev == mouse || 2209706f2543Smrg (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) && 2210706f2543Smrg dev->ptrfeed) { 2211706f2543Smrg dev->ptrfeed->ctrl = ctrl; 2212706f2543Smrg } 2213706f2543Smrg } 2214706f2543Smrg 2215706f2543Smrg return Success; 2216706f2543Smrg} 2217706f2543Smrg 2218706f2543Smrgint 2219706f2543SmrgProcGetPointerControl(ClientPtr client) 2220706f2543Smrg{ 2221706f2543Smrg DeviceIntPtr ptr = PickPointer(client); 2222706f2543Smrg PtrCtrl *ctrl = &ptr->ptrfeed->ctrl; 2223706f2543Smrg xGetPointerControlReply rep; 2224706f2543Smrg int rc; 2225706f2543Smrg REQUEST_SIZE_MATCH(xReq); 2226706f2543Smrg 2227706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); 2228706f2543Smrg if (rc != Success) 2229706f2543Smrg return rc; 2230706f2543Smrg 2231706f2543Smrg rep.type = X_Reply; 2232706f2543Smrg rep.length = 0; 2233706f2543Smrg rep.sequenceNumber = client->sequence; 2234706f2543Smrg rep.threshold = ctrl->threshold; 2235706f2543Smrg rep.accelNumerator = ctrl->num; 2236706f2543Smrg rep.accelDenominator = ctrl->den; 2237706f2543Smrg WriteReplyToClient(client, sizeof(xGenericReply), &rep); 2238706f2543Smrg return Success; 2239706f2543Smrg} 2240706f2543Smrg 2241706f2543Smrgvoid 2242706f2543SmrgMaybeStopHint(DeviceIntPtr dev, ClientPtr client) 2243706f2543Smrg{ 2244706f2543Smrg GrabPtr grab = dev->deviceGrab.grab; 2245706f2543Smrg 2246706f2543Smrg if ((grab && SameClient(grab, client) && 2247706f2543Smrg ((grab->eventMask & PointerMotionHintMask) || 2248706f2543Smrg (grab->ownerEvents && 2249706f2543Smrg (EventMaskForClient(dev->valuator->motionHintWindow, client) & 2250706f2543Smrg PointerMotionHintMask)))) || 2251706f2543Smrg (!grab && 2252706f2543Smrg (EventMaskForClient(dev->valuator->motionHintWindow, client) & 2253706f2543Smrg PointerMotionHintMask))) 2254706f2543Smrg dev->valuator->motionHintWindow = NullWindow; 2255706f2543Smrg} 2256706f2543Smrg 2257706f2543Smrgint 2258706f2543SmrgProcGetMotionEvents(ClientPtr client) 2259706f2543Smrg{ 2260706f2543Smrg WindowPtr pWin; 2261706f2543Smrg xTimecoord * coords = (xTimecoord *) NULL; 2262706f2543Smrg xGetMotionEventsReply rep; 2263706f2543Smrg int i, count, xmin, xmax, ymin, ymax, rc; 2264706f2543Smrg unsigned long nEvents; 2265706f2543Smrg DeviceIntPtr mouse = PickPointer(client); 2266706f2543Smrg TimeStamp start, stop; 2267706f2543Smrg REQUEST(xGetMotionEventsReq); 2268706f2543Smrg REQUEST_SIZE_MATCH(xGetMotionEventsReq); 2269706f2543Smrg 2270706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2271706f2543Smrg if (rc != Success) 2272706f2543Smrg return rc; 2273706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 2274706f2543Smrg if (rc != Success) 2275706f2543Smrg return rc; 2276706f2543Smrg 2277706f2543Smrg if (mouse->valuator->motionHintWindow) 2278706f2543Smrg MaybeStopHint(mouse, client); 2279706f2543Smrg rep.type = X_Reply; 2280706f2543Smrg rep.sequenceNumber = client->sequence; 2281706f2543Smrg nEvents = 0; 2282706f2543Smrg start = ClientTimeToServerTime(stuff->start); 2283706f2543Smrg stop = ClientTimeToServerTime(stuff->stop); 2284706f2543Smrg if ((CompareTimeStamps(start, stop) != LATER) && 2285706f2543Smrg (CompareTimeStamps(start, currentTime) != LATER) && 2286706f2543Smrg mouse->valuator->numMotionEvents) 2287706f2543Smrg { 2288706f2543Smrg if (CompareTimeStamps(stop, currentTime) == LATER) 2289706f2543Smrg stop = currentTime; 2290706f2543Smrg count = GetMotionHistory(mouse, &coords, start.milliseconds, 2291706f2543Smrg stop.milliseconds, pWin->drawable.pScreen, 2292706f2543Smrg TRUE); 2293706f2543Smrg xmin = pWin->drawable.x - wBorderWidth (pWin); 2294706f2543Smrg xmax = pWin->drawable.x + (int)pWin->drawable.width + 2295706f2543Smrg wBorderWidth (pWin); 2296706f2543Smrg ymin = pWin->drawable.y - wBorderWidth (pWin); 2297706f2543Smrg ymax = pWin->drawable.y + (int)pWin->drawable.height + 2298706f2543Smrg wBorderWidth (pWin); 2299706f2543Smrg for (i = 0; i < count; i++) 2300706f2543Smrg if ((xmin <= coords[i].x) && (coords[i].x < xmax) && 2301706f2543Smrg (ymin <= coords[i].y) && (coords[i].y < ymax)) 2302706f2543Smrg { 2303706f2543Smrg coords[nEvents].time = coords[i].time; 2304706f2543Smrg coords[nEvents].x = coords[i].x - pWin->drawable.x; 2305706f2543Smrg coords[nEvents].y = coords[i].y - pWin->drawable.y; 2306706f2543Smrg nEvents++; 2307706f2543Smrg } 2308706f2543Smrg } 2309706f2543Smrg rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord)); 2310706f2543Smrg rep.nEvents = nEvents; 2311706f2543Smrg WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); 2312706f2543Smrg if (nEvents) 2313706f2543Smrg { 2314706f2543Smrg client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite; 2315706f2543Smrg WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord), 2316706f2543Smrg (char *)coords); 2317706f2543Smrg } 2318706f2543Smrg free(coords); 2319706f2543Smrg return Success; 2320706f2543Smrg} 2321706f2543Smrg 2322706f2543Smrgint 2323706f2543SmrgProcQueryKeymap(ClientPtr client) 2324706f2543Smrg{ 2325706f2543Smrg xQueryKeymapReply rep; 2326706f2543Smrg int rc, i; 2327706f2543Smrg DeviceIntPtr keybd = PickKeyboard(client); 2328706f2543Smrg CARD8 *down = keybd->key->down; 2329706f2543Smrg 2330706f2543Smrg REQUEST_SIZE_MATCH(xReq); 2331706f2543Smrg rep.type = X_Reply; 2332706f2543Smrg rep.sequenceNumber = client->sequence; 2333706f2543Smrg rep.length = 2; 2334706f2543Smrg 2335706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); 2336706f2543Smrg if (rc != Success && rc != BadAccess) 2337706f2543Smrg return rc; 2338706f2543Smrg 2339706f2543Smrg for (i = 0; i<32; i++) 2340706f2543Smrg rep.map[i] = down[i]; 2341706f2543Smrg 2342706f2543Smrg if (rc == BadAccess) 2343706f2543Smrg memset(rep.map, 0, 32); 2344706f2543Smrg 2345706f2543Smrg WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); 2346706f2543Smrg 2347706f2543Smrg return Success; 2348706f2543Smrg} 2349706f2543Smrg 2350706f2543Smrg 2351706f2543Smrg/** 2352706f2543Smrg * Recalculate the number of buttons for the master device. The number of 2353706f2543Smrg * buttons on the master device is equal to the number of buttons on the 2354706f2543Smrg * slave device with the highest number of buttons. 2355706f2543Smrg */ 2356706f2543Smrgstatic void 2357706f2543SmrgRecalculateMasterButtons(DeviceIntPtr slave) 2358706f2543Smrg{ 2359706f2543Smrg DeviceIntPtr dev, master; 2360706f2543Smrg int maxbuttons = 0; 2361706f2543Smrg 2362706f2543Smrg if (!slave->button || IsMaster(slave)) 2363706f2543Smrg return; 2364706f2543Smrg 2365706f2543Smrg master = GetMaster(slave, MASTER_POINTER); 2366706f2543Smrg if (!master) 2367706f2543Smrg return; 2368706f2543Smrg 2369706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) 2370706f2543Smrg { 2371706f2543Smrg if (IsMaster(dev) || 2372706f2543Smrg dev->u.master != master || 2373706f2543Smrg !dev->button) 2374706f2543Smrg continue; 2375706f2543Smrg 2376706f2543Smrg maxbuttons = max(maxbuttons, dev->button->numButtons); 2377706f2543Smrg } 2378706f2543Smrg 2379706f2543Smrg if (master->button && master->button->numButtons != maxbuttons) 2380706f2543Smrg { 2381706f2543Smrg int i; 2382706f2543Smrg DeviceChangedEvent event; 2383706f2543Smrg 2384706f2543Smrg memset(&event, 0, sizeof(event)); 2385706f2543Smrg 2386706f2543Smrg master->button->numButtons = maxbuttons; 2387706f2543Smrg 2388706f2543Smrg event.header = ET_Internal; 2389706f2543Smrg event.type = ET_DeviceChanged; 2390706f2543Smrg event.time = GetTimeInMillis(); 2391706f2543Smrg event.deviceid = master->id; 2392706f2543Smrg event.flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE; 2393706f2543Smrg event.buttons.num_buttons = maxbuttons; 2394706f2543Smrg memcpy(&event.buttons.names, master->button->labels, maxbuttons * 2395706f2543Smrg sizeof(Atom)); 2396706f2543Smrg 2397706f2543Smrg if (master->valuator) 2398706f2543Smrg { 2399706f2543Smrg event.num_valuators = master->valuator->numAxes; 2400706f2543Smrg for (i = 0; i < event.num_valuators; i++) 2401706f2543Smrg { 2402706f2543Smrg event.valuators[i].min = master->valuator->axes[i].min_value; 2403706f2543Smrg event.valuators[i].max = master->valuator->axes[i].max_value; 2404706f2543Smrg event.valuators[i].resolution = master->valuator->axes[i].resolution; 2405706f2543Smrg event.valuators[i].mode = master->valuator->axes[i].mode; 2406706f2543Smrg event.valuators[i].name = master->valuator->axes[i].label; 2407706f2543Smrg } 2408706f2543Smrg } 2409706f2543Smrg 2410706f2543Smrg if (master->key) 2411706f2543Smrg { 2412706f2543Smrg event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code; 2413706f2543Smrg event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code; 2414706f2543Smrg } 2415706f2543Smrg 2416706f2543Smrg XISendDeviceChangedEvent(master, master, &event); 2417706f2543Smrg } 2418706f2543Smrg} 2419706f2543Smrg 2420706f2543Smrg/** 2421706f2543Smrg * Generate release events for all keys/button currently down on this 2422706f2543Smrg * device. 2423706f2543Smrg */ 2424706f2543Smrgvoid 2425706f2543SmrgReleaseButtonsAndKeys(DeviceIntPtr dev) 2426706f2543Smrg{ 2427706f2543Smrg EventListPtr eventlist = InitEventList(GetMaximumEventsNum()); 2428706f2543Smrg ButtonClassPtr b = dev->button; 2429706f2543Smrg KeyClassPtr k = dev->key; 2430706f2543Smrg int i, j, nevents; 2431706f2543Smrg 2432706f2543Smrg if (!eventlist) /* no release events for you */ 2433706f2543Smrg return; 2434706f2543Smrg 2435706f2543Smrg /* Release all buttons */ 2436706f2543Smrg for (i = 0; b && i < b->numButtons; i++) 2437706f2543Smrg { 2438706f2543Smrg if (BitIsOn(b->down, i)) 2439706f2543Smrg { 2440706f2543Smrg nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL); 2441706f2543Smrg for (j = 0; j < nevents; j++) 2442706f2543Smrg mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); 2443706f2543Smrg } 2444706f2543Smrg } 2445706f2543Smrg 2446706f2543Smrg /* Release all keys */ 2447706f2543Smrg for (i = 0; k && i < MAP_LENGTH; i++) 2448706f2543Smrg { 2449706f2543Smrg if (BitIsOn(k->down, i)) 2450706f2543Smrg { 2451706f2543Smrg nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i); 2452706f2543Smrg for (j = 0; j < nevents; j++) 2453706f2543Smrg mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); 2454706f2543Smrg } 2455706f2543Smrg } 2456706f2543Smrg 2457706f2543Smrg FreeEventList(eventlist, GetMaximumEventsNum()); 2458706f2543Smrg} 2459706f2543Smrg 2460706f2543Smrg/** 2461706f2543Smrg * Attach device 'dev' to device 'master'. 2462706f2543Smrg * Client is set to the client that issued the request, or NULL if it comes 2463706f2543Smrg * from some internal automatic pairing. 2464706f2543Smrg * 2465706f2543Smrg * Master may be NULL to set the device floating. 2466706f2543Smrg * 2467706f2543Smrg * We don't allow multi-layer hierarchies right now. You can't attach a slave 2468706f2543Smrg * to another slave. 2469706f2543Smrg */ 2470706f2543Smrgint 2471706f2543SmrgAttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) 2472706f2543Smrg{ 2473706f2543Smrg ScreenPtr screen; 2474706f2543Smrg DeviceIntPtr oldmaster; 2475706f2543Smrg if (!dev || IsMaster(dev)) 2476706f2543Smrg return BadDevice; 2477706f2543Smrg 2478706f2543Smrg if (master && !IsMaster(master)) /* can't attach to slaves */ 2479706f2543Smrg return BadDevice; 2480706f2543Smrg 2481706f2543Smrg /* set from floating to floating? */ 2482706f2543Smrg if (!dev->u.master && !master && dev->enabled) 2483706f2543Smrg return Success; 2484706f2543Smrg 2485706f2543Smrg /* free the existing sprite. */ 2486706f2543Smrg if (!dev->u.master && dev->spriteInfo->paired == dev) 2487706f2543Smrg { 2488706f2543Smrg screen = miPointerGetScreen(dev); 2489706f2543Smrg screen->DeviceCursorCleanup(dev, screen); 2490706f2543Smrg free(dev->spriteInfo->sprite); 2491706f2543Smrg } 2492706f2543Smrg 2493706f2543Smrg oldmaster = dev->u.master; 2494706f2543Smrg dev->u.master = master; 2495706f2543Smrg 2496706f2543Smrg /* If device is set to floating, we need to create a sprite for it, 2497706f2543Smrg * otherwise things go bad. However, we don't want to render the cursor, 2498706f2543Smrg * so we reset spriteOwner. 2499706f2543Smrg * Sprite has to be forced to NULL first, otherwise InitializeSprite won't 2500706f2543Smrg * alloc new memory but overwrite the previous one. 2501706f2543Smrg */ 2502706f2543Smrg if (!master) 2503706f2543Smrg { 2504706f2543Smrg WindowPtr currentRoot; 2505706f2543Smrg 2506706f2543Smrg if (dev->spriteInfo->sprite) 2507706f2543Smrg currentRoot = GetCurrentRootWindow(dev); 2508706f2543Smrg else /* new device auto-set to floating */ 2509706f2543Smrg currentRoot = screenInfo.screens[0]->root; 2510706f2543Smrg 2511706f2543Smrg /* we need to init a fake sprite */ 2512706f2543Smrg screen = currentRoot->drawable.pScreen; 2513706f2543Smrg screen->DeviceCursorInitialize(dev, screen); 2514706f2543Smrg dev->spriteInfo->sprite = NULL; 2515706f2543Smrg InitializeSprite(dev, currentRoot); 2516706f2543Smrg dev->spriteInfo->spriteOwner = FALSE; 2517706f2543Smrg dev->spriteInfo->paired = dev; 2518706f2543Smrg } else 2519706f2543Smrg { 2520706f2543Smrg dev->spriteInfo->sprite = master->spriteInfo->sprite; 2521706f2543Smrg dev->spriteInfo->paired = master; 2522706f2543Smrg dev->spriteInfo->spriteOwner = FALSE; 2523706f2543Smrg 2524706f2543Smrg RecalculateMasterButtons(master); 2525706f2543Smrg } 2526706f2543Smrg 2527706f2543Smrg /* XXX: in theory, the MD should change back to its old, original 2528706f2543Smrg * classes when the last SD is detached. Thanks to the XTEST devices, 2529706f2543Smrg * we'll always have an SD attached until the MD is removed. 2530706f2543Smrg * So let's not worry about that. 2531706f2543Smrg */ 2532706f2543Smrg 2533706f2543Smrg return Success; 2534706f2543Smrg} 2535706f2543Smrg 2536706f2543Smrg/** 2537706f2543Smrg * Return the device paired with the given device or NULL. 2538706f2543Smrg * Returns the device paired with the parent master if the given device is a 2539706f2543Smrg * slave device. 2540706f2543Smrg */ 2541706f2543SmrgDeviceIntPtr 2542706f2543SmrgGetPairedDevice(DeviceIntPtr dev) 2543706f2543Smrg{ 2544706f2543Smrg if (!IsMaster(dev) && dev->u.master) 2545706f2543Smrg dev = dev->u.master; 2546706f2543Smrg 2547706f2543Smrg return dev->spriteInfo->paired; 2548706f2543Smrg} 2549706f2543Smrg 2550706f2543Smrg 2551706f2543Smrg/** 2552706f2543Smrg * Returns the right master for the type of event needed. If the event is a 2553706f2543Smrg * keyboard event. 2554706f2543Smrg * This function may be called with a master device as argument. If so, the 2555706f2543Smrg * returned master is either the device itself or the paired master device. 2556706f2543Smrg * If dev is a floating slave device, NULL is returned. 2557706f2543Smrg * 2558706f2543Smrg * @type ::MASTER_KEYBOARD or ::MASTER_POINTER 2559706f2543Smrg */ 2560706f2543SmrgDeviceIntPtr 2561706f2543SmrgGetMaster(DeviceIntPtr dev, int which) 2562706f2543Smrg{ 2563706f2543Smrg DeviceIntPtr master; 2564706f2543Smrg 2565706f2543Smrg if (IsMaster(dev)) 2566706f2543Smrg master = dev; 2567706f2543Smrg else 2568706f2543Smrg master = dev->u.master; 2569706f2543Smrg 2570706f2543Smrg if (master) 2571706f2543Smrg { 2572706f2543Smrg if (which == MASTER_KEYBOARD) 2573706f2543Smrg { 2574706f2543Smrg if (master->type != MASTER_KEYBOARD) 2575706f2543Smrg master = GetPairedDevice(master); 2576706f2543Smrg } else 2577706f2543Smrg { 2578706f2543Smrg if (master->type != MASTER_POINTER) 2579706f2543Smrg master = GetPairedDevice(master); 2580706f2543Smrg } 2581706f2543Smrg } 2582706f2543Smrg 2583706f2543Smrg return master; 2584706f2543Smrg} 2585706f2543Smrg 2586706f2543Smrg/** 2587706f2543Smrg * Create a new device pair (== one pointer, one keyboard device). 2588706f2543Smrg * Only allocates the devices, you will need to call ActivateDevice() and 2589706f2543Smrg * EnableDevice() manually. 2590706f2543Smrg * Either a master or a slave device can be created depending on 2591706f2543Smrg * the value for master. 2592706f2543Smrg */ 2593706f2543Smrgint 2594706f2543SmrgAllocDevicePair (ClientPtr client, char* name, 2595706f2543Smrg DeviceIntPtr* ptr, 2596706f2543Smrg DeviceIntPtr* keybd, 2597706f2543Smrg DeviceProc ptr_proc, 2598706f2543Smrg DeviceProc keybd_proc, 2599706f2543Smrg Bool master) 2600706f2543Smrg{ 2601706f2543Smrg DeviceIntPtr pointer; 2602706f2543Smrg DeviceIntPtr keyboard; 2603706f2543Smrg *ptr = *keybd = NULL; 2604706f2543Smrg 2605706f2543Smrg pointer = AddInputDevice(client, ptr_proc, TRUE); 2606706f2543Smrg if (!pointer) 2607706f2543Smrg return BadAlloc; 2608706f2543Smrg 2609706f2543Smrg if (asprintf(&pointer->name, "%s pointer", name) == -1) { 2610706f2543Smrg pointer->name = NULL; 2611706f2543Smrg RemoveDevice(pointer, FALSE); 2612706f2543Smrg return BadAlloc; 2613706f2543Smrg } 2614706f2543Smrg 2615706f2543Smrg pointer->public.processInputProc = ProcessOtherEvent; 2616706f2543Smrg pointer->public.realInputProc = ProcessOtherEvent; 2617706f2543Smrg XkbSetExtension(pointer, ProcessPointerEvent); 2618706f2543Smrg pointer->deviceGrab.ActivateGrab = ActivatePointerGrab; 2619706f2543Smrg pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab; 2620706f2543Smrg pointer->coreEvents = TRUE; 2621706f2543Smrg pointer->spriteInfo->spriteOwner = TRUE; 2622706f2543Smrg 2623706f2543Smrg pointer->u.lastSlave = NULL; 2624706f2543Smrg pointer->last.slave = NULL; 2625706f2543Smrg pointer->type = (master) ? MASTER_POINTER : SLAVE; 2626706f2543Smrg 2627706f2543Smrg keyboard = AddInputDevice(client, keybd_proc, TRUE); 2628706f2543Smrg if (!keyboard) 2629706f2543Smrg { 2630706f2543Smrg RemoveDevice(pointer, FALSE); 2631706f2543Smrg return BadAlloc; 2632706f2543Smrg } 2633706f2543Smrg 2634706f2543Smrg if (asprintf(&keyboard->name, "%s keyboard", name) == -1) { 2635706f2543Smrg keyboard->name = NULL; 2636706f2543Smrg RemoveDevice(keyboard, FALSE); 2637706f2543Smrg RemoveDevice(pointer, FALSE); 2638706f2543Smrg return BadAlloc; 2639706f2543Smrg } 2640706f2543Smrg 2641706f2543Smrg keyboard->public.processInputProc = ProcessOtherEvent; 2642706f2543Smrg keyboard->public.realInputProc = ProcessOtherEvent; 2643706f2543Smrg XkbSetExtension(keyboard, ProcessKeyboardEvent); 2644706f2543Smrg keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab; 2645706f2543Smrg keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; 2646706f2543Smrg keyboard->coreEvents = TRUE; 2647706f2543Smrg keyboard->spriteInfo->spriteOwner = FALSE; 2648706f2543Smrg 2649706f2543Smrg keyboard->u.lastSlave = NULL; 2650706f2543Smrg keyboard->last.slave = NULL; 2651706f2543Smrg keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE; 2652706f2543Smrg 2653706f2543Smrg /* The ClassesRec stores the device classes currently not used. */ 2654706f2543Smrg pointer->unused_classes = calloc(1, sizeof(ClassesRec)); 2655706f2543Smrg keyboard->unused_classes = calloc(1, sizeof(ClassesRec)); 2656706f2543Smrg 2657706f2543Smrg *ptr = pointer; 2658706f2543Smrg *keybd = keyboard; 2659706f2543Smrg 2660706f2543Smrg return Success; 2661706f2543Smrg} 2662706f2543Smrg 2663706f2543Smrg/** 2664706f2543Smrg * Return Relative or Absolute for the device. 2665706f2543Smrg */ 2666706f2543Smrgint valuator_get_mode(DeviceIntPtr dev, int axis) 2667706f2543Smrg{ 2668706f2543Smrg return (dev->valuator->axes[axis].mode & DeviceMode); 2669706f2543Smrg} 2670706f2543Smrg 2671706f2543Smrg/** 2672706f2543Smrg * Set the given mode for the axis. If axis is VALUATOR_MODE_ALL_AXES, then 2673706f2543Smrg * set the mode for all axes. 2674706f2543Smrg */ 2675706f2543Smrgvoid valuator_set_mode(DeviceIntPtr dev, int axis, int mode) 2676706f2543Smrg{ 2677706f2543Smrg if (axis != VALUATOR_MODE_ALL_AXES) 2678706f2543Smrg dev->valuator->axes[axis].mode = mode; 2679706f2543Smrg else { 2680706f2543Smrg int i; 2681706f2543Smrg for (i = 0; i < dev->valuator->numAxes; i++) 2682706f2543Smrg dev->valuator->axes[i].mode = mode; 2683706f2543Smrg } 2684706f2543Smrg} 2685