devices.c 80.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/************************************************************

Copyright 1987, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.

Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.

                        All Rights Reserved

29
30
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
31
provided that the above copyright notice appear in all copies and that
32
both that copyright notice and this permission notice appear in
33
34
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
35
software without specific, written prior permission.
36
37
38
39
40
41
42
43
44
45
46

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

********************************************************/

47
48
49
50
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

51
#include <X11/X.h>
52
#include "misc.h"
53
#include "resource.h"
54
#include <X11/Xproto.h>
55
#include <X11/Xatom.h>
56
57
58
59
60
#include "windowstr.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
61
#include "ptrveloc.h"
Daniel Stone's avatar
Daniel Stone committed
62
#include "xkbsrv.h"
63
#include "privates.h"
64
#include "xace.h"
65
#include "mi.h"
66

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
67
68
69
#include "dispatch.h"
#include "swaprep.h"
#include "dixevents.h"
70
#include "mipointer.h"
71
#include "eventstr.h"
72
#include "dixgrabs.h"
73

74
#include <X11/extensions/XI.h>
75
#include <X11/extensions/XI2.h>
Daniel Stone's avatar
Daniel Stone committed
76
#include <X11/extensions/XIproto.h>
77
78
#include <math.h>
#include <pixman.h>
Daniel Stone's avatar
Daniel Stone committed
79
#include "exglobals.h"
Daniel Stone's avatar
Daniel Stone committed
80
#include "exevents.h"
81
#include "xiquerydevice.h"      /* for SizeDeviceClasses */
82
#include "xiproperty.h"
83
#include "enterleave.h"         /* for EnterWindow() */
84
#include "xserver-properties.h"
85
#include "xichangehierarchy.h"  /* For XISendDeviceHierarchyEvent */
86
#include "syncsrv.h"
Daniel Stone's avatar
Daniel Stone committed
87

88
89
90
91
/** @file
 * This file handles input device-related stuff.
 */

92
static void RecalculateMasterButtons(DeviceIntPtr slave);
93

94
static void
95
DeviceSetTransform(DeviceIntPtr dev, float *transform_data)
96
97
{
    struct pixman_f_transform scale;
98
    struct pixman_f_transform transform;
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    double sx, sy;
    int x, y;

    /**
     * calculate combined transformation matrix:
     *
     * M = InvScale * Transform * Scale
     *
     * So we can later transform points using M * p
     *
     * Where:
     *  Scale scales coordinates into 0..1 range
     *  Transform is the user supplied (affine) transform
     *  InvScale scales coordinates back up into their native range
     */
114
115
    sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value + 1;
    sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value + 1;
116
117
118
119
120
121
122

    /* invscale */
    pixman_f_transform_init_scale(&scale, sx, sy);
    scale.m[0][2] = dev->valuator->axes[0].min_value;
    scale.m[1][2] = dev->valuator->axes[1].min_value;

    /* transform */
123
124
    for (y = 0; y < 3; y++)
        for (x = 0; x < 3; x++)
125
            transform.m[y][x] = *transform_data++;
126

127
    pixman_f_transform_multiply(&dev->scale_and_transform, &scale, &transform);
128
129
130
131
132
133

    /* scale */
    pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy);
    scale.m[0][2] = -dev->valuator->axes[0].min_value / sx;
    scale.m[1][2] = -dev->valuator->axes[1].min_value / sy;

134
135
136
137
138
139
    pixman_f_transform_multiply(&dev->scale_and_transform, &dev->scale_and_transform, &scale);

    /* remove translation component for relative movements */
    dev->relative_transform = transform;
    dev->relative_transform.m[0][2] = 0;
    dev->relative_transform.m[1][2] = 0;
140
141
}

142
143
144
/**
 * DIX property handler.
 */
145
static int
146
147
DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
                  BOOL checkonly)
148
{
149
    if (property == XIGetKnownProperty(XI_PROP_ENABLED)) {
150
        if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1)
151
            return BadValue;
152

153
154
155
156
157
        /* Don't allow disabling of VCP/VCK or XTest devices */
        if ((dev == inputInfo.pointer ||
             dev == inputInfo.keyboard ||
             IsXTestDevice(dev, NULL))
            &&!(*(CARD8 *) prop->data))
158
159
            return BadAccess;

160
161
        if (!checkonly) {
            if ((*((CARD8 *) prop->data)) && !dev->enabled)
162
                EnableDevice(dev, TRUE);
163
            else if (!(*((CARD8 *) prop->data)) && dev->enabled)
164
                DisableDevice(dev, TRUE);
165
        }
166
167
168
    }
    else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM)) {
        float *f = (float *) prop->data;
169
170
171
172
173
174
        int i;

        if (prop->format != 32 || prop->size != 9 ||
            prop->type != XIGetKnownProperty(XATOM_FLOAT))
            return BadValue;

175
        for (i = 0; i < 9; i++)
176
177
178
            if (!isfinite(f[i]))
                return BadValue;

Peter Hutterer's avatar
Peter Hutterer committed
179
180
        if (!dev->valuator)
            return BadMatch;
181

182
183
        if (!checkonly)
            DeviceSetTransform(dev, f);
184
185
    }

186
    return Success;
187
188
}

189
190
191
192
/* Pair the keyboard to the pointer device. Keyboard events will follow the
 * pointer sprite. Only applicable for master devices.
 */
static int
193
PairDevices(DeviceIntPtr ptr, DeviceIntPtr kbd)
194
195
196
197
198
{
    if (!ptr)
        return BadDevice;

    /* Don't allow pairing for slave devices */
199
    if (!IsMaster(ptr) || !IsMaster(kbd))
200
201
202
203
204
        return BadDevice;

    if (ptr->spriteInfo->paired)
        return BadDevice;

205
    if (kbd->spriteInfo->spriteOwner) {
206
        free(kbd->spriteInfo->sprite);
207
208
209
210
211
212
213
214
215
216
        kbd->spriteInfo->sprite = NULL;
        kbd->spriteInfo->spriteOwner = FALSE;
    }

    kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
    kbd->spriteInfo->paired = ptr;
    ptr->spriteInfo->paired = kbd;
    return Success;
}

217
218
219
220
221
222
223
/**
 * Find and return the next unpaired MD pointer device.
 */
static DeviceIntPtr
NextFreePointerDevice(void)
{
    DeviceIntPtr dev;
224

225
    for (dev = inputInfo.devices; dev; dev = dev->next)
226
        if (IsMaster(dev) &&
227
            dev->spriteInfo->spriteOwner && !dev->spriteInfo->paired)
228
229
230
            return dev;
    return NULL;
}
231

232
233
234
235
236
237
238
/**
 * Create a new input device and init it to sane values. The device is added
 * to the server's off_devices list.
 *
 * @param deviceProc Callback for device control function (switch dev on/off).
 * @return The newly created device.
 */
239
DeviceIntPtr
240
AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
241
{
242
    DeviceIntPtr dev, *prev;    /* not a typo */
243
244
    DeviceIntPtr devtmp;
    int devid;
245
    char devind[MAXDEVICES];
246
    BOOL enabled;
247
    float transform[9];
248

249
    /* Find next available id, 0 and 1 are reserved */
250
    memset(devind, 0, sizeof(char) * MAXDEVICES);
251
    for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next)
252
        devind[devtmp->id]++;
253
    for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next)
254
255
        devind[devtmp->id]++;
    for (devid = 2; devid < MAXDEVICES && devind[devid]; devid++);
256

257
    if (devid >= MAXDEVICES)
258
        return (DeviceIntPtr) NULL;
259
260
261
262
263
264
265
266
267
268
269
    dev = calloc(1,
                 sizeof(DeviceIntRec) +
                 sizeof(SpriteInfoRec));
    if (!dev)
        return (DeviceIntPtr) NULL;

    if (!dixAllocatePrivates(&dev->devPrivates, PRIVATE_DEVICE)) {
        free(dev);
        return NULL;
    }

270
    dev->last.scroll = NULL;
271
    dev->last.touches = NULL;
272
    dev->id = devid;
273
274
    dev->public.processInputProc = ProcessOtherEvent;
    dev->public.realInputProc = ProcessOtherEvent;
275
276
277
    dev->public.enqueueInputProc = EnqueueEvent;
    dev->deviceProc = deviceProc;
    dev->startup = autoStart;
278
279

    /* device grab defaults */
280
    UpdateCurrentTimeIf();
281
    dev->deviceGrab.grabTime = currentTime;
282
283
    dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
    dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
284
    dev->deviceGrab.sync.event = calloc(1, sizeof(InternalEvent));
Adam Jackson's avatar
Adam Jackson committed
285

286
    XkbSetExtension(dev, ProcessKeyboardEvent);
287

Daniel Stone's avatar
Daniel Stone committed
288
    dev->coreEvents = TRUE;
289

290
    /* sprite defaults */
291
    dev->spriteInfo = (SpriteInfoPtr) &dev[1];
292

293
294
    /*  security creation/labeling check
     */
295
    if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
296
        dixFreePrivates(dev->devPrivates, PRIVATE_DEVICE);
297
298
        free(dev);
        return NULL;
299
300
301
302
    }

    inputInfo.numDevices++;

303
    for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next);
304
305
306
    *prev = dev;
    dev->next = NULL;

307
    enabled = FALSE;
308
    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
309
310
311
                           XA_INTEGER, 8, PropModeReplace, 1, &enabled, FALSE);
    XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED),
                                 FALSE);
312
313
314
315

    /* unity matrix */
    memset(transform, 0, sizeof(transform));
    transform[0] = transform[4] = transform[8] = 1.0f;
316
317
318
319
    dev->relative_transform.m[0][0] = 1.0;
    dev->relative_transform.m[1][1] = 1.0;
    dev->relative_transform.m[2][2] = 1.0;
    dev->scale_and_transform = dev->relative_transform;
320
321
322
323
324
325
326

    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
                           XIGetKnownProperty(XATOM_FLOAT), 32,
                           PropModeReplace, 9, transform, FALSE);
    XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
                                 FALSE);

327
    XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL);
328

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
329
    return dev;
330
331
}

332
void
333
334
SendDevicePresenceEvent(int deviceid, int type)
{
335
    DeviceIntRec dummyDev = { .id =  XIAllDevices };
336
337
338
339
340
341
342
    devicePresenceNotify ev;

    UpdateCurrentTimeIf();
    ev.type = DevicePresenceNotify;
    ev.time = currentTime.milliseconds;
    ev.devchange = type;
    ev.deviceid = deviceid;
343

344
    SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
345
                          (xEvent *) &ev, 1);
346
347
}

348
/**
349
 * Enable the device through the driver, add the device to the device list.
350
 * Switch device ON through the driver and push it onto the global device
351
352
 * list. Initialize the DIX sprite or pair the device. All clients are
 * notified about the device being enabled.
353
 *
354
355
 * A master pointer device needs to be enabled before a master keyboard
 * device.
356
 *
357
 * @param The device to be enabled.
358
 * @param sendevent True if an XI2 event should be sent.
359
 * @return TRUE on success or FALSE otherwise.
360
 */
361
Bool
362
EnableDevice(DeviceIntPtr dev, BOOL sendevent)
363
{
364
    DeviceIntPtr *prev;
Daniel Stone's avatar
Daniel Stone committed
365
    int ret;
366
    DeviceIntPtr other;
367
    BOOL enabled;
368
    int flags[MAXDEVICES] = { 0 };
369
370

    for (prev = &inputInfo.off_devices;
371
         *prev && (*prev != dev); prev = &(*prev)->next);
372

373
374
    if (!dev->spriteInfo->sprite) {
        if (IsMaster(dev)) {
375
            /* Sprites appear on first root window, so we can hardcode it */
376
            if (dev->spriteInfo->spriteOwner) {
377
                InitializeSprite(dev, screenInfo.screens[0]->root);
378
                /* mode doesn't matter */
379
                EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor);
380
            }
381
382
383
384
            else {
                other = NextFreePointerDevice();
                BUG_RETURN_VAL_MSG(other == NULL, FALSE,
                                   "[dix] cannot find pointer to pair with.\n");
385
                PairDevices(other, dev);
386
            }
387
388
        }
        else {
389
            if (dev->coreEvents)
390
                other = (IsPointerDevice(dev)) ? inputInfo.pointer:
391
392
                    inputInfo.keyboard;
            else
393
                other = NULL;   /* auto-float non-core devices */
394
395
            AttachDevice(NULL, dev, other);
        }
396
    }
397

Keith Packard's avatar
Keith Packard committed
398
    input_lock();
399
    if ((*prev != dev) || !dev->inited ||
400
        ((ret = (*dev->deviceProc) (dev, DEVICE_ON)) != Success)) {
401
        ErrorF("[dix] couldn't enable device %d\n", dev->id);
Keith Packard's avatar
Keith Packard committed
402
        input_unlock();
403
        return FALSE;
Daniel Stone's avatar
Daniel Stone committed
404
    }
Daniel Stone's avatar
Daniel Stone committed
405
    dev->enabled = TRUE;
406
    *prev = dev->next;
407

408
    for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next);
409
410
    *prev = dev;
    dev->next = NULL;
Keith Packard's avatar
Keith Packard committed
411
    input_unlock();
412

413
    enabled = TRUE;
414
    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
415
                           XA_INTEGER, 8, PropModeReplace, 1, &enabled, TRUE);
416

417
    SendDevicePresenceEvent(dev->id, DeviceEnabled);
418
    if (sendevent) {
419
420
421
        flags[dev->id] |= XIDeviceEnabled;
        XISendDeviceHierarchyEvent(flags);
    }
422

423
    if (!IsMaster(dev) && !IsFloating(dev))
424
        XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0);
425
426
    RecalculateMasterButtons(dev);

427
428
429
    /* initialise an idle timer for this device*/
    dev->idle_counter = SyncInitDeviceIdleTime(dev);

430
431
432
    return TRUE;
}

433

434
/**
435
436
437
438
 * Switch a device off through the driver and push it onto the off_devices
 * list. A device will not send events while disabled. All clients are
 * notified about the device being disabled.
 *
439
440
441
 * Master keyboard devices have to be disabled before master pointer devices
 * otherwise things turn bad.
 *
442
 * @param sendevent True if an XI2 event should be sent.
443
444
 * @return TRUE on success or FALSE otherwise.
 */
445
Bool
446
DisableDevice(DeviceIntPtr dev, BOOL sendevent)
447
{
448
    DeviceIntPtr *prev, other;
449
    BOOL enabled;
450
    int flags[MAXDEVICES] = { 0 };
451

452
453
454
    if (!dev->enabled)
        return TRUE;

455
    for (prev = &inputInfo.devices;
456
         *prev && (*prev != dev); prev = &(*prev)->next);
457
    if (*prev != dev)
458
        return FALSE;
459

460
    TouchEndPhysicallyActiveTouches(dev);
461
    ReleaseButtonsAndKeys(dev);
462
463
464
    SyncRemoveDeviceIdleTime(dev->idle_counter);
    dev->idle_counter = NULL;

465
    /* float attached devices */
466
467
468
    if (IsMaster(dev)) {
        for (other = inputInfo.devices; other; other = other->next) {
            if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) {
469
                AttachDevice(NULL, other, NULL);
470
471
                flags[other->id] |= XISlaveDetached;
            }
472
473
        }
    }
474
475
476
477
478
    else {
        for (other = inputInfo.devices; other; other = other->next) {
            if (IsMaster(other) && other->lastSlave == dev)
                other->lastSlave = NULL;
        }
479
    }
480

481
    if (IsMaster(dev) && dev->spriteInfo->sprite) {
482
        for (other = inputInfo.devices; other; other = other->next)
483
484
            if (other->spriteInfo->paired == dev && !other->spriteInfo->spriteOwner)
                DisableDevice(other, sendevent);
485
486
    }

487
488
489
    if (dev->spriteInfo->paired)
        dev->spriteInfo->paired = NULL;

Keith Packard's avatar
Keith Packard committed
490
    input_lock();
491
    (void) (*dev->deviceProc) (dev, DEVICE_OFF);
Daniel Stone's avatar
Daniel Stone committed
492
    dev->enabled = FALSE;
493

494
    /* now that the device is disabled, we can reset the event reader's
495
     * last.slave */
496
    for (other = inputInfo.devices; other; other = other->next) {
497
498
499
        if (other->last.slave == dev)
            other->last.slave = NULL;
    }
500
    input_unlock();
501

Keith Packard's avatar
Keith Packard committed
502
503
    FreeSprite(dev);

504
505
    LeaveWindow(dev);
    SetFocusOut(dev);
506

507
508
509
    *prev = dev->next;
    dev->next = inputInfo.off_devices;
    inputInfo.off_devices = dev;
510

511
    enabled = FALSE;
512
    XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
513
                           XA_INTEGER, 8, PropModeReplace, 1, &enabled, TRUE);
514

515
    SendDevicePresenceEvent(dev->id, DeviceDisabled);
516
    if (sendevent) {
517
518
519
        flags[dev->id] = XIDeviceDisabled;
        XISendDeviceHierarchyEvent(flags);
    }
520
521
522

    RecalculateMasterButtons(dev);

523
524
525
    return TRUE;
}

526
527
528
529
530
void
DisableAllDevices(void)
{
    DeviceIntPtr dev, tmp;

531
532
533
534
535
536
    /* Disable slave devices first, excluding XTest devices */
    nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
        if (!IsXTestDevice(dev, NULL) && !IsMaster(dev))
            DisableDevice(dev, FALSE);
    }
    /* Disable XTest devices */
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
    nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
        if (!IsMaster(dev))
            DisableDevice(dev, FALSE);
    }
    /* master keyboards need to be disabled first */
    nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
        if (dev->enabled && IsMaster(dev) && IsKeyboardDevice(dev))
            DisableDevice(dev, FALSE);
    }
    nt_list_for_each_entry_safe(dev, tmp, inputInfo.devices, next) {
        if (dev->enabled)
            DisableDevice(dev, FALSE);
    }
}

552
/**
553
554
 * Initialise a new device through the driver and tell all clients about the
 * new device.
555
 *
556
 * Must be called before EnableDevice.
557
558
 * The device will NOT send events until it is enabled!
 *
559
 * @param sendevent True if an XI2 event should be sent.
560
 * @return Success or an error code on failure.
561
 */
562
int
563
ActivateDevice(DeviceIntPtr dev, BOOL sendevent)
Daniel Stone's avatar
Daniel Stone committed
564
565
{
    int ret = Success;
566
    ScreenPtr pScreen = screenInfo.screens[0];
Daniel Stone's avatar
Daniel Stone committed
567
568
569
570

    if (!dev || !dev->deviceProc)
        return BadImplementation;

Keith Packard's avatar
Keith Packard committed
571
    input_lock();
Daniel Stone's avatar
Daniel Stone committed
572
    ret = (*dev->deviceProc) (dev, DEVICE_INIT);
Keith Packard's avatar
Keith Packard committed
573
    input_unlock();
Daniel Stone's avatar
Daniel Stone committed
574
    dev->inited = (ret == Success);
575
576
    if (!dev->inited)
        return ret;
577
578

    /* Initialize memory for sprites. */
579
    if (IsMaster(dev) && dev->spriteInfo->spriteOwner)
580
581
        if (!pScreen->DeviceCursorInitialize(dev, pScreen))
            ret = BadAlloc;
582

583
    SendDevicePresenceEvent(dev->id, DeviceAdded);
584
585
    if (sendevent) {
        int flags[MAXDEVICES] = { 0 };
586
587
588
        flags[dev->id] = XISlaveAdded;
        XISendDeviceHierarchyEvent(flags);
    }
Daniel Stone's avatar
Daniel Stone committed
589
590
591
    return ret;
}

592
593
594
595
/**
 * Ring the bell.
 * The actual task of ringing the bell is the job of the DDX.
 */
Daniel Stone's avatar
Daniel Stone committed
596
static void
597
CoreKeyboardBell(int volume, DeviceIntPtr pDev, void *arg, int something)
Daniel Stone's avatar
Daniel Stone committed
598
{
599
600
601
    KeybdCtrl *ctrl = arg;

    DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration);
Daniel Stone's avatar
Daniel Stone committed
602
603
604
}

static void
605
CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl * ctrl)
Daniel Stone's avatar
Daniel Stone committed
606
607
608
609
{
    return;
}

610
/**
611
 * Device control function for the Virtual Core Keyboard.
612
 */
613
int
Daniel Stone's avatar
Daniel Stone committed
614
615
616
617
618
CoreKeyboardProc(DeviceIntPtr pDev, int what)
{

    switch (what) {
    case DEVICE_INIT:
619
        if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell,
620
                                      CoreKeyboardCtl)) {
621
622
623
624
            ErrorF("Keyboard initialization failed. This could be a missing "
                   "or incorrect setup of xkeyboard-config.\n");
            return BadValue;
        }
625
        return Success;
Daniel Stone's avatar
Daniel Stone committed
626

627
628
629
    case DEVICE_ON:
    case DEVICE_OFF:
        return Success;
Daniel Stone's avatar
Daniel Stone committed
630
631

    case DEVICE_CLOSE:
632
        return Success;
Daniel Stone's avatar
Daniel Stone committed
633
    }
634
635

    return BadMatch;
Daniel Stone's avatar
Daniel Stone committed
636
637
}

638
639
640
/**
 * Device control function for the Virtual Core Pointer.
 */
641
int
Daniel Stone's avatar
Daniel Stone committed
642
643
CorePointerProc(DeviceIntPtr pDev, int what)
{
644
#define NBUTTONS 10
645
646
#define NAXES 2
    BYTE map[NBUTTONS + 1];
Daniel Stone's avatar
Daniel Stone committed
647
    int i = 0;
648
649
    Atom btn_labels[NBUTTONS] = { 0 };
    Atom axes_labels[NAXES] = { 0 };
650
    ScreenPtr scr = screenInfo.screens[0];
Daniel Stone's avatar
Daniel Stone committed
651
652
653

    switch (what) {
    case DEVICE_INIT:
654
        for (i = 1; i <= NBUTTONS; i++)
Daniel Stone's avatar
Daniel Stone committed
655
            map[i] = i;
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
        btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
        btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
        btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
        btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
        /* don't know about the rest */

        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);

        if (!InitPointerDeviceStruct
            ((DevicePtr) pDev, map, NBUTTONS, btn_labels,
             (PtrCtrlProcPtr) NoopDDA, GetMotionHistorySize(), NAXES,
             axes_labels)) {
673
674
            ErrorF("Could not initialize device '%s'. Out of memory.\n",
                   pDev->name);
675
            return BadAlloc;    /* IPDS only fails on allocs */
676
        }
677
678
679
680
681
        /* axisVal is per-screen, last.valuators is desktop-wide */
        pDev->valuator->axisVal[0] = scr->width / 2;
        pDev->last.valuators[0] = pDev->valuator->axisVal[0] + scr->x;
        pDev->valuator->axisVal[1] = scr->height / 2;
        pDev->last.valuators[1] = pDev->valuator->axisVal[1] + scr->y;
Daniel Stone's avatar
Daniel Stone committed
682
683
        break;

684
685
686
    case DEVICE_CLOSE:
        break;

Daniel Stone's avatar
Daniel Stone committed
687
688
689
690
691
    default:
        break;
    }

    return Success;
692
693
694

#undef NBUTTONS
#undef NAXES
Daniel Stone's avatar
Daniel Stone committed
695
696
}

697
/**
698
 * Initialise the two core devices, VCP and VCK (see events.c).
699
700
 * Both devices are not tied to physical devices, but guarantee that there is
 * always a keyboard and a pointer present and keep the protocol semantics.
701
 *
702
703
 * Note that the server MUST have two core devices at all times, even if there
 * is no physical device connected.
704
 */
705
void
706
InitCoreDevices(void)
Daniel Stone's avatar
Daniel Stone committed
707
{
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
    int result;

    result = AllocDevicePair(serverClient, "Virtual core",
                             &inputInfo.pointer, &inputInfo.keyboard,
                             CorePointerProc, CoreKeyboardProc, TRUE);
    if (result != Success) {
        FatalError("Failed to allocate virtual core devices: %d", result);
    }

    result = ActivateDevice(inputInfo.pointer, TRUE);
    if (result != Success) {
        FatalError("Failed to activate virtual core pointer: %d", result);
    }

    result = ActivateDevice(inputInfo.keyboard, TRUE);
    if (result != Success) {
        FatalError("Failed to activate virtual core keyboard: %d", result);
    }

    if (!EnableDevice(inputInfo.pointer, TRUE)) {
         FatalError("Failed to enable virtual core pointer.");
    }

    if (!EnableDevice(inputInfo.keyboard, TRUE)) {
         FatalError("Failed to enable virtual core keyboard.");
    }
734

735
    InitXTestDevices();
Daniel Stone's avatar
Daniel Stone committed
736
737
}

738
/**
739
 * Activate all switched-off devices and then enable all those devices.
740
 *
741
742
 * Will return an error if no core keyboard or core pointer is present.
 * In theory this should never happen if you call InitCoreDevices() first.
743
 *
744
745
746
 * InitAndStartDevices needs to be called AFTER the windows are initialized.
 * Devices will start sending events after InitAndStartDevices() has
 * completed.
747
 *
748
 * @return Success or error code on failure.
749
 */
750
int
Julien Cristau's avatar
Julien Cristau committed
751
InitAndStartDevices(void)
752
{
753
    DeviceIntPtr dev, next;
754

Daniel Stone's avatar
Daniel Stone committed
755
    for (dev = inputInfo.off_devices; dev; dev = dev->next) {
Daniel Stone's avatar
Daniel Stone committed
756
        DebugF("(dix) initialising device %d\n", dev->id);
Daniel Stone's avatar
Daniel Stone committed
757
        if (!dev->inited)
758
            ActivateDevice(dev, TRUE);
Daniel Stone's avatar
Daniel Stone committed
759
    }
760

761
    /* enable real devices */
762
    for (dev = inputInfo.off_devices; dev; dev = next) {
763
        DebugF("(dix) enabling device %d\n", dev->id);
764
765
766
        next = dev->next;
        if (dev->inited && dev->startup)
            EnableDevice(dev, TRUE);
767
    }
768
769

    return Success;
770
771
}

772
773
774
/**
 * Free the given device class and reset the pointer to NULL.
 */
775
static void
776
FreeDeviceClass(int type, void **class)
777
778
779
780
{
    if (!(*class))
        return;

781
782
    switch (type) {
    case KeyClass:
783
    {
784
        KeyClassPtr *k = (KeyClassPtr *) class;
785

786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
        if ((*k)->xkbInfo) {
            XkbFreeInfo((*k)->xkbInfo);
            (*k)->xkbInfo = NULL;
        }
        free((*k));
        break;
    }
    case ButtonClass:
    {
        ButtonClassPtr *b = (ButtonClassPtr *) class;

        free((*b)->xkb_acts);
        free((*b));
        break;
    }
    case ValuatorClass:
    {
        ValuatorClassPtr *v = (ValuatorClassPtr *) class;

        free((*v)->motion);
        free((*v));
        break;
    }
    case XITouchClass:
    {
        TouchClassPtr *t = (TouchClassPtr *) class;
        int i;

        for (i = 0; i < (*t)->num_touches; i++) {
            free((*t)->touches[i].sprite.spriteTrace);
            free((*t)->touches[i].listeners);
            free((*t)->touches[i].valuators);
        }

820
        free((*t)->touches);
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
        free((*t));
        break;
    }
    case FocusClass:
    {
        FocusClassPtr *f = (FocusClassPtr *) class;

        free((*f)->trace);
        free((*f));
        break;
    }
    case ProximityClass:
    {
        ProximityClassPtr *p = (ProximityClassPtr *) class;

        free((*p));
        break;
    }
839
840
841
    }
    *class = NULL;
}
842
843

static void
844
FreeFeedbackClass(int type, void **class)
845
846
847
848
{
    if (!(*class))
        return;

849
850
    switch (type) {
    case KbdFeedbackClass:
851
    {
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
        KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr *) class;
        KbdFeedbackPtr k, knext;

        for (k = (*kbdfeed); k; k = knext) {
            knext = k->next;
            if (k->xkb_sli)
                XkbFreeSrvLedInfo(k->xkb_sli);
            free(k);
        }
        break;
    }
    case PtrFeedbackClass:
    {
        PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr *) class;
        PtrFeedbackPtr p, pnext;

        for (p = (*ptrfeed); p; p = pnext) {
            pnext = p->next;
            free(p);
        }
        break;
    }
    case IntegerFeedbackClass:
    {
        IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr *) class;
        IntegerFeedbackPtr i, inext;

        for (i = (*intfeed); i; i = inext) {
            inext = i->next;
            free(i);
        }
        break;
    }
    case StringFeedbackClass:
    {
        StringFeedbackPtr *stringfeed = (StringFeedbackPtr *) class;
        StringFeedbackPtr s, snext;

        for (s = (*stringfeed); s; s = snext) {
            snext = s->next;
            free(s->ctrl.symbols_supported);
            free(s->ctrl.symbols_displayed);
            free(s);
        }
        break;
    }
    case BellFeedbackClass:
    {
        BellFeedbackPtr *bell = (BellFeedbackPtr *) class;
        BellFeedbackPtr b, bnext;

        for (b = (*bell); b; b = bnext) {
            bnext = b->next;
            free(b);
        }
        break;
    }
    case LedFeedbackClass:
    {
        LedFeedbackPtr *leds = (LedFeedbackPtr *) class;
        LedFeedbackPtr l, lnext;

        for (l = (*leds); l; l = lnext) {
            lnext = l->next;
            if (l->xkb_sli)
                XkbFreeSrvLedInfo(l->xkb_sli);
            free(l);
        }
        break;
    }
922
923
924
    }
    *class = NULL;
}
925
926
927
928
929
930
931

static void
FreeAllDeviceClasses(ClassesPtr classes)
{
    if (!classes)
        return;

932
933
934
935
936
937
938
939
940
941
942
943
944
    FreeDeviceClass(KeyClass, (void *) &classes->key);
    FreeDeviceClass(ValuatorClass, (void *) &classes->valuator);
    FreeDeviceClass(XITouchClass, (void *) &classes->touch);
    FreeDeviceClass(ButtonClass, (void *) &classes->button);
    FreeDeviceClass(FocusClass, (void *) &classes->focus);
    FreeDeviceClass(ProximityClass, (void *) &classes->proximity);

    FreeFeedbackClass(KbdFeedbackClass, (void *) &classes->kbdfeed);
    FreeFeedbackClass(PtrFeedbackClass, (void *) &classes->ptrfeed);
    FreeFeedbackClass(IntegerFeedbackClass, (void *) &classes->intfeed);
    FreeFeedbackClass(StringFeedbackClass, (void *) &classes->stringfeed);
    FreeFeedbackClass(BellFeedbackClass, (void *) &classes->bell);
    FreeFeedbackClass(LedFeedbackClass, (void *) &classes->leds);
945
946
947

}

948
/**
949
 * Close down a device and free all resources.
950
951
952
953
 * Once closed down, the driver will probably not expect you that you'll ever
 * enable it again and free associated structs. If you want the device to just
 * be disabled, DisableDevice().
 * Don't call this function directly, use RemoveDevice() instead.
Keith Packard's avatar
Keith Packard committed
954
955
 *
 * Called with input lock held.
956
 */
957
static void
958
CloseDevice(DeviceIntPtr dev)
959
{
960
    ScreenPtr screen = screenInfo.screens[0];
961
    ClassesPtr classes;
962
    int j;
963

964
965
966
    if (!dev)
        return;

967
968
    XIDeleteAllDeviceProperties(dev);

969
    if (dev->inited)
970
        (void) (*dev->deviceProc) (dev, DEVICE_CLOSE);
Daniel Stone's avatar
Daniel Stone committed
971

972
973
974
    FreeSprite(dev);

    if (IsMaster(dev))
975
976
        screen->DeviceCursorCleanup(dev, screen);

977
    /* free acceleration info */
978
979
    if (dev->valuator && dev->valuator->accelScheme.AccelCleanupProc)
        dev->valuator->accelScheme.AccelCleanupProc(dev);
980

981
    while (dev->xkb_interest)
982
        XkbRemoveResourceClient((DevicePtr) dev, dev->xkb_interest->resource);
983

Peter Hutterer's avatar
Peter Hutterer committed
984
    free(dev->name);
Daniel Stone's avatar
Daniel Stone committed
985

986
    classes = (ClassesPtr) &dev->key;
987
    FreeAllDeviceClasses(classes);
Daniel Stone's avatar
Daniel Stone committed
988

989
    if (IsMaster(dev)) {
990
        classes = dev->unused_classes;
991
        FreeAllDeviceClasses(classes);
992
        free(classes);
993
994
    }

995
    /* a client may have the device set as client pointer */