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
    if (!XineramaSetWindowPntrs(pDev, pWin))
601
        return;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
602

603
    i = PanoramiXNumScreens - 1;
604

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

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

613
        if (x || y)
614
            RegionTranslate(&pSprite->Reg1, x, y);
615

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

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

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

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

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

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

637
#endif                          /* PANORAMIX */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
638

639
640
641
642
643
644
645
646
647
648
649
650
651
652
/**
 * 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.
 */
653
void
654
SetMaskForEvent(int deviceid, Mask mask, int event)
655
{
656
    if (deviceid < 0 || deviceid >= MAXDEVICES)
657
        FatalError("SetMaskForEvent: bogus device id");
658
    event_filters[deviceid][event] = mask;
659
660
}

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

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

676
    if (RegionContainsPoint(shape, x, y, &box))
677
        return;
678
    box = *RegionExtents(shape);
679
680
    /* this is rather crude */
    do {
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
        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! */
        }
697
    } while (!RegionContainsPoint(shape, x, y, &box));
698
699
700
701
702
    *px = x;
    *py = y;
}

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

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

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

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

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

776
    if (qe) {
777
        ev = &qe->event->device_event;
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
        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;
795
        }
796
    }
797
798
    if (pWin) {
        BoxRec lims;
799

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

804
            if (!XineramaSetWindowPntrs(pDev, pWin))
805
806
807
808
                return;

            i = PanoramiXNumScreens - 1;

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

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

817
                if (x || y)
818
                    RegionTranslate(&pSprite->Reg2, x, y);
819

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

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

836
837
838
839
840
841
842
843
844
        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;
845
846

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

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

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

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

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

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

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

        if (*pScreen->CursorConfinedTo)
            (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin);
901
902
903
    }
}

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

Peter Hutterer's avatar
Peter Hutterer committed
910
911
912
913
914
915
916
/**
 * 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.
 */
917
static void
918
ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
919
{
920
    SpritePtr pSprite = pDev->spriteInfo->sprite;
921
    ScreenPtr pScreen;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
922

923
924
925
926
927
    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);
928
929
930
931
932
933
934
935
#ifdef PANORAMIX
        /* XXX: is this really necessary?? (whot) */
        if (!noPanoramiXExtension)
            pScreen = pSprite->screen;
        else
#endif
            pScreen = pSprite->hotPhys.pScreen;

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

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

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

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

994
995
996
997
/**
 * @param dev device which you want to know its current root window
 * @return root window where dev's sprite is located
 */
998
WindowPtr
999
GetCurrentRootWindow(DeviceIntPtr dev)
1000
{
For faster browsing, not all history is shown. View entire blame