events.c 191 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.

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

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
47
/* The panoramix components contained the following notice */
Egbert Eich's avatar
Egbert Eich committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*****************************************************************

Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software.

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
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
shall not be used in advertising or otherwise to promote the sale, use or other
dealings in this Software without prior written authorization from Digital
Equipment Corporation.

******************************************************************/
75

76
/*
77
 * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
 */
98

Peter Hutterer's avatar
Peter Hutterer committed
99
/** @file events.c
Peter Hutterer's avatar
Peter Hutterer committed
100
101
102
 * This file handles event delivery and a big part of the server-side protocol
 * handling (the parts for input devices).
 */
103

104
105
106
107
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

108
#include <X11/X.h>
109
#include "misc.h"
110
#include "resource.h"
111
#include <X11/Xproto.h>
112
113
#include "windowstr.h"
#include "inputstr.h"
114
#include "inpututils.h"
115
116
117
118
#include "scrnintstr.h"
#include "cursorstr.h"

#include "dixstruct.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
119
120
121
122
123
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#include "globals.h"
124

Daniel Stone's avatar
Daniel Stone committed
125
#include <X11/extensions/XKBproto.h>
Daniel Stone's avatar
Daniel Stone committed
126
#include "xkbsrv.h"
127
#include "xace.h"
128
#include "probes.h"
129

130
#include <X11/extensions/XIproto.h>
Peter Hutterer's avatar
Peter Hutterer committed
131
#include <X11/extensions/XI2proto.h>
132
#include <X11/extensions/XI.h>
133
#include <X11/extensions/XI2.h>
134
#include "exglobals.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
135
136
#include "exevents.h"
#include "extnsionst.h"
137

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
138
139
140
#include "dixevents.h"
#include "dixgrabs.h"
#include "dispatch.h"
141
142
143
144
145

#include <X11/extensions/ge.h>
#include "geext.h"
#include "geint.h"

146
#include "eventstr.h"
147
#include "enterleave.h"
148
#include "eventconvert.h"
149
#include "mi.h"
150

Peter Hutterer's avatar
Peter Hutterer committed
151
/* Extension events type numbering starts at EXTENSION_EVENT_BASE.  */
152
#define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
#define AllButtonsMask ( \
	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
#define MotionMask ( \
	PointerMotionMask | Button1MotionMask | \
	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
	Button5MotionMask | ButtonMotionMask )
#define PropagateMask ( \
	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
	MotionMask )
#define PointerGrabMask ( \
	ButtonPressMask | ButtonReleaseMask | \
	EnterWindowMask | LeaveWindowMask | \
	PointerMotionHintMask | KeymapStateMask | \
	MotionMask )
#define AllModifiersMask ( \
	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
	Mod3Mask | Mod4Mask | Mod5Mask )
171
172
#define LastEventMask OwnerGrabButtonMask
#define AllEventMasks (LastEventMask|(LastEventMask-1))
173

174
175
176
177
178
179
180
181
182
183
184
185
186
/* @return the core event type or 0 if the event is not a core event */
static inline int
core_get_type(const xEvent *event)
{
    int type = event->u.u.type;

    return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type;
}

/* @return the XI2 event type or 0 if the event is not a XI2 event */
static inline int
xi2_get_type(const xEvent *event)
{
187
    const xGenericEvent *e = (const xGenericEvent *) event;
188

189
190
    return (e->type != GenericEvent ||
            e->extension != IReqCode) ? 0 : e->evtype;
191
}
Peter Hutterer's avatar
Peter Hutterer committed
192

193
194
195
196
197
/**
 * Used to indicate a implicit passive grab created by a ButtonPress event.
 * See DeliverEventsToWindow().
 */
#define ImplicitGrabMask (1 << 7)
198
199
200

#define WID(w) ((w) ? ((w)->drawable.id) : 0)

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
201
202
#define XE_KBPTR (xE->u.keyButtonPointer)

203
204
CallbackListPtr EventCallback;
CallbackListPtr DeviceEventCallback;
205
206
207

#define DNPMCOUNT 8

208
Mask DontPropagateMasks[DNPMCOUNT];
209
210
static int DontPropagateRefCnts[DNPMCOUNT];

211
212
213
214
static void CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe,
                               WindowPtr pWin);
static void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor,
                            Bool generateEvents, Bool confineToScreen,
215
                            ScreenPtr pScreen);
216
217
218
static Bool IsWrongPointerBarrierClient(ClientPtr client,
                                        DeviceIntPtr dev,
                                        xEvent *event);
219

220
221
222
/** Key repeat hack. Do not use but in TryClientEvents */
extern BOOL EventIsKeyRepeat(xEvent *event);

Peter Hutterer's avatar
Peter Hutterer committed
223
/**
224
225
 * Main input device struct.
 *     inputInfo.pointer
Peter Hutterer's avatar
Peter Hutterer committed
226
 *     is the core pointer. Referred to as "virtual core pointer", "VCP",
227
 *     "core pointer" or inputInfo.pointer. The VCP is the first master
228
 *     pointer device and cannot be deleted.
229
 *
Peter Hutterer's avatar
Peter Hutterer committed
230
231
232
 *     inputInfo.keyboard
 *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
 *     See inputInfo.pointer.
233
 *
Peter Hutterer's avatar
Peter Hutterer committed
234
 *     inputInfo.devices
235
 *     linked list containing all devices including VCP and VCK.
Peter Hutterer's avatar
Peter Hutterer committed
236
237
238
239
240
 *
 *     inputInfo.off_devices
 *     Devices that have not been initialized and are thus turned off.
 *
 *     inputInfo.numDevices
241
 *     Total number of devices.
242
243
244
245
246
247
248
249
250
251
252
253
 *
 *     inputInfo.all_devices
 *     Virtual device used for XIAllDevices passive grabs. This device is
 *     not part of the inputInfo.devices list and mostly unset except for
 *     the deviceid. It exists because passivegrabs need a valid device
 *     reference.
 *
 *     inputInfo.all_master_devices
 *     Virtual device used for XIAllMasterDevices passive grabs. This device
 *     is not part of the inputInfo.devices list and mostly unset except for
 *     the deviceid. It exists because passivegrabs need a valid device
 *     reference.
Peter Hutterer's avatar
Peter Hutterer committed
254
 */
255
InputInfo inputInfo;
256

257
EventSyncInfoRec syncEvents;
258

259
260
261
262
static struct DeviceEventTime {
    Bool reset;
    TimeStamp time;
} lastDeviceEventTime[MAXDEVICES];
263

Peter Hutterer's avatar
Peter Hutterer committed
264
265
266
/**
 * The root window the given device is currently on.
 */
267
#define RootWindow(sprite) sprite->spriteTrace[0]
268

269
static xEvent *swapEvent = NULL;
270
271
static int swapEventLen = 0;

272
273
274
275
276
277
void
NotImplemented(xEvent *from, xEvent *to)
{
    FatalError("Not implemented");
}

278
279
/**
 * Convert the given event type from an XI event to a core event.
Peter Hutterer's avatar
Peter Hutterer committed
280
 * @param[in] The XI 1.x event type.
281
282
 * @return The matching core event type or 0 if there is none.
 */
283
int
284
285
286
XItoCoreType(int xitype)
{
    int coretype = 0;
287

288
289
290
291
292
293
294
295
296
297
    if (xitype == DeviceMotionNotify)
        coretype = MotionNotify;
    else if (xitype == DeviceButtonPress)
        coretype = ButtonPress;
    else if (xitype == DeviceButtonRelease)
        coretype = ButtonRelease;
    else if (xitype == DeviceKeyPress)
        coretype = KeyPress;
    else if (xitype == DeviceKeyRelease)
        coretype = KeyRelease;
298

299
300
301
    return coretype;
}

302
/**
Peter Hutterer's avatar
Peter Hutterer committed
303
304
 * @return true if the device owns a cursor, false if device shares a cursor
 * sprite with another device.
305
 */
306
Bool
307
DevHasCursor(DeviceIntPtr pDev)
308
{
309
    return pDev->spriteInfo->spriteOwner;
310
311
}

312
/*
Peter Hutterer's avatar
Peter Hutterer committed
313
 * @return true if a device is a pointer, check is the same as used by XI to
314
315
 * fill the 'use' field.
 */
316
Bool
317
318
IsPointerDevice(DeviceIntPtr dev)
{
319
    return (dev->type == MASTER_POINTER) ||
320
        (dev->valuator && dev->button) || (dev->valuator && !dev->key);
321
322
323
}

/*
Peter Hutterer's avatar
Peter Hutterer committed
324
 * @return true if a device is a keyboard, check is the same as used by XI to
325
 * fill the 'use' field.
326
327
328
 *
 * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
 * count them as keyboard devices.
329
 */
330
Bool
331
332
IsKeyboardDevice(DeviceIntPtr dev)
{
333
    return (dev->type == MASTER_KEYBOARD) ||
334
        ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
335
336
337
338
339
}

Bool
IsMaster(DeviceIntPtr dev)
{
340
    return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
341
342
}

343
344
345
Bool
IsFloating(DeviceIntPtr dev)
{
346
    return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL;
347
348
}

Peter Hutterer's avatar
Peter Hutterer committed
349
350
351
/**
 * Max event opcode.
 */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
352
extern int lastEvent;
353

Peter Hutterer's avatar
Peter Hutterer committed
354
#define CantBeFiltered NoEventMask
355
/**
Peter Hutterer's avatar
Peter Hutterer committed
356
357
 * Event masks for each event type.
 *
358
359
 * One set of filters for each device, initialized by memcpy of
 * default_filter in InitEvents.
Peter Hutterer's avatar
Peter Hutterer committed
360
361
362
363
364
365
366
 *
 * Filters are used whether a given event may be delivered to a client,
 * usually in the form of if (window-event-mask & filter); then deliver event.
 *
 * One notable filter is for PointerMotion/DevicePointerMotion events. Each
 * time a button is pressed, the filter is modified to also contain the
 * matching ButtonXMotion mask.
367
 */
368
Mask event_filters[MAXDEVICES][MAXEVENTS];
369

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
static const Mask default_filter[MAXEVENTS] = {
    NoSuchEvent,                /* 0 */
    NoSuchEvent,                /* 1 */
    KeyPressMask,               /* KeyPress */
    KeyReleaseMask,             /* KeyRelease */
    ButtonPressMask,            /* ButtonPress */
    ButtonReleaseMask,          /* ButtonRelease */
    PointerMotionMask,          /* MotionNotify (initial state) */
    EnterWindowMask,            /* EnterNotify */
    LeaveWindowMask,            /* LeaveNotify */
    FocusChangeMask,            /* FocusIn */
    FocusChangeMask,            /* FocusOut */
    KeymapStateMask,            /* KeymapNotify */
    ExposureMask,               /* Expose */
    CantBeFiltered,             /* GraphicsExpose */
    CantBeFiltered,             /* NoExpose */
    VisibilityChangeMask,       /* VisibilityNotify */
    SubstructureNotifyMask,     /* CreateNotify */
    StructureAndSubMask,        /* DestroyNotify */
    StructureAndSubMask,        /* UnmapNotify */
    StructureAndSubMask,        /* MapNotify */
    SubstructureRedirectMask,   /* MapRequest */
    StructureAndSubMask,        /* ReparentNotify */
    StructureAndSubMask,        /* ConfigureNotify */
    SubstructureRedirectMask,   /* ConfigureRequest */
    StructureAndSubMask,        /* GravityNotify */
    ResizeRedirectMask,         /* ResizeRequest */
    StructureAndSubMask,        /* CirculateNotify */
    SubstructureRedirectMask,   /* CirculateRequest */
    PropertyChangeMask,         /* PropertyNotify */
    CantBeFiltered,             /* SelectionClear */
    CantBeFiltered,             /* SelectionRequest */
    CantBeFiltered,             /* SelectionNotify */
    ColormapChangeMask,         /* ColormapNotify */
    CantBeFiltered,             /* ClientMessage */
    CantBeFiltered              /* MappingNotify */
406
};
407

408
409
410
411
/**
 * For the given event, return the matching event filter. This filter may then
 * be AND'ed with the selected event mask.
 *
412
413
414
415
 * For XI2 events, the returned filter is simply the byte containing the event
 * mask we're interested in. E.g. for a mask of (1 << 13), this would be
 * byte[1].
 *
416
417
418
419
 * @param[in] dev The device the event belongs to, may be NULL.
 * @param[in] event The event to get the filter for. Only the type of the
 *                  event matters, or the extension + evtype for GenericEvents.
 * @return The filter mask for the given event.
420
421
 *
 * @see GetEventMask
422
 */
423
Mask
424
425
GetEventFilter(DeviceIntPtr dev, xEvent *event)
{
426
427
    int evtype = 0;

428
    if (event->u.u.type != GenericEvent)
429
        return event_get_filter_from_type(dev, event->u.u.type);
430
    else if ((evtype = xi2_get_type(event)))
431
        return event_get_filter_from_xi2type(evtype);
Peter Hutterer's avatar
Peter Hutterer committed
432
    ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
433
434
435
    return 0;
}

436
437
438
439
/**
 * Return the single byte of the device's XI2 mask that contains the mask
 * for the event_type.
 */
440
int
441
GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type)
442
{
443
444
445
446
    /* we just return the matching filter because that's the only use
     * for this mask anyway.
     */
    if (xi2mask_isset(mask, dev, event_type))
447
        return event_get_filter_from_xi2type(event_type);
448
449
    else
        return 0;
450
451
}

452
/**
453
454
 * @return TRUE if the mask is set for this event from this device on the
 * window, or FALSE otherwise.
455
 */
456
Bool
457
WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev)
458
459
460
461
{
    OtherInputMasks *inputMasks = wOtherInputMasks(win);
    int evtype;

462
    if (!inputMasks || xi2_get_type(ev) == 0)
463
464
        return 0;

465
    evtype = ((xGenericEvent *) ev)->evtype;
466

467
    return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
468
}
469

Daniel Stone's avatar
Daniel Stone committed
470
Mask
471
GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
472
{
473
474
    int evtype;

475
    /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
476
    if ((evtype = xi2_get_type(event))) {
477
        return GetXI2MaskByte(other->xi2mask, dev, evtype);
478
479
    }
    else if (core_get_type(event) != 0)
480
        return other->mask[XIAllDevices];
481
482
483
484
    else
        return other->mask[dev->id];
}

485
486
static CARD8 criticalEvents[32] = {
    0x7c, 0x30, 0x40            /* key, button, expose, and configure events */
487
488
};

489
static void
490
491
SyntheticMotion(DeviceIntPtr dev, int x, int y)
{
492
493
    int screenno = 0;

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
494
#ifdef PANORAMIX
495
496
497
498
    if (!noPanoramiXExtension)
        screenno = dev->spriteInfo->sprite->screen->myNum;
#endif
    PostSyntheticMotion(dev, x, y, screenno,
499
500
                        (syncEvents.playingEvents) ? syncEvents.time.
                        milliseconds : currentTime.milliseconds);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
501

502
503
504
505
}

#ifdef PANORAMIX
static void PostNewCursor(DeviceIntPtr pDev);
506

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
507
static Bool
508
509
XineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent)
{
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
510
511
    ScreenPtr pScreen;
    int i;
512
    SpritePtr pSprite = pDev->spriteInfo->sprite;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
513
514

    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
515
       to send the message too and what the coordinates relative to
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
516
517
       that screen are. */

518
    pScreen = pSprite->screen;
519
520
    x += screenInfo.screens[0]->x;
    y += screenInfo.screens[0]->y;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
521

522
523
524
525
526
527
528
529
530
    if (!point_on_screen(pScreen, x, y)) {
        FOR_NSCREENS(i) {
            if (i == pScreen->myNum)
                continue;
            if (point_on_screen(screenInfo.screens[i], x, y)) {
                pScreen = screenInfo.screens[i];
                break;
            }
        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
531
532
    }

533
    pSprite->screen = pScreen;
534
535
536
537
    pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
    pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
    x -= pScreen->x;
    y -= pScreen->y;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
538

539
    return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
540
541
542
}

static void
543
XineramaConstrainCursor(DeviceIntPtr pDev)
544
{
545
    SpritePtr pSprite = pDev->spriteInfo->sprite;
546
547
548
549
550
    ScreenPtr pScreen;
    BoxRec newBox;

    pScreen = pSprite->screen;
    newBox = pSprite->physLimits;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
551
552
553

    /* Translate the constraining box to the screen
       the sprite is actually on */
554
555
556
557
    newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
    newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
    newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
    newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
558

559
    (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox);
560
561
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
562
static Bool
563
XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
564
{
565
    SpritePtr pSprite = pDev->spriteInfo->sprite;
566

567
568
569
570
571
572
573
574
575
576
    if (pWin == screenInfo.screens[0]->root) {
        int i;

        FOR_NSCREENS(i)
            pSprite->windows[i] = screenInfo.screens[i]->root;
    }
    else {
        PanoramiXRes *win;
        int rc, i;

577
        rc = dixLookupResourceByType((void **) &win, pWin->drawable.id,
578
579
580
581
582
583
584
585
586
587
                                     XRT_WINDOW, serverClient, DixReadAccess);
        if (rc != Success)
            return FALSE;

        FOR_NSCREENS(i) {
            rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
                                 serverClient, DixReadAccess);
            if (rc != Success)  /* window is being unmapped */
                return FALSE;
        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
588
589
590
591
592
    }
    return TRUE;
}

static void
593
XineramaConfineCursorToWindow(DeviceIntPtr pDev,
594
                              WindowPtr pWin, Bool generateEvents)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
595
{
596
    SpritePtr pSprite = pDev->spriteInfo->sprite;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
597

598
    int x, y, off_x, off_y, i;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
599

600
601
    assert(!noPanoramiXExtension);

602
    if (!XineramaSetWindowPntrs(pDev, pWin))
603
        return;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
604

605
    i = PanoramiXNumScreens - 1;
606

607
    RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize);
608
609
    off_x = screenInfo.screens[i]->x;
    off_y = screenInfo.screens[i]->y;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
610

611
    while (i--) {
612
613
        x = off_x - screenInfo.screens[i]->x;
        y = off_y - screenInfo.screens[i]->y;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
614

615
        if (x || y)
616
            RegionTranslate(&pSprite->Reg1, x, y);
617

618
        RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
619
                    &pSprite->windows[i]->borderSize);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
620

621
622
        off_x = screenInfo.screens[i]->x;
        off_y = screenInfo.screens[i]->y;
623
    }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
624

625
    pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
626

627
    if (RegionNumRects(&pSprite->Reg1) > 1)
628
629
630
        pSprite->hotShape = &pSprite->Reg1;
    else
        pSprite->hotShape = NullRegion;
631

632
    pSprite->confined = FALSE;
633
634
    pSprite->confineWin =
        (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
635

636
    CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
637
638
}

639
#endif                          /* PANORAMIX */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
640

641
642
643
644
645
646
647
648
649
650
651
652
653
654
/**
 * Modifies the filter for the given protocol event type to the given masks.
 *
 * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
 * The latter initialises masks for the matching XI events, it's a once-off
 * setting.
 * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
 * time a button is pressed to include the matching ButtonXMotion mask in the
 * filter.
 *
 * @param[in] deviceid The device to modify the filter for.
 * @param[in] mask The new filter mask.
 * @param[in] event Protocol event type.
 */
655
void
656
SetMaskForEvent(int deviceid, Mask mask, int event)
657
{
658
    if (deviceid < 0 || deviceid >= MAXDEVICES)
659
        FatalError("SetMaskForEvent: bogus device id");
660
    event_filters[deviceid][event] = mask;
661
662
}

663
void
Roland Mainz's avatar
Roland Mainz committed
664
SetCriticalEvent(int event)
665
{
666
    if (event >= MAXEVENTS)
667
        FatalError("SetCriticalEvent: bogus event number");
668
669
670
    criticalEvents[event >> 3] |= 1 << (event & 7);
}

671
void
672
ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
673
674
675
676
677
{
    BoxRec box;
    int x = *px, y = *py;
    int incx = 1, incy = 1;

678
    if (RegionContainsPoint(shape, x, y, &box))
679
        return;
680
    box = *RegionExtents(shape);
681
682
    /* this is rather crude */
    do {
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
        x += incx;
        if (x >= box.x2) {
            incx = -1;
            x = *px - 1;
        }
        else if (x < box.x1) {
            incx = 1;
            x = *px;
            y += incy;
            if (y >= box.y2) {
                incy = -1;
                y = *py - 1;
            }
            else if (y < box.y1)
                return;         /* should never get here! */
        }
699
    } while (!RegionContainsPoint(shape, x, y, &box));
700
701
702
703
704
    *px = x;
    *py = y;
}

static void
705
706
707
708
CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents,
                Bool confineToScreen, /* unused if PanoramiX on */
                ScreenPtr pScreen)    /* unused if PanoramiX on */
{
709
    HotSpot new;
710
    SpritePtr pSprite = pDev->spriteInfo->sprite;
711
712

    if (!cursor)
713
        return;
714
    new = pSprite->hotPhys;
715
716
717
718
#ifdef PANORAMIX
    if (!noPanoramiXExtension)
        /* I don't care what the DDX has to say about it */
        pSprite->physLimits = pSprite->hotLimits;
719
    else
720
721
722
723
724
725
726
#endif
    {
        if (pScreen)
            new.pScreen = pScreen;
        else
            pScreen = new.pScreen;
        (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
727
                                  &pSprite->physLimits);
728
        pSprite->confined = confineToScreen;
729
        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
730
731
732
    }

    /* constrain the pointer to those limits */
733
    if (new.x < pSprite->physLimits.x1)
734
735
736
        new.x = pSprite->physLimits.x1;
    else if (new.x >= pSprite->physLimits.x2)
        new.x = pSprite->physLimits.x2 - 1;
737
    if (new.y < pSprite->physLimits.y1)
738
739
740
        new.y = pSprite->physLimits.y1;
    else if (new.y >= pSprite->physLimits.y2)
        new.y = pSprite->physLimits.y2 - 1;
741
    if (pSprite->hotShape)
742
        ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
743
744
745
746
747
    if ((
#ifdef PANORAMIX
            noPanoramiXExtension &&
#endif
            (pScreen != pSprite->hotPhys.pScreen)) ||
748
        (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) {
749
750
#ifdef PANORAMIX
        if (!noPanoramiXExtension)
751
            XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents);
752
        else
753
#endif
754
755
756
757
758
759
        {
            if (pScreen != pSprite->hotPhys.pScreen)
                pSprite->hotPhys = new;
            (*pScreen->SetCursorPosition)
                (pDev, pScreen, new.x, new.y, generateEvents);
        }
760
        if (!generateEvents)
761
            SyntheticMotion(pDev, new.x, new.y);
762
    }
763
764
765
766
767
768

#ifdef PANORAMIX
    /* Tell DDX what the limits are */
    if (!noPanoramiXExtension)
        XineramaConstrainCursor(pDev);
#endif
769
770
771
}

static void
772
CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin)
773
{
774
    SpritePtr pSprite = pDev->spriteInfo->sprite;
775
    RegionPtr reg = NULL;
776
    DeviceEvent *ev = NULL;
777

778
    if (qe) {
779
        ev = &qe->event->device_event;
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
        switch (ev->type) {
        case ET_Motion:
        case ET_ButtonPress:
        case ET_ButtonRelease:
        case ET_KeyPress:
        case ET_KeyRelease:
        case ET_ProximityIn:
        case ET_ProximityOut:
            pSprite->hot.pScreen = qe->pScreen;
            pSprite->hot.x = ev->root_x;
            pSprite->hot.y = ev->root_y;
            pWin =
                pDev->deviceGrab.grab ? pDev->deviceGrab.grab->
                confineTo : NullWindow;
            break;
        default:
            break;
797
        }
798
    }
799
800
    if (pWin) {
        BoxRec lims;
801

802
803
804
805
#ifdef PANORAMIX
        if (!noPanoramiXExtension) {
            int x, y, off_x, off_y, i;

806
            if (!XineramaSetWindowPntrs(pDev, pWin))
807
808
809
810
                return;

            i = PanoramiXNumScreens - 1;

811
            RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize);
812
813
            off_x = screenInfo.screens[i]->x;
            off_y = screenInfo.screens[i]->y;
814

815
            while (i--) {
816
817
                x = off_x - screenInfo.screens[i]->x;
                y = off_y - screenInfo.screens[i]->y;
818

819
                if (x || y)
820
                    RegionTranslate(&pSprite->Reg2, x, y);
821

822
                RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
823
                            &pSprite->windows[i]->borderSize);
824

825
826
                off_x = screenInfo.screens[i]->x;
                off_y = screenInfo.screens[i]->y;
827
            }
828
829
        }
        else
830
831
#endif
        {
832
            if (pSprite->hot.pScreen != pWin->drawable.pScreen) {
833
834
835
836
837
                pSprite->hot.pScreen = pWin->drawable.pScreen;
                pSprite->hot.x = pSprite->hot.y = 0;
            }
        }

838
839
840
841
842
843
844
845
846
        lims = *RegionExtents(&pWin->borderSize);
        if (pSprite->hot.x < lims.x1)
            pSprite->hot.x = lims.x1;
        else if (pSprite->hot.x >= lims.x2)
            pSprite->hot.x = lims.x2 - 1;
        if (pSprite->hot.y < lims.y1)
            pSprite->hot.y = lims.y1;
        else if (pSprite->hot.y >= lims.y2)
            pSprite->hot.y = lims.y2 - 1;
847
848

#ifdef PANORAMIX
849
        if (!noPanoramiXExtension) {
850
            if (RegionNumRects(&pSprite->Reg2) > 1)
851
852
                reg = &pSprite->Reg2;

853
854
        }
        else
855
856
857
858
859
860
861
862
863
#endif
        {
            if (wBoundingShape(pWin))
                reg = &pWin->borderSize;
        }

        if (reg)
            ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);

864
865
866
867
868
        if (qe && ev) {
            qe->pScreen = pSprite->hot.pScreen;
            ev->root_x = pSprite->hot.x;
            ev->root_y = pSprite->hot.y;
        }
869
    }
870
#ifdef PANORAMIX
871
    if (noPanoramiXExtension)   /* No typo. Only set the root win if disabled */
872
#endif
873
        RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
874
875
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
876
static void
877
878
ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents,
                      Bool confineToScreen)
879
{
880
    SpritePtr pSprite = pDev->spriteInfo->sprite;
881

882
883
884
    if (syncEvents.playingEvents) {
        CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin);
        SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
885
    }
886
    else {
887
888
        ScreenPtr pScreen = pWin->drawable.pScreen;

889
#ifdef PANORAMIX
890
        if (!noPanoramiXExtension) {
891
892
893
894
            XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
            return;
        }
#endif
895
896
897
        pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
        pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
            : NullRegion;
898
        CheckPhysLimits(pDev, pSprite->current, generateEvents,
899
                        confineToScreen, pWin->drawable.pScreen);
900
901
902

        if (*pScreen->CursorConfinedTo)
            (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin);
903
904
905
    }
}

906
Bool
907
PointerConfinedToScreen(DeviceIntPtr pDev)
908
{
909
    return pDev->spriteInfo->sprite->confined;
910
911
}

Peter Hutterer's avatar
Peter Hutterer committed
912
913
914
915
916
917
918
/**
 * Update the sprite cursor to the given cursor.
 *
 * ChangeToCursor() will display the new cursor and free the old cursor (if
 * applicable). If the provided cursor is already the updated cursor, nothing
 * happens.
 */
919
static void
920
ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
921
{
922
    SpritePtr pSprite = pDev->spriteInfo->sprite;
923
    ScreenPtr pScreen;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
924

925
926
927
928
929
    if (cursor != pSprite->current) {
        if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
            (pSprite->current->bits->yhot != cursor->bits->yhot))
            CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
                            (ScreenPtr) NULL);
930
931
932
933
934
935
936
937
#ifdef PANORAMIX
        /* XXX: is this really necessary?? (whot) */
        if (!noPanoramiXExtension)
            pScreen = pSprite->screen;
        else
#endif
            pScreen = pSprite->hotPhys.pScreen;

938
939
        (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
        FreeCursor(pSprite->current, (Cursor) 0);
Peter Hutterer's avatar
Peter Hutterer committed
940
        pSprite->current = RefCursor(cursor);
941
942
943
    }
}

Peter Hutterer's avatar
Peter Hutterer committed
944
/**
945
 * @returns true if b is a descendent of a
Peter Hutterer's avatar
Peter Hutterer committed
946
 */
947
Bool
948
IsParent(WindowPtr a, WindowPtr b)
949
950
{
    for (b = b->parent; b; b = b->parent)
951
952
        if (b == a)
            return TRUE;
953
954
955
    return FALSE;
}

Peter Hutterer's avatar
Peter Hutterer committed
956
957
958
/**
 * Update the cursor displayed on the screen.
 *
959
 * Called whenever a cursor may have changed shape or position.
Peter Hutterer's avatar
Peter Hutterer committed
960
 */
961
static void
962
PostNewCursor(DeviceIntPtr pDev)
963
{
964
    WindowPtr win;
965
    GrabPtr grab = pDev->deviceGrab.grab;
966
967
    SpritePtr pSprite = pDev->spriteInfo->sprite;
    CursorPtr pCursor;
968
969

    if (syncEvents.playingEvents)
970
971
972
973
974
975
976
977
978
979
        return;
    if (grab) {
        if (grab->cursor) {
            ChangeToCursor(pDev, grab->cursor);
            return;
        }
        if (IsParent(grab->window, pSprite->win))
            win = pSprite->win;
        else
            win = grab->window;
980
981
    }
    else
982
983
984
        win = pSprite->win;
    for (; win; win = win->parent) {
        if (win->optional) {
985
986
987
            pCursor = WindowGetDeviceCursor(win, pDev);
            if (!pCursor && win->optional->cursor != NullCursor)
                pCursor = win->optional->cursor;
988
            if (pCursor) {
989
990
991
                ChangeToCursor(pDev, pCursor);
                return;
            }
992
        }
993
    }
994
995
}

996
997
998
999
/**
 * @param dev device which you want to know its current root window
 * @return root window where dev's sprite is located
 */
1000
WindowPtr
1001
GetCurrentRootWindow(DeviceIntPtr dev)
1002
{
1003
    return RootWindow(dev->spriteInfo->sprite);
1004
1005
}

Peter Hutterer's avatar
Peter Hutterer committed
1006
1007
1008
/**
 * @return window underneath the cursor sprite.
 */
1009
WindowPtr
1010
GetSpriteWindow(DeviceIntPtr pDev)
1011
{
1012
    return pDev->spriteInfo->sprite->win;
1013
1014
}

Peter Hutterer's avatar
Peter Hutterer committed
1015
1016
1017
/**
 * @return current sprite cursor.
 */
1018
CursorPtr
1019
GetSpriteCursor(DeviceIntPtr pDev)
1020
{
1021
    return pDev->spriteInfo->sprite->current;
1022
1023
}

Peter Hutterer's avatar
Peter Hutterer committed
1024
1025
1026
/**
 * Set x/y current sprite position in screen coordinates.
 */
1027
void