Imported Upstream version 1.15.1
[deb_xorg-server.git] / dix / events.c
CommitLineData
a09e091a
JB
1/************************************************************
2
3Copyright 1987, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27 All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Digital not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45********************************************************/
46
47/* The panoramix components contained the following notice */
48/*****************************************************************
49
50Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
51
52Permission is hereby granted, free of charge, to any person obtaining a copy
53of this software and associated documentation files (the "Software"), to deal
54in the Software without restriction, including without limitation the rights
55to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56copies of the Software.
57
58The above copyright notice and this permission notice shall be included in
59all copies or substantial portions of the Software.
60
61THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
64DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
65BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
66WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
67IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68
69Except as contained in this notice, the name of Digital Equipment Corporation
70shall not be used in advertising or otherwise to promote the sale, use or other
71dealings in this Software without prior written authorization from Digital
72Equipment Corporation.
73
74******************************************************************/
75
76/*
77 * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
78 *
79 * Permission is hereby granted, free of charge, to any person obtaining a
80 * copy of this software and associated documentation files (the "Software"),
81 * to deal in the Software without restriction, including without limitation
82 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83 * and/or sell copies of the Software, and to permit persons to whom the
84 * Software is furnished to do so, subject to the following conditions:
85 *
86 * The above copyright notice and this permission notice (including the next
87 * paragraph) shall be included in all copies or substantial portions of the
88 * Software.
89 *
90 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
93 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
95 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
96 * DEALINGS IN THE SOFTWARE.
97 */
98
99/** @file events.c
100 * This file handles event delivery and a big part of the server-side protocol
101 * handling (the parts for input devices).
102 */
103
104#ifdef HAVE_DIX_CONFIG_H
105#include <dix-config.h>
106#endif
107
108#include <X11/X.h>
109#include "misc.h"
110#include "resource.h"
111#include <X11/Xproto.h>
112#include "windowstr.h"
113#include "inputstr.h"
114#include "inpututils.h"
115#include "scrnintstr.h"
116#include "cursorstr.h"
117
118#include "dixstruct.h"
119#ifdef PANORAMIX
120#include "panoramiX.h"
121#include "panoramiXsrv.h"
122#endif
123#include "globals.h"
124
125#include <X11/extensions/XKBproto.h>
126#include "xkbsrv.h"
127#include "xace.h"
128
129#ifdef XSERVER_DTRACE
130#include <sys/types.h>
131typedef const char *string;
132
133#include "Xserver-dtrace.h"
134#endif
135
136#include <X11/extensions/XIproto.h>
137#include <X11/extensions/XI2proto.h>
138#include <X11/extensions/XI.h>
139#include <X11/extensions/XI2.h>
140#include "exglobals.h"
141#include "exevents.h"
142#include "extnsionst.h"
143
144#include "dixevents.h"
145#include "dixgrabs.h"
146#include "dispatch.h"
147
148#include <X11/extensions/ge.h>
149#include "geext.h"
150#include "geint.h"
151
152#include "eventstr.h"
153#include "enterleave.h"
154#include "eventconvert.h"
155#include "mi.h"
156
157/* Extension events type numbering starts at EXTENSION_EVENT_BASE. */
158#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
159#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
160#define AllButtonsMask ( \
161 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
162#define MotionMask ( \
163 PointerMotionMask | Button1MotionMask | \
164 Button2MotionMask | Button3MotionMask | Button4MotionMask | \
165 Button5MotionMask | ButtonMotionMask )
166#define PropagateMask ( \
167 KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
168 MotionMask )
169#define PointerGrabMask ( \
170 ButtonPressMask | ButtonReleaseMask | \
171 EnterWindowMask | LeaveWindowMask | \
172 PointerMotionHintMask | KeymapStateMask | \
173 MotionMask )
174#define AllModifiersMask ( \
175 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
176 Mod3Mask | Mod4Mask | Mod5Mask )
177#define LastEventMask OwnerGrabButtonMask
178#define AllEventMasks (LastEventMask|(LastEventMask-1))
179
180/* @return the core event type or 0 if the event is not a core event */
181static inline int
182core_get_type(const xEvent *event)
183{
184 int type = event->u.u.type;
185
186 return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type;
187}
188
189/* @return the XI2 event type or 0 if the event is not a XI2 event */
190static inline int
191xi2_get_type(const xEvent *event)
192{
193 const xGenericEvent *e = (const xGenericEvent *) event;
194
195 return (e->type != GenericEvent ||
196 e->extension != IReqCode) ? 0 : e->evtype;
197}
198
199/**
200 * Used to indicate a implicit passive grab created by a ButtonPress event.
201 * See DeliverEventsToWindow().
202 */
203#define ImplicitGrabMask (1 << 7)
204
205#define WID(w) ((w) ? ((w)->drawable.id) : 0)
206
207#define XE_KBPTR (xE->u.keyButtonPointer)
208
209CallbackListPtr EventCallback;
210CallbackListPtr DeviceEventCallback;
211
212#define DNPMCOUNT 8
213
214Mask DontPropagateMasks[DNPMCOUNT];
215static int DontPropagateRefCnts[DNPMCOUNT];
216
217static void CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe,
218 WindowPtr pWin);
219static void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor,
220 Bool generateEvents, Bool confineToScreen,
221 ScreenPtr pScreen);
222static Bool IsWrongPointerBarrierClient(ClientPtr client,
223 DeviceIntPtr dev,
224 xEvent *event);
225
226/** Key repeat hack. Do not use but in TryClientEvents */
227extern BOOL EventIsKeyRepeat(xEvent *event);
228
229/**
230 * Main input device struct.
231 * inputInfo.pointer
232 * is the core pointer. Referred to as "virtual core pointer", "VCP",
233 * "core pointer" or inputInfo.pointer. The VCP is the first master
234 * pointer device and cannot be deleted.
235 *
236 * inputInfo.keyboard
237 * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
238 * See inputInfo.pointer.
239 *
240 * inputInfo.devices
241 * linked list containing all devices including VCP and VCK.
242 *
243 * inputInfo.off_devices
244 * Devices that have not been initialized and are thus turned off.
245 *
246 * inputInfo.numDevices
247 * Total number of devices.
248 *
249 * inputInfo.all_devices
250 * Virtual device used for XIAllDevices passive grabs. This device is
251 * not part of the inputInfo.devices list and mostly unset except for
252 * the deviceid. It exists because passivegrabs need a valid device
253 * reference.
254 *
255 * inputInfo.all_master_devices
256 * Virtual device used for XIAllMasterDevices passive grabs. This device
257 * is not part of the inputInfo.devices list and mostly unset except for
258 * the deviceid. It exists because passivegrabs need a valid device
259 * reference.
260 */
261InputInfo inputInfo;
262
263EventSyncInfoRec syncEvents;
264
265static struct DeviceEventTime {
266 Bool reset;
267 TimeStamp time;
268} lastDeviceEventTime[MAXDEVICES];
269
270/**
271 * The root window the given device is currently on.
272 */
273#define RootWindow(sprite) sprite->spriteTrace[0]
274
275static xEvent *swapEvent = NULL;
276static int swapEventLen = 0;
277
278void
279NotImplemented(xEvent *from, xEvent *to)
280{
281 FatalError("Not implemented");
282}
283
284/**
285 * Convert the given event type from an XI event to a core event.
286 * @param[in] The XI 1.x event type.
287 * @return The matching core event type or 0 if there is none.
288 */
289int
290XItoCoreType(int xitype)
291{
292 int coretype = 0;
293
294 if (xitype == DeviceMotionNotify)
295 coretype = MotionNotify;
296 else if (xitype == DeviceButtonPress)
297 coretype = ButtonPress;
298 else if (xitype == DeviceButtonRelease)
299 coretype = ButtonRelease;
300 else if (xitype == DeviceKeyPress)
301 coretype = KeyPress;
302 else if (xitype == DeviceKeyRelease)
303 coretype = KeyRelease;
304
305 return coretype;
306}
307
308/**
309 * @return true if the device owns a cursor, false if device shares a cursor
310 * sprite with another device.
311 */
312Bool
313DevHasCursor(DeviceIntPtr pDev)
314{
315 return pDev->spriteInfo->spriteOwner;
316}
317
318/*
319 * @return true if a device is a pointer, check is the same as used by XI to
320 * fill the 'use' field.
321 */
322Bool
323IsPointerDevice(DeviceIntPtr dev)
324{
325 return (dev->type == MASTER_POINTER) ||
326 (dev->valuator && dev->button) || (dev->valuator && !dev->key);
327}
328
329/*
330 * @return true if a device is a keyboard, check is the same as used by XI to
331 * fill the 'use' field.
332 *
333 * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
334 * count them as keyboard devices.
335 */
336Bool
337IsKeyboardDevice(DeviceIntPtr dev)
338{
339 return (dev->type == MASTER_KEYBOARD) ||
340 ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
341}
342
343Bool
344IsMaster(DeviceIntPtr dev)
345{
346 return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
347}
348
349Bool
350IsFloating(DeviceIntPtr dev)
351{
352 return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL;
353}
354
355/**
356 * Max event opcode.
357 */
358extern int lastEvent;
359
360#define CantBeFiltered NoEventMask
361/**
362 * Event masks for each event type.
363 *
364 * One set of filters for each device, initialized by memcpy of
365 * default_filter in InitEvents.
366 *
367 * Filters are used whether a given event may be delivered to a client,
368 * usually in the form of if (window-event-mask & filter); then deliver event.
369 *
370 * One notable filter is for PointerMotion/DevicePointerMotion events. Each
371 * time a button is pressed, the filter is modified to also contain the
372 * matching ButtonXMotion mask.
373 */
374Mask event_filters[MAXDEVICES][MAXEVENTS];
375
376static const Mask default_filter[MAXEVENTS] = {
377 NoSuchEvent, /* 0 */
378 NoSuchEvent, /* 1 */
379 KeyPressMask, /* KeyPress */
380 KeyReleaseMask, /* KeyRelease */
381 ButtonPressMask, /* ButtonPress */
382 ButtonReleaseMask, /* ButtonRelease */
383 PointerMotionMask, /* MotionNotify (initial state) */
384 EnterWindowMask, /* EnterNotify */
385 LeaveWindowMask, /* LeaveNotify */
386 FocusChangeMask, /* FocusIn */
387 FocusChangeMask, /* FocusOut */
388 KeymapStateMask, /* KeymapNotify */
389 ExposureMask, /* Expose */
390 CantBeFiltered, /* GraphicsExpose */
391 CantBeFiltered, /* NoExpose */
392 VisibilityChangeMask, /* VisibilityNotify */
393 SubstructureNotifyMask, /* CreateNotify */
394 StructureAndSubMask, /* DestroyNotify */
395 StructureAndSubMask, /* UnmapNotify */
396 StructureAndSubMask, /* MapNotify */
397 SubstructureRedirectMask, /* MapRequest */
398 StructureAndSubMask, /* ReparentNotify */
399 StructureAndSubMask, /* ConfigureNotify */
400 SubstructureRedirectMask, /* ConfigureRequest */
401 StructureAndSubMask, /* GravityNotify */
402 ResizeRedirectMask, /* ResizeRequest */
403 StructureAndSubMask, /* CirculateNotify */
404 SubstructureRedirectMask, /* CirculateRequest */
405 PropertyChangeMask, /* PropertyNotify */
406 CantBeFiltered, /* SelectionClear */
407 CantBeFiltered, /* SelectionRequest */
408 CantBeFiltered, /* SelectionNotify */
409 ColormapChangeMask, /* ColormapNotify */
410 CantBeFiltered, /* ClientMessage */
411 CantBeFiltered /* MappingNotify */
412};
413
414/**
415 * For the given event, return the matching event filter. This filter may then
416 * be AND'ed with the selected event mask.
417 *
418 * For XI2 events, the returned filter is simply the byte containing the event
419 * mask we're interested in. E.g. for a mask of (1 << 13), this would be
420 * byte[1].
421 *
422 * @param[in] dev The device the event belongs to, may be NULL.
423 * @param[in] event The event to get the filter for. Only the type of the
424 * event matters, or the extension + evtype for GenericEvents.
425 * @return The filter mask for the given event.
426 *
427 * @see GetEventMask
428 */
429Mask
430GetEventFilter(DeviceIntPtr dev, xEvent *event)
431{
432 int evtype = 0;
433
434 if (event->u.u.type != GenericEvent)
435 return event_get_filter_from_type(dev, event->u.u.type);
436 else if ((evtype = xi2_get_type(event)))
437 return event_get_filter_from_xi2type(evtype);
438 ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
439 return 0;
440}
441
442/**
443 * Return the single byte of the device's XI2 mask that contains the mask
444 * for the event_type.
445 */
446int
447GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type)
448{
449 /* we just return the matching filter because that's the only use
450 * for this mask anyway.
451 */
452 if (xi2mask_isset(mask, dev, event_type))
453 return event_get_filter_from_xi2type(event_type);
454 else
455 return 0;
456}
457
458/**
459 * @return TRUE if the mask is set for this event from this device on the
460 * window, or FALSE otherwise.
461 */
462Bool
463WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev)
464{
465 OtherInputMasks *inputMasks = wOtherInputMasks(win);
466 int evtype;
467
468 if (!inputMasks || xi2_get_type(ev) == 0)
469 return 0;
470
471 evtype = ((xGenericEvent *) ev)->evtype;
472
473 return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
474}
475
476Mask
477GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
478{
479 int evtype;
480
481 /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
482 if ((evtype = xi2_get_type(event))) {
483 return GetXI2MaskByte(other->xi2mask, dev, evtype);
484 }
485 else if (core_get_type(event) != 0)
486 return other->mask[XIAllDevices];
487 else
488 return other->mask[dev->id];
489}
490
491static CARD8 criticalEvents[32] = {
492 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */
493};
494
495static void
496SyntheticMotion(DeviceIntPtr dev, int x, int y)
497{
498 int screenno = 0;
499
500#ifdef PANORAMIX
501 if (!noPanoramiXExtension)
502 screenno = dev->spriteInfo->sprite->screen->myNum;
503#endif
504 PostSyntheticMotion(dev, x, y, screenno,
505 (syncEvents.playingEvents) ? syncEvents.time.
506 milliseconds : currentTime.milliseconds);
507
508}
509
510#ifdef PANORAMIX
511static void PostNewCursor(DeviceIntPtr pDev);
512
513static Bool
514XineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent)
515{
516 ScreenPtr pScreen;
517 int i;
518 SpritePtr pSprite = pDev->spriteInfo->sprite;
519
520 /* x,y are in Screen 0 coordinates. We need to decide what Screen
521 to send the message too and what the coordinates relative to
522 that screen are. */
523
524 pScreen = pSprite->screen;
525 x += screenInfo.screens[0]->x;
526 y += screenInfo.screens[0]->y;
527
528 if (!point_on_screen(pScreen, x, y)) {
529 FOR_NSCREENS(i) {
530 if (i == pScreen->myNum)
531 continue;
532 if (point_on_screen(screenInfo.screens[i], x, y)) {
533 pScreen = screenInfo.screens[i];
534 break;
535 }
536 }
537 }
538
539 pSprite->screen = pScreen;
540 pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
541 pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
542 x -= pScreen->x;
543 y -= pScreen->y;
544
545 return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
546}
547
548static void
549XineramaConstrainCursor(DeviceIntPtr pDev)
550{
551 SpritePtr pSprite = pDev->spriteInfo->sprite;
552 ScreenPtr pScreen;
553 BoxRec newBox;
554
555 pScreen = pSprite->screen;
556 newBox = pSprite->physLimits;
557
558 /* Translate the constraining box to the screen
559 the sprite is actually on */
560 newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
561 newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
562 newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
563 newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
564
565 (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox);
566}
567
568static Bool
569XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
570{
571 SpritePtr pSprite = pDev->spriteInfo->sprite;
572
573 if (pWin == screenInfo.screens[0]->root) {
574 int i;
575
576 FOR_NSCREENS(i)
577 pSprite->windows[i] = screenInfo.screens[i]->root;
578 }
579 else {
580 PanoramiXRes *win;
581 int rc, i;
582
583 rc = dixLookupResourceByType((pointer *) &win, pWin->drawable.id,
584 XRT_WINDOW, serverClient, DixReadAccess);
585 if (rc != Success)
586 return FALSE;
587
588 FOR_NSCREENS(i) {
589 rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
590 serverClient, DixReadAccess);
591 if (rc != Success) /* window is being unmapped */
592 return FALSE;
593 }
594 }
595 return TRUE;
596}
597
598static void
599XineramaConfineCursorToWindow(DeviceIntPtr pDev,
600 WindowPtr pWin, Bool generateEvents)
601{
602 SpritePtr pSprite = pDev->spriteInfo->sprite;
603
604 int x, y, off_x, off_y, i;
605
606 if (!XineramaSetWindowPntrs(pDev, pWin))
607 return;
608
609 i = PanoramiXNumScreens - 1;
610
611 RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize);
612 off_x = screenInfo.screens[i]->x;
613 off_y = screenInfo.screens[i]->y;
614
615 while (i--) {
616 x = off_x - screenInfo.screens[i]->x;
617 y = off_y - screenInfo.screens[i]->y;
618
619 if (x || y)
620 RegionTranslate(&pSprite->Reg1, x, y);
621
622 RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
623 &pSprite->windows[i]->borderSize);
624
625 off_x = screenInfo.screens[i]->x;
626 off_y = screenInfo.screens[i]->y;
627 }
628
629 pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
630
631 if (RegionNumRects(&pSprite->Reg1) > 1)
632 pSprite->hotShape = &pSprite->Reg1;
633 else
634 pSprite->hotShape = NullRegion;
635
636 pSprite->confined = FALSE;
637 pSprite->confineWin =
638 (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
639
640 CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
641}
642
643#endif /* PANORAMIX */
644
645/**
646 * Modifies the filter for the given protocol event type to the given masks.
647 *
648 * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
649 * The latter initialises masks for the matching XI events, it's a once-off
650 * setting.
651 * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
652 * time a button is pressed to include the matching ButtonXMotion mask in the
653 * filter.
654 *
655 * @param[in] deviceid The device to modify the filter for.
656 * @param[in] mask The new filter mask.
657 * @param[in] event Protocol event type.
658 */
659void
660SetMaskForEvent(int deviceid, Mask mask, int event)
661{
662 if (deviceid < 0 || deviceid >= MAXDEVICES)
663 FatalError("SetMaskForEvent: bogus device id");
664 event_filters[deviceid][event] = mask;
665}
666
667void
668SetCriticalEvent(int event)
669{
670 if (event >= MAXEVENTS)
671 FatalError("SetCriticalEvent: bogus event number");
672 criticalEvents[event >> 3] |= 1 << (event & 7);
673}
674
675void
676ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
677{
678 BoxRec box;
679 int x = *px, y = *py;
680 int incx = 1, incy = 1;
681
682 if (RegionContainsPoint(shape, x, y, &box))
683 return;
684 box = *RegionExtents(shape);
685 /* this is rather crude */
686 do {
687 x += incx;
688 if (x >= box.x2) {
689 incx = -1;
690 x = *px - 1;
691 }
692 else if (x < box.x1) {
693 incx = 1;
694 x = *px;
695 y += incy;
696 if (y >= box.y2) {
697 incy = -1;
698 y = *py - 1;
699 }
700 else if (y < box.y1)
701 return; /* should never get here! */
702 }
703 } while (!RegionContainsPoint(shape, x, y, &box));
704 *px = x;
705 *py = y;
706}
707
708static void
709CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents,
710 Bool confineToScreen, /* unused if PanoramiX on */
711 ScreenPtr pScreen) /* unused if PanoramiX on */
712{
713 HotSpot new;
714 SpritePtr pSprite = pDev->spriteInfo->sprite;
715
716 if (!cursor)
717 return;
718 new = pSprite->hotPhys;
719#ifdef PANORAMIX
720 if (!noPanoramiXExtension)
721 /* I don't care what the DDX has to say about it */
722 pSprite->physLimits = pSprite->hotLimits;
723 else
724#endif
725 {
726 if (pScreen)
727 new.pScreen = pScreen;
728 else
729 pScreen = new.pScreen;
730 (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
731 &pSprite->physLimits);
732 pSprite->confined = confineToScreen;
733 (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
734 }
735
736 /* constrain the pointer to those limits */
737 if (new.x < pSprite->physLimits.x1)
738 new.x = pSprite->physLimits.x1;
739 else if (new.x >= pSprite->physLimits.x2)
740 new.x = pSprite->physLimits.x2 - 1;
741 if (new.y < pSprite->physLimits.y1)
742 new.y = pSprite->physLimits.y1;
743 else if (new.y >= pSprite->physLimits.y2)
744 new.y = pSprite->physLimits.y2 - 1;
745 if (pSprite->hotShape)
746 ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
747 if ((
748#ifdef PANORAMIX
749 noPanoramiXExtension &&
750#endif
751 (pScreen != pSprite->hotPhys.pScreen)) ||
752 (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) {
753#ifdef PANORAMIX
754 if (!noPanoramiXExtension)
755 XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents);
756 else
757#endif
758 {
759 if (pScreen != pSprite->hotPhys.pScreen)
760 pSprite->hotPhys = new;
761 (*pScreen->SetCursorPosition)
762 (pDev, pScreen, new.x, new.y, generateEvents);
763 }
764 if (!generateEvents)
765 SyntheticMotion(pDev, new.x, new.y);
766 }
767
768#ifdef PANORAMIX
769 /* Tell DDX what the limits are */
770 if (!noPanoramiXExtension)
771 XineramaConstrainCursor(pDev);
772#endif
773}
774
775static void
776CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin)
777{
778 SpritePtr pSprite = pDev->spriteInfo->sprite;
779 RegionPtr reg = NULL;
780 DeviceEvent *ev = NULL;
781
782 if (qe) {
783 ev = &qe->event->device_event;
784 switch (ev->type) {
785 case ET_Motion:
786 case ET_ButtonPress:
787 case ET_ButtonRelease:
788 case ET_KeyPress:
789 case ET_KeyRelease:
790 case ET_ProximityIn:
791 case ET_ProximityOut:
792 pSprite->hot.pScreen = qe->pScreen;
793 pSprite->hot.x = ev->root_x;
794 pSprite->hot.y = ev->root_y;
795 pWin =
796 pDev->deviceGrab.grab ? pDev->deviceGrab.grab->
797 confineTo : NullWindow;
798 break;
799 default:
800 break;
801 }
802 }
803 if (pWin) {
804 BoxRec lims;
805
806#ifdef PANORAMIX
807 if (!noPanoramiXExtension) {
808 int x, y, off_x, off_y, i;
809
810 if (!XineramaSetWindowPntrs(pDev, pWin))
811 return;
812
813 i = PanoramiXNumScreens - 1;
814
815 RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize);
816 off_x = screenInfo.screens[i]->x;
817 off_y = screenInfo.screens[i]->y;
818
819 while (i--) {
820 x = off_x - screenInfo.screens[i]->x;
821 y = off_y - screenInfo.screens[i]->y;
822
823 if (x || y)
824 RegionTranslate(&pSprite->Reg2, x, y);
825
826 RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
827 &pSprite->windows[i]->borderSize);
828
829 off_x = screenInfo.screens[i]->x;
830 off_y = screenInfo.screens[i]->y;
831 }
832 }
833 else
834#endif
835 {
836 if (pSprite->hot.pScreen != pWin->drawable.pScreen) {
837 pSprite->hot.pScreen = pWin->drawable.pScreen;
838 pSprite->hot.x = pSprite->hot.y = 0;
839 }
840 }
841
842 lims = *RegionExtents(&pWin->borderSize);
843 if (pSprite->hot.x < lims.x1)
844 pSprite->hot.x = lims.x1;
845 else if (pSprite->hot.x >= lims.x2)
846 pSprite->hot.x = lims.x2 - 1;
847 if (pSprite->hot.y < lims.y1)
848 pSprite->hot.y = lims.y1;
849 else if (pSprite->hot.y >= lims.y2)
850 pSprite->hot.y = lims.y2 - 1;
851
852#ifdef PANORAMIX
853 if (!noPanoramiXExtension) {
854 if (RegionNumRects(&pSprite->Reg2) > 1)
855 reg = &pSprite->Reg2;
856
857 }
858 else
859#endif
860 {
861 if (wBoundingShape(pWin))
862 reg = &pWin->borderSize;
863 }
864
865 if (reg)
866 ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
867
868 if (qe && ev) {
869 qe->pScreen = pSprite->hot.pScreen;
870 ev->root_x = pSprite->hot.x;
871 ev->root_y = pSprite->hot.y;
872 }
873 }
874#ifdef PANORAMIX
875 if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */
876#endif
877 RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
878}
879
880static void
881ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents,
882 Bool confineToScreen)
883{
884 SpritePtr pSprite = pDev->spriteInfo->sprite;
885
886 if (syncEvents.playingEvents) {
887 CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin);
888 SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
889 }
890 else {
891#ifdef PANORAMIX
892 if (!noPanoramiXExtension) {
893 XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
894 return;
895 }
896#endif
897 pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
898 pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
899 : NullRegion;
900 CheckPhysLimits(pDev, pSprite->current, generateEvents,
901 confineToScreen, pWin->drawable.pScreen);
902 }
903}
904
905Bool
906PointerConfinedToScreen(DeviceIntPtr pDev)
907{
908 return pDev->spriteInfo->sprite->confined;
909}
910
911/**
912 * Update the sprite cursor to the given cursor.
913 *
914 * ChangeToCursor() will display the new cursor and free the old cursor (if
915 * applicable). If the provided cursor is already the updated cursor, nothing
916 * happens.
917 */
918static void
919ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
920{
921 SpritePtr pSprite = pDev->spriteInfo->sprite;
922 ScreenPtr pScreen;
923
924 if (cursor != pSprite->current) {
925 if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
926 (pSprite->current->bits->yhot != cursor->bits->yhot))
927 CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
928 (ScreenPtr) NULL);
929#ifdef PANORAMIX
930 /* XXX: is this really necessary?? (whot) */
931 if (!noPanoramiXExtension)
932 pScreen = pSprite->screen;
933 else
934#endif
935 pScreen = pSprite->hotPhys.pScreen;
936
937 (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
938 FreeCursor(pSprite->current, (Cursor) 0);
939 pSprite->current = RefCursor(cursor);
940 }
941}
942
943/**
944 * @returns true if b is a descendent of a
945 */
946Bool
947IsParent(WindowPtr a, WindowPtr b)
948{
949 for (b = b->parent; b; b = b->parent)
950 if (b == a)
951 return TRUE;
952 return FALSE;
953}
954
955/**
956 * Update the cursor displayed on the screen.
957 *
958 * Called whenever a cursor may have changed shape or position.
959 */
960static void
961PostNewCursor(DeviceIntPtr pDev)
962{
963 WindowPtr win;
964 GrabPtr grab = pDev->deviceGrab.grab;
965 SpritePtr pSprite = pDev->spriteInfo->sprite;
966 CursorPtr pCursor;
967
968 if (syncEvents.playingEvents)
969 return;
970 if (grab) {
971 if (grab->cursor) {
972 ChangeToCursor(pDev, grab->cursor);
973 return;
974 }
975 if (IsParent(grab->window, pSprite->win))
976 win = pSprite->win;
977 else
978 win = grab->window;
979 }
980 else
981 win = pSprite->win;
982 for (; win; win = win->parent) {
983 if (win->optional) {
984 pCursor = WindowGetDeviceCursor(win, pDev);
985 if (!pCursor && win->optional->cursor != NullCursor)
986 pCursor = win->optional->cursor;
987 if (pCursor) {
988 ChangeToCursor(pDev, pCursor);
989 return;
990 }
991 }
992 }
993}
994
995/**
996 * @param dev device which you want to know its current root window
997 * @return root window where dev's sprite is located
998 */
999WindowPtr
1000GetCurrentRootWindow(DeviceIntPtr dev)
1001{
1002 return RootWindow(dev->spriteInfo->sprite);
1003}
1004
1005/**
1006 * @return window underneath the cursor sprite.
1007 */
1008WindowPtr
1009GetSpriteWindow(DeviceIntPtr pDev)
1010{
1011 return pDev->spriteInfo->sprite->win;
1012}
1013
1014/**
1015 * @return current sprite cursor.
1016 */
1017CursorPtr
1018GetSpriteCursor(DeviceIntPtr pDev)
1019{
1020 return pDev->spriteInfo->sprite->current;
1021}
1022
1023/**
1024 * Set x/y current sprite position in screen coordinates.
1025 */
1026void
1027GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
1028{
1029 SpritePtr pSprite = pDev->spriteInfo->sprite;
1030
1031 *px = pSprite->hotPhys.x;
1032 *py = pSprite->hotPhys.y;
1033}
1034
1035#ifdef PANORAMIX
1036int
1037XineramaGetCursorScreen(DeviceIntPtr pDev)
1038{
1039 if (!noPanoramiXExtension) {
1040 return pDev->spriteInfo->sprite->screen->myNum;
1041 }
1042 else {
1043 return 0;
1044 }
1045}
1046#endif /* PANORAMIX */
1047
1048#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
1049
1050static void
1051MonthChangedOrBadTime(CARD32 *ms)
1052{
1053 /* If the ddx/OS is careless about not processing timestamped events from
1054 * different sources in sorted order, then it's possible for time to go
1055 * backwards when it should not. Here we ensure a decent time.
1056 */
1057 if ((currentTime.milliseconds - *ms) > TIMESLOP)
1058 currentTime.months++;
1059 else
1060 *ms = currentTime.milliseconds;
1061}
1062
1063void
1064NoticeTime(const DeviceIntPtr dev, TimeStamp time)
1065{
1066 lastDeviceEventTime[XIAllDevices].time = currentTime;
1067 lastDeviceEventTime[dev->id].time = currentTime;
1068
1069 LastEventTimeToggleResetFlag(dev->id, TRUE);
1070 LastEventTimeToggleResetFlag(XIAllDevices, TRUE);
1071}
1072
1073static void
1074NoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms)
1075{
1076 TimeStamp time;
1077 if (*ms < currentTime.milliseconds)
1078 MonthChangedOrBadTime(ms);
1079 time.months = currentTime.months;
1080 time.milliseconds = *ms;
1081 NoticeTime(dev, time);
1082}
1083
1084void
1085NoticeEventTime(InternalEvent *ev, DeviceIntPtr dev)
1086{
1087 if (!syncEvents.playingEvents)
1088 NoticeTimeMillis(dev, &ev->any.time);
1089}
1090
1091TimeStamp
1092LastEventTime(int deviceid)
1093{
1094 return lastDeviceEventTime[deviceid].time;
1095}
1096
1097Bool
1098LastEventTimeWasReset(int deviceid)
1099{
1100 return lastDeviceEventTime[deviceid].reset;
1101}
1102
1103void
1104LastEventTimeToggleResetFlag(int deviceid, Bool state)
1105{
1106 lastDeviceEventTime[deviceid].reset = state;
1107}
1108
1109void
1110LastEventTimeToggleResetAll(Bool state)
1111{
1112 DeviceIntPtr dev;
1113 nt_list_for_each_entry(dev, inputInfo.devices, next) {
1114 LastEventTimeToggleResetFlag(dev->id, FALSE);
1115 }
1116 LastEventTimeToggleResetFlag(XIAllDevices, FALSE);
1117 LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE);
1118}
1119
1120/**************************************************************************
1121 * The following procedures deal with synchronous events *
1122 **************************************************************************/
1123
1124/**
1125 * EnqueueEvent is a device's processInputProc if a device is frozen.
1126 * Instead of delivering the events to the client, the event is tacked onto a
1127 * linked list for later delivery.
1128 */
1129void
1130EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
1131{
1132 QdEventPtr tail = NULL;
1133 QdEventPtr qe;
1134 SpritePtr pSprite = device->spriteInfo->sprite;
1135 int eventlen;
1136 DeviceEvent *event = &ev->device_event;
1137
1138 if (!xorg_list_is_empty(&syncEvents.pending))
1139 tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next);
1140
1141 NoticeTimeMillis(device, &ev->any.time);
1142
1143 /* Fix for key repeating bug. */
1144 if (device->key != NULL && device->key->xkbInfo != NULL &&
1145 event->type == ET_KeyRelease)
1146 AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
1147
1148 if (DeviceEventCallback) {
1149 DeviceEventInfoRec eventinfo;
1150
1151 /* The RECORD spec says that the root window field of motion events
1152 * must be valid. At this point, it hasn't been filled in yet, so
1153 * we do it here. The long expression below is necessary to get
1154 * the current root window; the apparently reasonable alternative
1155 * GetCurrentRootWindow()->drawable.id doesn't give you the right
1156 * answer on the first motion event after a screen change because
1157 * the data that GetCurrentRootWindow relies on hasn't been
1158 * updated yet.
1159 */
1160 if (ev->any.type == ET_Motion)
1161 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1162
1163 eventinfo.event = ev;
1164 eventinfo.device = device;
1165 CallCallbacks(&DeviceEventCallback, (pointer) &eventinfo);
1166 }
1167
1168 if (event->type == ET_Motion) {
1169#ifdef PANORAMIX
1170 if (!noPanoramiXExtension) {
1171 event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
1172 event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
1173 }
1174#endif
1175 pSprite->hotPhys.x = event->root_x;
1176 pSprite->hotPhys.y = event->root_y;
1177 /* do motion compression, but not if from different devices */
1178 if (tail &&
1179 (tail->event->any.type == ET_Motion) &&
1180 (tail->device == device) &&
1181 (tail->pScreen == pSprite->hotPhys.pScreen)) {
1182 DeviceEvent *tailev = &tail->event->device_event;
1183
1184 tailev->root_x = pSprite->hotPhys.x;
1185 tailev->root_y = pSprite->hotPhys.y;
1186 tailev->time = event->time;
1187 tail->months = currentTime.months;
1188 return;
1189 }
1190 }
1191
1192 eventlen = event->length;
1193
1194 qe = malloc(sizeof(QdEventRec) + eventlen);
1195 if (!qe)
1196 return;
1197 xorg_list_init(&qe->next);
1198 qe->device = device;
1199 qe->pScreen = pSprite->hotPhys.pScreen;
1200 qe->months = currentTime.months;
1201 qe->event = (InternalEvent *) (qe + 1);
1202 memcpy(qe->event, event, eventlen);
1203 xorg_list_append(&qe->next, &syncEvents.pending);
1204}
1205
1206/**
1207 * Run through the list of events queued up in syncEvents.
1208 * For each event do:
1209 * If the device for this event is not frozen anymore, take it and process it
1210 * as usually.
1211 * After that, check if there's any devices in the list that are not frozen.
1212 * If there is none, we're done. If there is at least one device that is not
1213 * frozen, then re-run from the beginning of the event queue.
1214 */
1215void
1216PlayReleasedEvents(void)
1217{
1218 QdEventPtr tmp;
1219 QdEventPtr qe;
1220 DeviceIntPtr dev;
1221 DeviceIntPtr pDev;
1222
1223 restart:
1224 xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
1225 if (!qe->device->deviceGrab.sync.frozen) {
1226 xorg_list_del(&qe->next);
1227 pDev = qe->device;
1228 if (qe->event->any.type == ET_Motion)
1229 CheckVirtualMotion(pDev, qe, NullWindow);
1230 syncEvents.time.months = qe->months;
1231 syncEvents.time.milliseconds = qe->event->any.time;
1232#ifdef PANORAMIX
1233 /* Translate back to the sprite screen since processInputProc
1234 will translate from sprite screen to screen 0 upon reentry
1235 to the DIX layer */
1236 if (!noPanoramiXExtension) {
1237 DeviceEvent *ev = &qe->event->device_event;
1238
1239 switch (ev->type) {
1240 case ET_Motion:
1241 case ET_ButtonPress:
1242 case ET_ButtonRelease:
1243 case ET_KeyPress:
1244 case ET_KeyRelease:
1245 case ET_ProximityIn:
1246 case ET_ProximityOut:
1247 case ET_TouchBegin:
1248 case ET_TouchUpdate:
1249 case ET_TouchEnd:
1250 ev->root_x += screenInfo.screens[0]->x -
1251 pDev->spriteInfo->sprite->screen->x;
1252 ev->root_y += screenInfo.screens[0]->y -
1253 pDev->spriteInfo->sprite->screen->y;
1254 break;
1255 default:
1256 break;
1257 }
1258
1259 }
1260#endif
1261 (*qe->device->public.processInputProc) (qe->event, qe->device);
1262 free(qe);
1263 for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen;
1264 dev = dev->next);
1265 if (!dev)
1266 break;
1267
1268 /* Playing the event may have unfrozen another device. */
1269 /* So to play it safe, restart at the head of the queue */
1270 goto restart;
1271 }
1272 }
1273}
1274
1275/**
1276 * Freeze or thaw the given devices. The device's processing proc is
1277 * switched to either the real processing proc (in case of thawing) or an
1278 * enqueuing processing proc (usually EnqueueEvent()).
1279 *
1280 * @param dev The device to freeze/thaw
1281 * @param frozen True to freeze or false to thaw.
1282 */
1283static void
1284FreezeThaw(DeviceIntPtr dev, Bool frozen)
1285{
1286 dev->deviceGrab.sync.frozen = frozen;
1287 if (frozen)
1288 dev->public.processInputProc = dev->public.enqueueInputProc;
1289 else
1290 dev->public.processInputProc = dev->public.realInputProc;
1291}
1292
1293/**
1294 * Unfreeze devices and replay all events to the respective clients.
1295 *
1296 * ComputeFreezes takes the first event in the device's frozen event queue. It
1297 * runs up the sprite tree (spriteTrace) and searches for the window to replay
1298 * the events from. If it is found, it checks for passive grabs one down from
1299 * the window or delivers the events.
1300 */
1301static void
1302ComputeFreezes(void)
1303{
1304 DeviceIntPtr replayDev = syncEvents.replayDev;
1305 WindowPtr w;
1306 GrabPtr grab;
1307 DeviceIntPtr dev;
1308
1309 for (dev = inputInfo.devices; dev; dev = dev->next)
1310 FreezeThaw(dev, dev->deviceGrab.sync.other ||
1311 (dev->deviceGrab.sync.state >= FROZEN));
1312 if (syncEvents.playingEvents ||
1313 (!replayDev && xorg_list_is_empty(&syncEvents.pending)))
1314 return;
1315 syncEvents.playingEvents = TRUE;
1316 if (replayDev) {
1317 DeviceEvent *event = replayDev->deviceGrab.sync.event;
1318
1319 syncEvents.replayDev = (DeviceIntPtr) NULL;
1320
1321 w = XYToWindow(replayDev->spriteInfo->sprite,
1322 event->root_x, event->root_y);
1323 if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) {
1324 if (IsTouchEvent((InternalEvent *) event)) {
1325 TouchPointInfoPtr ti =
1326 TouchFindByClientID(replayDev, event->touchid);
1327 BUG_WARN(!ti);
1328
1329 TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
1330 }
1331 else if (replayDev->focus &&
1332 !IsPointerEvent((InternalEvent *) event))
1333 DeliverFocusedEvent(replayDev, (InternalEvent *) event, w);
1334 else
1335 DeliverDeviceEvents(w, (InternalEvent *) event, NullGrab,
1336 NullWindow, replayDev);
1337 }
1338 }
1339 for (dev = inputInfo.devices; dev; dev = dev->next) {
1340 if (!dev->deviceGrab.sync.frozen) {
1341 PlayReleasedEvents();
1342 break;
1343 }
1344 }
1345 syncEvents.playingEvents = FALSE;
1346 for (dev = inputInfo.devices; dev; dev = dev->next) {
1347 if (DevHasCursor(dev)) {
1348 /* the following may have been skipped during replay,
1349 so do it now */
1350 if ((grab = dev->deviceGrab.grab) && grab->confineTo) {
1351 if (grab->confineTo->drawable.pScreen !=
1352 dev->spriteInfo->sprite->hotPhys.pScreen)
1353 dev->spriteInfo->sprite->hotPhys.x =
1354 dev->spriteInfo->sprite->hotPhys.y = 0;
1355 ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
1356 }
1357 else
1358 ConfineCursorToWindow(dev,
1359 dev->spriteInfo->sprite->hotPhys.pScreen->
1360 root, TRUE, FALSE);
1361 PostNewCursor(dev);
1362 }
1363 }
1364}
1365
1366#ifdef RANDR
1367void
1368ScreenRestructured(ScreenPtr pScreen)
1369{
1370 GrabPtr grab;
1371 DeviceIntPtr pDev;
1372
1373 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
1374 if (!IsFloating(pDev) && !DevHasCursor(pDev))
1375 continue;
1376
1377 /* GrabDevice doesn't have a confineTo field, so we don't need to
1378 * worry about it. */
1379 if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
1380 if (grab->confineTo->drawable.pScreen
1381 != pDev->spriteInfo->sprite->hotPhys.pScreen)
1382 pDev->spriteInfo->sprite->hotPhys.x =
1383 pDev->spriteInfo->sprite->hotPhys.y = 0;
1384 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
1385 }
1386 else
1387 ConfineCursorToWindow(pDev,
1388 pDev->spriteInfo->sprite->hotPhys.pScreen->
1389 root, TRUE, FALSE);
1390 }
1391}
1392#endif
1393
1394static void
1395CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
1396{
1397 GrabPtr grab = thisDev->deviceGrab.grab;
1398 DeviceIntPtr dev;
1399
1400 if (thisMode == GrabModeSync)
1401 thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
1402 else { /* free both if same client owns both */
1403 thisDev->deviceGrab.sync.state = THAWED;
1404 if (thisDev->deviceGrab.sync.other &&
1405 (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
1406 CLIENT_BITS(grab->resource)))
1407 thisDev->deviceGrab.sync.other = NullGrab;
1408 }
1409
1410 if (IsMaster(thisDev)) {
1411 dev = GetPairedDevice(thisDev);
1412 if (otherMode == GrabModeSync)
1413 dev->deviceGrab.sync.other = grab;
1414 else { /* free both if same client owns both */
1415 if (dev->deviceGrab.sync.other &&
1416 (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
1417 CLIENT_BITS(grab->resource)))
1418 dev->deviceGrab.sync.other = NullGrab;
1419 }
1420 }
1421 ComputeFreezes();
1422}
1423
1424/**
1425 * Save the device's master device id. This needs to be done
1426 * if a client directly grabs a slave device that is attached to a master. For
1427 * the duration of the grab, the device is detached, ungrabbing re-attaches it
1428 * though.
1429 *
1430 * We store the ID of the master device only in case the master disappears
1431 * while the device has a grab.
1432 */
1433static void
1434DetachFromMaster(DeviceIntPtr dev)
1435{
1436 if (IsFloating(dev))
1437 return;
1438
1439 dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
1440
1441 AttachDevice(NULL, dev, NULL);
1442}
1443
1444static void
1445ReattachToOldMaster(DeviceIntPtr dev)
1446{
1447 DeviceIntPtr master = NULL;
1448
1449 if (IsMaster(dev))
1450 return;
1451
1452 dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
1453
1454 if (master) {
1455 AttachDevice(serverClient, dev, master);
1456 dev->saved_master_id = 0;
1457 }
1458}
1459
1460/**
1461 * Update touch records when an explicit grab is activated. Any touches owned by
1462 * the grabbing client are updated so the listener state reflects the new grab.
1463 */
1464static void
1465UpdateTouchesForGrab(DeviceIntPtr mouse)
1466{
1467 int i;
1468
1469 if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
1470 return;
1471
1472 for (i = 0; i < mouse->touch->num_touches; i++) {
1473 TouchPointInfoPtr ti = mouse->touch->touches + i;
1474 TouchListener *listener = &ti->listeners[0];
1475 GrabPtr grab = mouse->deviceGrab.grab;
1476
1477 if (ti->active &&
1478 CLIENT_BITS(listener->listener) == grab->resource) {
1479 listener->listener = grab->resource;
1480 listener->level = grab->grabtype;
1481 listener->state = LISTENER_IS_OWNER;
1482 listener->window = grab->window;
1483
1484 if (grab->grabtype == CORE || grab->grabtype == XI ||
1485 !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
1486 listener->type = LISTENER_POINTER_GRAB;
1487 else
1488 listener->type = LISTENER_GRAB;
1489 if (listener->grab)
1490 FreeGrab(listener->grab);
1491 listener->grab = AllocGrab(grab);
1492 }
1493 }
1494}
1495
1496/**
1497 * Activate a pointer grab on the given device. A pointer grab will cause all
1498 * core pointer events of this device to be delivered to the grabbing client only.
1499 * No other device will send core events to the grab client while the grab is
1500 * on, but core events will be sent to other clients.
1501 * Can cause the cursor to change if a grab cursor is set.
1502 *
1503 * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
1504 * is an implicit grab caused by a ButtonPress event.
1505 *
1506 * @param mouse The device to grab.
1507 * @param grab The grab structure, needs to be setup.
1508 * @param autoGrab True if the grab was caused by a button down event and not
1509 * explicitely by a client.
1510 */
1511void
1512ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
1513 TimeStamp time, Bool autoGrab)
1514{
1515 GrabInfoPtr grabinfo = &mouse->deviceGrab;
1516 GrabPtr oldgrab = grabinfo->grab;
1517 WindowPtr oldWin = (grabinfo->grab) ?
1518 grabinfo->grab->window : mouse->spriteInfo->sprite->win;
1519 Bool isPassive = autoGrab & ~ImplicitGrabMask;
1520
1521 /* slave devices need to float for the duration of the grab. */
1522 if (grab->grabtype == XI2 &&
1523 !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
1524 DetachFromMaster(mouse);
1525
1526 if (grab->confineTo) {
1527 if (grab->confineTo->drawable.pScreen
1528 != mouse->spriteInfo->sprite->hotPhys.pScreen)
1529 mouse->spriteInfo->sprite->hotPhys.x =
1530 mouse->spriteInfo->sprite->hotPhys.y = 0;
1531 ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
1532 }
1533 DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
1534 mouse->valuator->motionHintWindow = NullWindow;
1535 if (syncEvents.playingEvents)
1536 grabinfo->grabTime = syncEvents.time;
1537 else
1538 grabinfo->grabTime = time;
1539 grabinfo->grab = AllocGrab(grab);
1540 grabinfo->fromPassiveGrab = isPassive;
1541 grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
1542 PostNewCursor(mouse);
1543 UpdateTouchesForGrab(mouse);
1544 CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
1545 (Bool) grab->keyboardMode);
1546 if (oldgrab)
1547 FreeGrab(oldgrab);
1548}
1549
1550/**
1551 * Delete grab on given device, update the sprite.
1552 *
1553 * Extension devices are set up for ActivateKeyboardGrab().
1554 */
1555void
1556DeactivatePointerGrab(DeviceIntPtr mouse)
1557{
1558 GrabPtr grab = mouse->deviceGrab.grab;
1559 DeviceIntPtr dev;
1560 Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
1561 Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
1562 mouse->deviceGrab.implicitGrab);
1563 XID grab_resource = grab->resource;
1564 int i;
1565
1566 /* If an explicit grab was deactivated, we must remove it from the head of
1567 * all the touches' listener lists. */
1568 for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
1569 TouchPointInfoPtr ti = mouse->touch->touches + i;
1570 if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
1571 int mode = XIRejectTouch;
1572 /* Rejecting will generate a TouchEnd, but we must not
1573 emulate a ButtonRelease here. So pretend the listener
1574 already has the end event */
1575 if (grab->grabtype == CORE || grab->grabtype == XI ||
1576 !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) {
1577 mode = XIAcceptTouch;
1578 /* NOTE: we set the state here, but
1579 * ProcessTouchOwnershipEvent() will still call
1580 * TouchEmitTouchEnd for this listener. The other half of
1581 * this hack is in DeliverTouchEndEvent */
1582 ti->listeners[0].state = LISTENER_HAS_END;
1583 }
1584 TouchListenerAcceptReject(mouse, ti, 0, mode);
1585 }
1586 }
1587
1588 TouchRemovePointerGrab(mouse);
1589
1590 mouse->valuator->motionHintWindow = NullWindow;
1591 mouse->deviceGrab.grab = NullGrab;
1592 mouse->deviceGrab.sync.state = NOT_GRABBED;
1593 mouse->deviceGrab.fromPassiveGrab = FALSE;
1594
1595 for (dev = inputInfo.devices; dev; dev = dev->next) {
1596 if (dev->deviceGrab.sync.other == grab)
1597 dev->deviceGrab.sync.other = NullGrab;
1598 }
1599 DoEnterLeaveEvents(mouse, mouse->id, grab->window,
1600 mouse->spriteInfo->sprite->win, NotifyUngrab);
1601 if (grab->confineTo)
1602 ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
1603 PostNewCursor(mouse);
1604
1605 if (!wasImplicit && grab->grabtype == XI2)
1606 ReattachToOldMaster(mouse);
1607
1608 ComputeFreezes();
1609
1610 FreeGrab(grab);
1611}
1612
1613/**
1614 * Activate a keyboard grab on the given device.
1615 *
1616 * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1617 */
1618void
1619ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
1620 Bool passive)
1621{
1622 GrabInfoPtr grabinfo = &keybd->deviceGrab;
1623 GrabPtr oldgrab = grabinfo->grab;
1624 WindowPtr oldWin;
1625
1626 /* slave devices need to float for the duration of the grab. */
1627 if (grab->grabtype == XI2 && keybd->enabled &&
1628 !(passive & ImplicitGrabMask) && !IsMaster(keybd))
1629 DetachFromMaster(keybd);
1630
1631 if (!keybd->enabled)
1632 oldWin = NULL;
1633 else if (grabinfo->grab)
1634 oldWin = grabinfo->grab->window;
1635 else if (keybd->focus)
1636 oldWin = keybd->focus->win;
1637 else
1638 oldWin = keybd->spriteInfo->sprite->win;
1639 if (oldWin == FollowKeyboardWin)
1640 oldWin = keybd->focus->win;
1641 if (keybd->valuator)
1642 keybd->valuator->motionHintWindow = NullWindow;
1643 if (oldWin)
1644 DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
1645 if (syncEvents.playingEvents)
1646 grabinfo->grabTime = syncEvents.time;
1647 else
1648 grabinfo->grabTime = time;
1649 grabinfo->grab = AllocGrab(grab);
1650 grabinfo->fromPassiveGrab = passive;
1651 grabinfo->implicitGrab = passive & ImplicitGrabMask;
1652 CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode,
1653 (Bool) grab->pointerMode);
1654 if (oldgrab)
1655 FreeGrab(oldgrab);
1656}
1657
1658/**
1659 * Delete keyboard grab for the given device.
1660 */
1661void
1662DeactivateKeyboardGrab(DeviceIntPtr keybd)
1663{
1664 GrabPtr grab = keybd->deviceGrab.grab;
1665 DeviceIntPtr dev;
1666 WindowPtr focusWin;
1667 Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
1668 keybd->deviceGrab.implicitGrab);
1669
1670 if (keybd->valuator)
1671 keybd->valuator->motionHintWindow = NullWindow;
1672 keybd->deviceGrab.grab = NullGrab;
1673 keybd->deviceGrab.sync.state = NOT_GRABBED;
1674 keybd->deviceGrab.fromPassiveGrab = FALSE;
1675
1676 for (dev = inputInfo.devices; dev; dev = dev->next) {
1677 if (dev->deviceGrab.sync.other == grab)
1678 dev->deviceGrab.sync.other = NullGrab;
1679 }
1680
1681 if (keybd->focus)
1682 focusWin = keybd->focus->win;
1683 else if (keybd->spriteInfo->sprite)
1684 focusWin = keybd->spriteInfo->sprite->win;
1685 else
1686 focusWin = NullWindow;
1687
1688 if (focusWin == FollowKeyboardWin)
1689 focusWin = inputInfo.keyboard->focus->win;
1690
1691 DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
1692
1693 if (!wasImplicit && grab->grabtype == XI2)
1694 ReattachToOldMaster(keybd);
1695
1696 ComputeFreezes();
1697
1698 FreeGrab(grab);
1699}
1700
1701void
1702AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
1703{
1704 Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
1705 TimeStamp grabTime;
1706 DeviceIntPtr dev;
1707 GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab;
1708
1709 thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
1710 thisSynced = FALSE;
1711 otherGrabbed = FALSE;
1712 othersFrozen = FALSE;
1713 grabTime = grabinfo->grabTime;
1714 for (dev = inputInfo.devices; dev; dev = dev->next) {
1715 devgrabinfo = &dev->deviceGrab;
1716
1717 if (dev == thisDev)
1718 continue;
1719 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) {
1720 if (!(thisGrabbed || otherGrabbed) ||
1721 (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
1722 grabTime = devgrabinfo->grabTime;
1723 otherGrabbed = TRUE;
1724 if (grabinfo->sync.other == devgrabinfo->grab)
1725 thisSynced = TRUE;
1726 if (devgrabinfo->sync.state >= FROZEN)
1727 othersFrozen = TRUE;
1728 }
1729 }
1730 if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
1731 return;
1732 if ((CompareTimeStamps(time, currentTime) == LATER) ||
1733 (CompareTimeStamps(time, grabTime) == EARLIER))
1734 return;
1735 switch (newState) {
1736 case THAWED: /* Async */
1737 if (thisGrabbed)
1738 grabinfo->sync.state = THAWED;
1739 if (thisSynced)
1740 grabinfo->sync.other = NullGrab;
1741 ComputeFreezes();
1742 break;
1743 case FREEZE_NEXT_EVENT: /* Sync */
1744 if (thisGrabbed) {
1745 grabinfo->sync.state = FREEZE_NEXT_EVENT;
1746 if (thisSynced)
1747 grabinfo->sync.other = NullGrab;
1748 ComputeFreezes();
1749 }
1750 break;
1751 case THAWED_BOTH: /* AsyncBoth */
1752 if (othersFrozen) {
1753 for (dev = inputInfo.devices; dev; dev = dev->next) {
1754 devgrabinfo = &dev->deviceGrab;
1755 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1756 devgrabinfo->sync.state = THAWED;
1757 if (devgrabinfo->sync.other &&
1758 SameClient(devgrabinfo->sync.other, client))
1759 devgrabinfo->sync.other = NullGrab;
1760 }
1761 ComputeFreezes();
1762 }
1763 break;
1764 case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
1765 if (othersFrozen) {
1766 for (dev = inputInfo.devices; dev; dev = dev->next) {
1767 devgrabinfo = &dev->deviceGrab;
1768 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1769 devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
1770 if (devgrabinfo->sync.other
1771 && SameClient(devgrabinfo->sync.other, client))
1772 devgrabinfo->sync.other = NullGrab;
1773 }
1774 ComputeFreezes();
1775 }
1776 break;
1777 case NOT_GRABBED: /* Replay */
1778 if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) {
1779 if (thisSynced)
1780 grabinfo->sync.other = NullGrab;
1781 syncEvents.replayDev = thisDev;
1782 syncEvents.replayWin = grabinfo->grab->window;
1783 (*grabinfo->DeactivateGrab) (thisDev);
1784 syncEvents.replayDev = (DeviceIntPtr) NULL;
1785 }
1786 break;
1787 case THAW_OTHERS: /* AsyncOthers */
1788 if (othersFrozen) {
1789 for (dev = inputInfo.devices; dev; dev = dev->next) {
1790 if (dev == thisDev)
1791 continue;
1792 devgrabinfo = &dev->deviceGrab;
1793 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1794 devgrabinfo->sync.state = THAWED;
1795 if (devgrabinfo->sync.other
1796 && SameClient(devgrabinfo->sync.other, client))
1797 devgrabinfo->sync.other = NullGrab;
1798 }
1799 ComputeFreezes();
1800 }
1801 break;
1802 }
1803
1804 /* We've unfrozen the grab. If the grab was a touch grab, we're now the
1805 * owner and expected to accept/reject it. Reject == ReplayPointer which
1806 * we've handled in ComputeFreezes() (during DeactivateGrab) above,
1807 * anything else is accept.
1808 */
1809 if (newState != NOT_GRABBED /* Replay */ &&
1810 IsTouchEvent((InternalEvent*)grabinfo->sync.event)) {
1811 TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid);
1812 }
1813}
1814
1815/**
1816 * Server-side protocol handling for AllowEvents request.
1817 *
1818 * Release some events from a frozen device.
1819 */
1820int
1821ProcAllowEvents(ClientPtr client)
1822{
1823 TimeStamp time;
1824 DeviceIntPtr mouse = NULL;
1825 DeviceIntPtr keybd = NULL;
1826
1827 REQUEST(xAllowEventsReq);
1828
1829 REQUEST_SIZE_MATCH(xAllowEventsReq);
1830 time = ClientTimeToServerTime(stuff->time);
1831
1832 mouse = PickPointer(client);
1833 keybd = PickKeyboard(client);
1834
1835 switch (stuff->mode) {
1836 case ReplayPointer:
1837 AllowSome(client, time, mouse, NOT_GRABBED);
1838 break;
1839 case SyncPointer:
1840 AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
1841 break;
1842 case AsyncPointer:
1843 AllowSome(client, time, mouse, THAWED);
1844 break;
1845 case ReplayKeyboard:
1846 AllowSome(client, time, keybd, NOT_GRABBED);
1847 break;
1848 case SyncKeyboard:
1849 AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
1850 break;
1851 case AsyncKeyboard:
1852 AllowSome(client, time, keybd, THAWED);
1853 break;
1854 case SyncBoth:
1855 AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
1856 break;
1857 case AsyncBoth:
1858 AllowSome(client, time, keybd, THAWED_BOTH);
1859 break;
1860 default:
1861 client->errorValue = stuff->mode;
1862 return BadValue;
1863 }
1864 return Success;
1865}
1866
1867/**
1868 * Deactivate grabs from any device that has been grabbed by the client.
1869 */
1870void
1871ReleaseActiveGrabs(ClientPtr client)
1872{
1873 DeviceIntPtr dev;
1874 Bool done;
1875
1876 /* XXX CloseDownClient should remove passive grabs before
1877 * releasing active grabs.
1878 */
1879 do {
1880 done = TRUE;
1881 for (dev = inputInfo.devices; dev; dev = dev->next) {
1882 if (dev->deviceGrab.grab &&
1883 SameClient(dev->deviceGrab.grab, client)) {
1884 (*dev->deviceGrab.DeactivateGrab) (dev);
1885 done = FALSE;
1886 }
1887 }
1888 } while (!done);
1889}
1890
1891/**************************************************************************
1892 * The following procedures deal with delivering events *
1893 **************************************************************************/
1894
1895/**
1896 * Deliver the given events to the given client.
1897 *
1898 * More than one event may be delivered at a time. This is the case with
1899 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1900 *
1901 * TryClientEvents() is the last station before actually writing the events to
1902 * the socket. Anything that is not filtered here, will get delivered to the
1903 * client.
1904 * An event is only delivered if
1905 * - mask and filter match up.
1906 * - no other client has a grab on the device that caused the event.
1907 *
1908 *
1909 * @param client The target client to deliver to.
1910 * @param dev The device the event came from. May be NULL.
1911 * @param pEvents The events to be delivered.
1912 * @param count Number of elements in pEvents.
1913 * @param mask Event mask as set by the window.
1914 * @param filter Mask based on event type.
1915 * @param grab Possible grab on the device that caused the event.
1916 *
1917 * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1918 * client.
1919 */
1920int
1921TryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
1922 int count, Mask mask, Mask filter, GrabPtr grab)
1923{
1924 int type;
1925
1926#ifdef DEBUG_EVENTS
1927 ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
1928 pEvents->u.u.type, pEvents->u.u.detail, mask,
1929 client ? client->index : -1,
1930 (client && client->clientGone) ? " (gone)" : "");
1931#endif
1932
1933 if (!client || client == serverClient || client->clientGone) {
1934#ifdef DEBUG_EVENTS
1935 ErrorF(" not delivered to fake/dead client\n");
1936#endif
1937 return 0;
1938 }
1939
1940 if (filter != CantBeFiltered && !(mask & filter)) {
1941#ifdef DEBUG_EVENTS
1942 ErrorF(" filtered\n");
1943#endif
1944 return 0;
1945 }
1946
1947 if (grab && !SameClient(grab, client)) {
1948#ifdef DEBUG_EVENTS
1949 ErrorF(" not delivered due to grab\n");
1950#endif
1951 return -1; /* don't send, but notify caller */
1952 }
1953
1954 type = pEvents->u.u.type;
1955 if (type == MotionNotify) {
1956 if (mask & PointerMotionHintMask) {
1957 if (WID(dev->valuator->motionHintWindow) ==
1958 pEvents->u.keyButtonPointer.event) {
1959#ifdef DEBUG_EVENTS
1960 ErrorF("[dix] \n");
1961 ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
1962#endif
1963 return 1; /* don't send, but pretend we did */
1964 }
1965 pEvents->u.u.detail = NotifyHint;
1966 }
1967 else {
1968 pEvents->u.u.detail = NotifyNormal;
1969 }
1970 }
1971 else if (type == DeviceMotionNotify) {
1972 if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents,
1973 mask) != 0)
1974 return 1;
1975 }
1976 else if (type == KeyPress) {
1977 if (EventIsKeyRepeat(pEvents)) {
1978 if (!_XkbWantsDetectableAutoRepeat(client)) {
1979 xEvent release = *pEvents;
1980
1981 release.u.u.type = KeyRelease;
1982 WriteEventsToClient(client, 1, &release);
1983#ifdef DEBUG_EVENTS
1984 ErrorF(" (plus fake core release for repeat)");
1985#endif
1986 }
1987 else {
1988#ifdef DEBUG_EVENTS
1989 ErrorF(" (detectable autorepeat for core)");
1990#endif
1991 }
1992 }
1993
1994 }
1995 else if (type == DeviceKeyPress) {
1996 if (EventIsKeyRepeat(pEvents)) {
1997 if (!_XkbWantsDetectableAutoRepeat(client)) {
1998 deviceKeyButtonPointer release =
1999 *(deviceKeyButtonPointer *) pEvents;
2000 release.type = DeviceKeyRelease;
2001#ifdef DEBUG_EVENTS
2002 ErrorF(" (plus fake xi1 release for repeat)");
2003#endif
2004 WriteEventsToClient(client, 1, (xEvent *) &release);
2005 }
2006 else {
2007#ifdef DEBUG_EVENTS
2008 ErrorF(" (detectable autorepeat for core)");
2009#endif
2010 }
2011 }
2012 }
2013
2014 if (BitIsOn(criticalEvents, type)) {
2015 if (client->smart_priority < SMART_MAX_PRIORITY)
2016 client->smart_priority++;
2017 SetCriticalOutputPending();
2018 }
2019
2020 WriteEventsToClient(client, count, pEvents);
2021#ifdef DEBUG_EVENTS
2022 ErrorF("[dix] delivered\n");
2023#endif
2024 return 1;
2025}
2026
2027static BOOL
2028ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
2029 xEvent *event, Mask deliveryMask)
2030{
2031 GrabPtr tempGrab;
2032 OtherInputMasks *inputMasks;
2033 CARD8 type = event->u.u.type;
2034 enum InputLevel grabtype;
2035
2036 if (type == ButtonPress)
2037 grabtype = CORE;
2038 else if (type == DeviceButtonPress)
2039 grabtype = XI;
2040 else if ((type = xi2_get_type(event)) == XI_ButtonPress)
2041 grabtype = XI2;
2042 else
2043 return FALSE;
2044
2045 tempGrab = AllocGrab(NULL);
2046 if (!tempGrab)
2047 return FALSE;
2048 tempGrab->next = NULL;
2049 tempGrab->device = dev;
2050 tempGrab->resource = client->clientAsMask;
2051 tempGrab->window = win;
2052 tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
2053 tempGrab->eventMask = deliveryMask;
2054 tempGrab->keyboardMode = GrabModeAsync;
2055 tempGrab->pointerMode = GrabModeAsync;
2056 tempGrab->confineTo = NullWindow;
2057 tempGrab->cursor = NullCursor;
2058 tempGrab->type = type;
2059 tempGrab->grabtype = grabtype;
2060
2061 /* get the XI and XI2 device mask */
2062 inputMasks = wOtherInputMasks(win);
2063 tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0;
2064
2065 if (inputMasks)
2066 xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
2067
2068 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab,
2069 currentTime, TRUE | ImplicitGrabMask);
2070 FreeGrab(tempGrab);
2071 return TRUE;
2072}
2073
2074/**
2075 * Attempt event delivery to the client owning the window.
2076 */
2077static enum EventDeliveryState
2078DeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
2079 xEvent *events, int count, Mask filter, GrabPtr grab)
2080{
2081 /* if nobody ever wants to see this event, skip some work */
2082 if (filter != CantBeFiltered &&
2083 !((wOtherEventMasks(win) | win->eventMask) & filter))
2084 return EVENT_SKIP;
2085
2086 if (IsInterferingGrab(wClient(win), dev, events))
2087 return EVENT_SKIP;
2088
2089 if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) {
2090 int attempt = TryClientEvents(wClient(win), dev, events,
2091 count, win->eventMask,
2092 filter, grab);
2093
2094 if (attempt > 0)
2095 return EVENT_DELIVERED;
2096 if (attempt < 0)
2097 return EVENT_REJECTED;
2098 }
2099
2100 return EVENT_NOT_DELIVERED;
2101}
2102
2103/**
2104 * Get the list of clients that should be tried for event delivery on the
2105 * given window.
2106 *
2107 * @return 1 if the client list should be traversed, zero if the event
2108 * should be skipped.
2109 */
2110static Bool
2111GetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
2112 xEvent *events, Mask filter, InputClients ** iclients)
2113{
2114 int rc = 0;
2115
2116 if (core_get_type(events) != 0)
2117 *iclients = (InputClients *) wOtherClients(win);
2118 else if (xi2_get_type(events) != 0) {
2119 OtherInputMasks *inputMasks = wOtherInputMasks(win);
2120
2121 /* Has any client selected for the event? */
2122 if (!WindowXI2MaskIsset(dev, win, events))
2123 goto out;
2124 *iclients = inputMasks->inputClients;
2125 }
2126 else {
2127 OtherInputMasks *inputMasks = wOtherInputMasks(win);
2128
2129 /* Has any client selected for the event? */
2130 if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter))
2131 goto out;
2132
2133 *iclients = inputMasks->inputClients;
2134 }
2135
2136 rc = 1;
2137 out:
2138 return rc;
2139}
2140
2141/**
2142 * Try delivery on each client in inputclients, provided the event mask
2143 * accepts it and there is no interfering core grab..
2144 */
2145static enum EventDeliveryState
2146DeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
2147 WindowPtr win, xEvent *events,
2148 int count, Mask filter, GrabPtr grab,
2149 ClientPtr *client_return, Mask *mask_return)
2150{
2151 int attempt;
2152 enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
2153 Bool have_device_button_grab_class_client = FALSE;
2154
2155 for (; inputclients; inputclients = inputclients->next) {
2156 Mask mask;
2157 ClientPtr client = rClient(inputclients);
2158
2159 if (IsInterferingGrab(client, dev, events))
2160 continue;
2161
2162 if (IsWrongPointerBarrierClient(client, dev, events))
2163 continue;
2164
2165 mask = GetEventMask(dev, events, inputclients);
2166
2167 if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
2168 /* do nothing */ ;
2169 else if ((attempt = TryClientEvents(client, dev,
2170 events, count,
2171 mask, filter, grab))) {
2172 if (attempt > 0) {
2173 /*
2174 * The order of clients is arbitrary therefore if one
2175 * client belongs to DeviceButtonGrabClass make sure to
2176 * catch it.
2177 */
2178 if (!have_device_button_grab_class_client) {
2179 rc = EVENT_DELIVERED;
2180 *client_return = client;
2181 *mask_return = mask;
2182 /* Success overrides non-success, so if we've been
2183 * successful on one client, return that */
2184 if (mask & DeviceButtonGrabMask)
2185 have_device_button_grab_class_client = TRUE;
2186 }
2187 } else if (rc == EVENT_NOT_DELIVERED)
2188 rc = EVENT_REJECTED;
2189 }
2190 }
2191
2192 return rc;
2193}
2194
2195/**
2196 * Deliver events to clients registered on the window.
2197 *
2198 * @param client_return On successful delivery, set to the recipient.
2199 * @param mask_return On successful delivery, set to the recipient's event
2200 * mask for this event.
2201 */
2202static enum EventDeliveryState
2203DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
2204 int count, Mask filter, GrabPtr grab,
2205 ClientPtr *client_return, Mask *mask_return)
2206{
2207 InputClients *iclients;
2208
2209 if (!GetClientsForDelivery(dev, win, events, filter, &iclients))
2210 return EVENT_SKIP;
2211
2212 return DeliverEventToInputClients(dev, iclients, win, events, count, filter,
2213 grab, client_return, mask_return);
2214
2215}
2216
2217/**
2218 * Deliver events to a window. At this point, we do not yet know if the event
2219 * actually needs to be delivered. May activate a grab if the event is a
2220 * button press.
2221 *
2222 * Core events are always delivered to the window owner. If the filter is
2223 * something other than CantBeFiltered, the event is also delivered to other
2224 * clients with the matching mask on the window.
2225 *
2226 * More than one event may be delivered at a time. This is the case with
2227 * DeviceMotionNotifies which may be followed by DeviceValuator events.
2228 *
2229 * @param pWin The window that would get the event.
2230 * @param pEvents The events to be delivered.
2231 * @param count Number of elements in pEvents.
2232 * @param filter Mask based on event type.
2233 * @param grab Possible grab on the device that caused the event.
2234 *
2235 * @return a positive number if at least one successful delivery has been
2236 * made, 0 if no events were delivered, or a negative number if the event
2237 * has not been delivered _and_ rejected by at least one client.
2238 */
2239int
2240DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
2241 *pEvents, int count, Mask filter, GrabPtr grab)
2242{
2243 int deliveries = 0, nondeliveries = 0;
2244 ClientPtr client = NullClient;
2245 Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
2246 this mask is the mask of the grab. */
2247 int type = pEvents->u.u.type;
2248
2249 /* Deliver to window owner */
2250 if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) {
2251 enum EventDeliveryState rc;
2252
2253 rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
2254
2255 switch (rc) {
2256 case EVENT_SKIP:
2257 return 0;
2258 case EVENT_REJECTED:
2259 nondeliveries--;
2260 break;
2261 case EVENT_DELIVERED:
2262 /* We delivered to the owner, with our event mask */
2263 deliveries++;
2264 client = wClient(pWin);
2265 deliveryMask = pWin->eventMask;
2266 break;
2267 case EVENT_NOT_DELIVERED:
2268 break;
2269 }
2270 }
2271
2272 /* CantBeFiltered means only window owner gets the event */
2273 if (filter != CantBeFiltered) {
2274 enum EventDeliveryState rc;
2275
2276 rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
2277 grab, &client, &deliveryMask);
2278
2279 switch (rc) {
2280 case EVENT_SKIP:
2281 return 0;
2282 case EVENT_REJECTED:
2283 nondeliveries--;
2284 break;
2285 case EVENT_DELIVERED:
2286 deliveries++;
2287 break;
2288 case EVENT_NOT_DELIVERED:
2289 break;
2290 }
2291 }
2292
2293 if (deliveries) {
2294 /*
2295 * Note that since core events are delivered first, an implicit grab may
2296 * be activated on a core grab, stopping the XI events.
2297 */
2298 if (!grab &&
2299 ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
2300 /* grab activated */ ;
2301 else if (type == MotionNotify)
2302 pDev->valuator->motionHintWindow = pWin;
2303 else if (type == DeviceMotionNotify || type == DeviceButtonPress)
2304 CheckDeviceGrabAndHintWindow(pWin, type,
2305 (deviceKeyButtonPointer *) pEvents,
2306 grab, client, deliveryMask);
2307 return deliveries;
2308 }
2309 return nondeliveries;
2310}
2311
2312/**
2313 * Filter out raw events for XI 2.0 and XI 2.1 clients.
2314 *
2315 * If there is a grab on the device, 2.0 clients only get raw events if they
2316 * have the grab. 2.1+ clients get raw events in all cases.
2317 *
2318 * @return TRUE if the event should be discarded, FALSE otherwise.
2319 */
2320static BOOL
2321FilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root)
2322{
2323 XIClientPtr client_xi_version;
2324 int cmp;
2325
2326 /* device not grabbed -> don't filter */
2327 if (!grab)
2328 return FALSE;
2329
2330 client_xi_version =
2331 dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
2332
2333 cmp = version_compare(client_xi_version->major_version,
2334 client_xi_version->minor_version, 2, 0);
2335 /* XI 2.0: if device is grabbed, skip
2336 XI 2.1: if device is grabbed by us, skip, we've already delivered */
2337 if (cmp == 0)
2338 return TRUE;
2339
2340 return (grab->window != root) ? FALSE : SameClient(grab, client);
2341}
2342
2343/**
2344 * Deliver a raw event to the grab owner (if any) and to all root windows.
2345 *
2346 * Raw event delivery differs between XI 2.0 and XI 2.1.
2347 * XI 2.0: events delivered to the grabbing client (if any) OR to all root
2348 * windows
2349 * XI 2.1: events delivered to all root windows, regardless of grabbing
2350 * state.
2351 */
2352void
2353DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
2354{
2355 GrabPtr grab = device->deviceGrab.grab;
2356 xEvent *xi;
2357 int i, rc;
2358 int filter;
2359
2360 rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi);
2361 if (rc != Success) {
2362 ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
2363 __func__, device->name, rc);
2364 return;
2365 }
2366
2367 if (grab)
2368 DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE);
2369
2370 filter = GetEventFilter(device, xi);
2371
2372 for (i = 0; i < screenInfo.numScreens; i++) {
2373 WindowPtr root;
2374 InputClients *inputclients;
2375
2376 root = screenInfo.screens[i]->root;
2377 if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
2378 continue;
2379
2380 for (; inputclients; inputclients = inputclients->next) {
2381 ClientPtr c; /* unused */
2382 Mask m; /* unused */
2383 InputClients ic = *inputclients;
2384
2385 /* Because we run through the list manually, copy the actual
2386 * list, shorten the copy to only have one client and then pass
2387 * that down to DeliverEventToInputClients. This way we avoid
2388 * double events on XI 2.1 clients that have a grab on the
2389 * device.
2390 */
2391 ic.next = NULL;
2392
2393 if (!FilterRawEvents(rClient(&ic), grab, root))
2394 DeliverEventToInputClients(device, &ic, root, xi, 1,
2395 filter, NULL, &c, &m);
2396 }
2397 }
2398
2399 free(xi);
2400}
2401
2402/* If the event goes to dontClient, don't send it and return 0. if
2403 send works, return 1 or if send didn't work, return 2.
2404 Only works for core events.
2405*/
2406
2407#ifdef PANORAMIX
2408static int
2409XineramaTryClientEventsResult(ClientPtr client,
2410 GrabPtr grab, Mask mask, Mask filter)
2411{
2412 if ((client) && (client != serverClient) && (!client->clientGone) &&
2413 ((filter == CantBeFiltered) || (mask & filter))) {
2414 if (grab && !SameClient(grab, client))
2415 return -1;
2416 else
2417 return 1;
2418 }
2419 return 0;
2420}
2421#endif
2422
2423/**
2424 * Try to deliver events to the interested parties.
2425 *
2426 * @param pWin The window that would get the event.
2427 * @param pEvents The events to be delivered.
2428 * @param count Number of elements in pEvents.
2429 * @param filter Mask based on event type.
2430 * @param dontClient Don't deliver to the dontClient.
2431 */
2432int
2433MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
2434 int count, Mask filter, ClientPtr dontClient)
2435{
2436 OtherClients *other;
2437
2438 if (pWin->eventMask & filter) {
2439 if (wClient(pWin) == dontClient)
2440 return 0;
2441#ifdef PANORAMIX
2442 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2443 return XineramaTryClientEventsResult(wClient(pWin), NullGrab,
2444 pWin->eventMask, filter);
2445#endif
2446 if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
2447 return 1; /* don't send, but pretend we did */
2448 return TryClientEvents(wClient(pWin), NULL, pEvents, count,
2449 pWin->eventMask, filter, NullGrab);
2450 }
2451 for (other = wOtherClients(pWin); other; other = other->next) {
2452 if (other->mask & filter) {
2453 if (SameClient(other, dontClient))
2454 return 0;
2455#ifdef PANORAMIX
2456 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2457 return XineramaTryClientEventsResult(rClient(other), NullGrab,
2458 other->mask, filter);
2459#endif
2460 if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
2461 count))
2462 return 1; /* don't send, but pretend we did */
2463 return TryClientEvents(rClient(other), NULL, pEvents, count,
2464 other->mask, filter, NullGrab);
2465 }
2466 }
2467 return 2;
2468}
2469
2470static Window
2471FindChildForEvent(SpritePtr pSprite, WindowPtr event)
2472{
2473 WindowPtr w = DeepestSpriteWin(pSprite);
2474 Window child = None;
2475
2476 /* If the search ends up past the root should the child field be
2477 set to none or should the value in the argument be passed
2478 through. It probably doesn't matter since everyone calls
2479 this function with child == None anyway. */
2480 while (w) {
2481 /* If the source window is same as event window, child should be
2482 none. Don't bother going all all the way back to the root. */
2483
2484 if (w == event) {
2485 child = None;
2486 break;
2487 }
2488
2489 if (w->parent == event) {
2490 child = w->drawable.id;
2491 break;
2492 }
2493 w = w->parent;
2494 }
2495 return child;
2496}
2497
2498/**
2499 * Adjust event fields to comply with the window properties.
2500 *
2501 * @param xE Event to be modified in place
2502 * @param pWin The window to get the information from.
2503 * @param child Child window setting for event (if applicable)
2504 * @param calcChild If True, calculate the child window.
2505 */
2506void
2507FixUpEventFromWindow(SpritePtr pSprite,
2508 xEvent *xE, WindowPtr pWin, Window child, Bool calcChild)
2509{
2510 int evtype;
2511
2512 if (calcChild)
2513 child = FindChildForEvent(pSprite, pWin);
2514
2515 if ((evtype = xi2_get_type(xE))) {
2516 xXIDeviceEvent *event = (xXIDeviceEvent *) xE;
2517
2518 switch (evtype) {
2519 case XI_RawKeyPress:
2520 case XI_RawKeyRelease:
2521 case XI_RawButtonPress:
2522 case XI_RawButtonRelease:
2523 case XI_RawMotion:
2524 case XI_RawTouchBegin:
2525 case XI_RawTouchUpdate:
2526 case XI_RawTouchEnd:
2527 case XI_DeviceChanged:
2528 case XI_HierarchyChanged:
2529 case XI_PropertyEvent:
2530 case XI_BarrierHit:
2531 case XI_BarrierLeave:
2532 return;
2533 default:
2534 break;
2535 }
2536
2537 event->root = RootWindow(pSprite)->drawable.id;
2538 event->event = pWin->drawable.id;
2539
2540 if (evtype == XI_TouchOwnership) {
2541 event->child = child;
2542 return;
2543 }
2544
2545 if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
2546 event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
2547 event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
2548 event->child = child;
2549 }
2550 else {
2551 event->event_x = 0;
2552 event->event_y = 0;
2553 event->child = None;
2554 }
2555
2556 if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
2557 event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
2558 ((xXIEnterEvent *) event)->same_screen =
2559 (pSprite->hot.pScreen == pWin->drawable.pScreen);
2560
2561 }
2562 else {
2563 XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
2564 XE_KBPTR.event = pWin->drawable.id;
2565 if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
2566 XE_KBPTR.sameScreen = xTrue;
2567 XE_KBPTR.child = child;
2568 XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x;
2569 XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y;
2570 }
2571 else {
2572 XE_KBPTR.sameScreen = xFalse;
2573 XE_KBPTR.child = None;
2574 XE_KBPTR.eventX = 0;
2575 XE_KBPTR.eventY = 0;
2576 }
2577 }
2578}
2579
2580/**
2581 * Check if a given event is deliverable at all on a given window.
2582 *
2583 * This function only checks if any client wants it, not for a specific
2584 * client.
2585 *
2586 * @param[in] dev The device this event is being sent for.
2587 * @param[in] evtype The event type of the event that is to be sent.
2588 * @param[in] win The current event window.
2589 *
2590 * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
2591 * ::EVENT_DONT_PROPAGATE_MASK.
2592 */
2593int
2594EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
2595{
2596 int rc = 0;
2597 int filter = 0;
2598 int type;
2599 OtherInputMasks *inputMasks = wOtherInputMasks(win);
2600
2601 if ((type = GetXI2Type(evtype)) != 0) {
2602 if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
2603 rc |= EVENT_XI2_MASK;
2604 }
2605
2606 if ((type = GetXIType(evtype)) != 0) {
2607 filter = event_get_filter_from_type(dev, type);
2608
2609 /* Check for XI mask */
2610 if (inputMasks &&
2611 (inputMasks->deliverableEvents[dev->id] & filter) &&
2612 (inputMasks->inputEvents[dev->id] & filter))
2613 rc |= EVENT_XI1_MASK;
2614
2615 /* Check for XI DontPropagate mask */
2616 if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
2617 rc |= EVENT_DONT_PROPAGATE_MASK;
2618
2619 }
2620
2621 if ((type = GetCoreType(evtype)) != 0) {
2622 filter = event_get_filter_from_type(dev, type);
2623
2624 /* Check for core mask */
2625 if ((win->deliverableEvents & filter) &&
2626 ((wOtherEventMasks(win) | win->eventMask) & filter))
2627 rc |= EVENT_CORE_MASK;
2628
2629 /* Check for core DontPropagate mask */
2630 if (filter & wDontPropagateMask(win))
2631 rc |= EVENT_DONT_PROPAGATE_MASK;
2632 }
2633
2634 return rc;
2635}
2636
2637static int
2638DeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
2639 WindowPtr win, Window child, GrabPtr grab)
2640{
2641 SpritePtr pSprite = dev->spriteInfo->sprite;
2642 Mask filter;
2643 int deliveries = 0;
2644
2645 if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) {
2646 filter = GetEventFilter(dev, xE);
2647 FixUpEventFromWindow(pSprite, xE, win, child, FALSE);
2648 deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab);
2649 }
2650
2651 return deliveries;
2652}
2653
2654static int
2655DeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
2656 WindowPtr win, Window child, GrabPtr grab)
2657{
2658 xEvent *xE = NULL;
2659 int count = 0;
2660 int deliveries = 0;
2661 int rc;
2662
2663 switch (level) {
2664 case XI2:
2665 rc = EventToXI2(event, &xE);
2666 count = 1;
2667 break;
2668 case XI:
2669 rc = EventToXI(event, &xE, &count);
2670 break;
2671 case CORE:
2672 rc = EventToCore(event, &xE, &count);
2673 break;
2674 }
2675
2676 if (rc == Success) {
2677 deliveries = DeliverEvent(dev, xE, count, win, child, grab);
2678 free(xE);
2679 }
2680 else
2681 BUG_WARN_MSG(rc != BadMatch,
2682 "%s: conversion to level %d failed with rc %d\n",
2683 dev->name, level, rc);
2684 return deliveries;
2685}
2686
2687/**
2688 * Deliver events caused by input devices.
2689 *
2690 * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
2691 * called directly from the processInputProc.
2692 * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
2693 * DeliverDeviceEvents.
2694 * For focused events, DeliverFocusedEvent is called first, and _may_ call
2695 * DeliverDeviceEvents.
2696 *
2697 * @param pWin Window to deliver event to.
2698 * @param event The events to deliver, not yet in wire format.
2699 * @param grab Possible grab on a device.
2700 * @param stopAt Don't recurse up to the root window.
2701 * @param dev The device that is responsible for the event.
2702 *
2703 * @see DeliverGrabbedEvent
2704 * @see DeliverFocusedEvent
2705 */
2706int
2707DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
2708 WindowPtr stopAt, DeviceIntPtr dev)
2709{
2710 Window child = None;
2711 int deliveries = 0;
2712 int mask;
2713
2714 verify_internal_event(event);
2715
2716 while (pWin) {
2717 if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) {
2718 /* XI2 events first */
2719 if (mask & EVENT_XI2_MASK) {
2720 deliveries =
2721 DeliverOneEvent(event, dev, XI2, pWin, child, grab);
2722 if (deliveries > 0)
2723 break;
2724 }
2725
2726 /* XI events */
2727 if (mask & EVENT_XI1_MASK) {
2728 deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
2729 if (deliveries > 0)
2730 break;
2731 }
2732
2733 /* Core event */
2734 if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) {
2735 deliveries =
2736 DeliverOneEvent(event, dev, CORE, pWin, child, grab);
2737 if (deliveries > 0)
2738 break;
2739 }
2740
2741 }
2742
2743 if ((deliveries < 0) || (pWin == stopAt) ||
2744 (mask & EVENT_DONT_PROPAGATE_MASK)) {
2745 deliveries = 0;
2746 break;
2747 }
2748
2749 child = pWin->drawable.id;
2750 pWin = pWin->parent;
2751 }
2752
2753 return deliveries;
2754}
2755
2756/**
2757 * Deliver event to a window and it's immediate parent. Used for most window
2758 * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2759 * propagate up the tree or extension events
2760 *
2761 * In case of a ReparentNotify event, the event will be delivered to the
2762 * otherParent as well.
2763 *
2764 * @param pWin Window to deliver events to.
2765 * @param xE Events to deliver.
2766 * @param count number of events in xE.
2767 * @param otherParent Used for ReparentNotify events.
2768 */
2769int
2770DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
2771{
2772 DeviceIntRec dummy;
2773 int deliveries;
2774
2775#ifdef PANORAMIX
2776 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2777 return count;
2778#endif
2779
2780 if (!count)
2781 return 0;
2782
2783 dummy.id = XIAllDevices;
2784
2785 switch (xE->u.u.type) {
2786 case DestroyNotify:
2787 case UnmapNotify:
2788 case MapNotify:
2789 case MapRequest:
2790 case ReparentNotify:
2791 case ConfigureNotify:
2792 case ConfigureRequest:
2793 case GravityNotify:
2794 case CirculateNotify:
2795 case CirculateRequest:
2796 xE->u.destroyNotify.event = pWin->drawable.id;
2797 break;
2798 }
2799
2800 switch (xE->u.u.type) {
2801 case DestroyNotify:
2802 case UnmapNotify:
2803 case MapNotify:
2804 case ReparentNotify:
2805 case ConfigureNotify:
2806 case GravityNotify:
2807 case CirculateNotify:
2808 break;
2809 default:
2810 {
2811 Mask filter;
2812
2813 filter = GetEventFilter(&dummy, xE);
2814 return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
2815 }
2816 }
2817
2818 deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
2819 StructureNotifyMask, NullGrab);
2820 if (pWin->parent) {
2821 xE->u.destroyNotify.event = pWin->parent->drawable.id;
2822 deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
2823 SubstructureNotifyMask, NullGrab);
2824 if (xE->u.u.type == ReparentNotify) {
2825 xE->u.destroyNotify.event = otherParent->drawable.id;
2826 deliveries += DeliverEventsToWindow(&dummy,
2827 otherParent, xE, count,
2828 SubstructureNotifyMask,
2829 NullGrab);
2830 }
2831 }
2832 return deliveries;
2833}
2834
2835static Bool
2836PointInBorderSize(WindowPtr pWin, int x, int y)
2837{
2838 BoxRec box;
2839
2840 if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
2841 return TRUE;
2842
2843#ifdef PANORAMIX
2844 if (!noPanoramiXExtension &&
2845 XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
2846 SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
2847 int i;
2848
2849 FOR_NSCREENS_FORWARD_SKIP(i) {
2850 if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
2851 x + screenInfo.screens[0]->x -
2852 screenInfo.screens[i]->x,
2853 y + screenInfo.screens[0]->y -
2854 screenInfo.screens[i]->y, &box))
2855 return TRUE;
2856 }
2857 }
2858#endif
2859 return FALSE;
2860}
2861
2862/**
2863 * Traversed from the root window to the window at the position x/y. While
2864 * traversing, it sets up the traversal history in the spriteTrace array.
2865 * After completing, the spriteTrace history is set in the following way:
2866 * spriteTrace[0] ... root window
2867 * spriteTrace[1] ... top level window that encloses x/y
2868 * ...
2869 * spriteTrace[spriteTraceGood - 1] ... window at x/y
2870 *
2871 * @returns the window at the given coordinates.
2872 */
2873WindowPtr
2874XYToWindow(SpritePtr pSprite, int x, int y)
2875{
2876 WindowPtr pWin;
2877 BoxRec box;
2878
2879 pSprite->spriteTraceGood = 1; /* root window still there */
2880 pWin = RootWindow(pSprite)->firstChild;
2881 while (pWin) {
2882 if ((pWin->mapped) &&
2883 (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
2884 (x < pWin->drawable.x + (int) pWin->drawable.width +
2885 wBorderWidth(pWin)) &&
2886 (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
2887 (y < pWin->drawable.y + (int) pWin->drawable.height +
2888 wBorderWidth(pWin))
2889 /* When a window is shaped, a further check
2890 * is made to see if the point is inside
2891 * borderSize
2892 */
2893 && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
2894 && (!wInputShape(pWin) ||
2895 RegionContainsPoint(wInputShape(pWin),
2896 x - pWin->drawable.x,
2897 y - pWin->drawable.y, &box))
2898#ifdef ROOTLESS
2899 /* In rootless mode windows may be offscreen, even when
2900 * they're in X's stack. (E.g. if the native window system
2901 * implements some form of virtual desktop system).
2902 */
2903 && !pWin->rootlessUnhittable
2904#endif
2905 ) {
2906 if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
2907 pSprite->spriteTraceSize += 10;
2908 pSprite->spriteTrace = realloc(pSprite->spriteTrace,
2909 pSprite->spriteTraceSize *
2910 sizeof(WindowPtr));
2911 }
2912 pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
2913 pWin = pWin->firstChild;
2914 }
2915 else
2916 pWin = pWin->nextSib;
2917 }
2918 return DeepestSpriteWin(pSprite);
2919}
2920
2921/**
2922 * Ungrab a currently FocusIn grabbed device and grab the device on the
2923 * given window. If the win given is the NoneWin, the device is ungrabbed if
2924 * applicable and FALSE is returned.
2925 *
2926 * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2927 */
2928BOOL
2929ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2930{
2931 BOOL rc = FALSE;
2932 DeviceEvent event;
2933
2934 if (dev->deviceGrab.grab) {
2935 if (!dev->deviceGrab.fromPassiveGrab ||
2936 dev->deviceGrab.grab->type != XI_Enter ||
2937 dev->deviceGrab.grab->window == win ||
2938 IsParent(dev->deviceGrab.grab->window, win))
2939 return FALSE;
2940 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2941 (*dev->deviceGrab.DeactivateGrab) (dev);
2942 }
2943
2944 if (win == NoneWin || win == PointerRootWin)
2945 return FALSE;
2946
2947 event = (DeviceEvent) {
2948 .header = ET_Internal,
2949 .type = ET_FocusIn,
2950 .length = sizeof(DeviceEvent),
2951 .time = GetTimeInMillis(),
2952 .deviceid = dev->id,
2953 .sourceid = dev->id,
2954 .detail.button = 0
2955 };
2956 rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2957 TRUE) != NULL);
2958 if (rc)
2959 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2960 return rc;
2961}
2962
2963/**
2964 * Ungrab a currently Enter grabbed device and grab the device for the given
2965 * window.
2966 *
2967 * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2968 */
2969static BOOL
2970ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2971{
2972 BOOL rc = FALSE;
2973 DeviceEvent event;
2974
2975 if (dev->deviceGrab.grab) {
2976 if (!dev->deviceGrab.fromPassiveGrab ||
2977 dev->deviceGrab.grab->type != XI_Enter ||
2978 dev->deviceGrab.grab->window == win ||
2979 IsParent(dev->deviceGrab.grab->window, win))
2980 return FALSE;
2981 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2982 (*dev->deviceGrab.DeactivateGrab) (dev);
2983 }
2984
2985 event = (DeviceEvent) {
2986 .header = ET_Internal,
2987 .type = ET_Enter,
2988 .length = sizeof(DeviceEvent),
2989 .time = GetTimeInMillis(),
2990 .deviceid = dev->id,
2991 .sourceid = dev->id,
2992 .detail.button = 0
2993 };
2994 rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2995 TRUE) != NULL);
2996 if (rc)
2997 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
2998 return rc;
2999}
3000
3001/**
3002 * Update the sprite coordinates based on the event. Update the cursor
3003 * position, then update the event with the new coordinates that may have been
3004 * changed. If the window underneath the sprite has changed, change to new
3005 * cursor and send enter/leave events.
3006 *
3007 * CheckMotion() will not do anything and return FALSE if the event is not a
3008 * pointer event.
3009 *
3010 * @return TRUE if the sprite has moved or FALSE otherwise.
3011 */
3012Bool
3013CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
3014{
3015 WindowPtr prevSpriteWin, newSpriteWin;
3016 SpritePtr pSprite = pDev->spriteInfo->sprite;
3017
3018 verify_internal_event((InternalEvent *) ev);
3019
3020 prevSpriteWin = pSprite->win;
3021
3022 if (ev && !syncEvents.playingEvents) {
3023 /* GetPointerEvents() guarantees that pointer events have the correct
3024 rootX/Y set already. */
3025 switch (ev->type) {
3026 case ET_ButtonPress:
3027 case ET_ButtonRelease:
3028 case ET_Motion:
3029 case ET_TouchBegin:
3030 case ET_TouchUpdate:
3031 case ET_TouchEnd:
3032 break;
3033 default:
3034 /* all other events return FALSE */
3035 return FALSE;
3036 }
3037
3038#ifdef PANORAMIX
3039 if (!noPanoramiXExtension) {
3040 /* Motion events entering DIX get translated to Screen 0
3041 coordinates. Replayed events have already been
3042 translated since they've entered DIX before */
3043 ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
3044 ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
3045 }
3046 else
3047#endif
3048 {
3049 if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) {
3050 pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
3051 RootWindow(pDev->spriteInfo->sprite) =
3052 pSprite->hot.pScreen->root;
3053 }
3054 }
3055
3056 pSprite->hot.x = ev->root_x;
3057 pSprite->hot.y = ev->root_y;
3058 if (pSprite->hot.x < pSprite->physLimits.x1)
3059 pSprite->hot.x = pSprite->physLimits.x1;
3060 else if (pSprite->hot.x >= pSprite->physLimits.x2)
3061 pSprite->hot.x = pSprite->physLimits.x2 - 1;
3062 if (pSprite->hot.y < pSprite->physLimits.y1)
3063 pSprite->hot.y = pSprite->physLimits.y1;
3064 else if (pSprite->hot.y >= pSprite->physLimits.y2)
3065 pSprite->hot.y = pSprite->physLimits.y2 - 1;
3066 if (pSprite->hotShape)
3067 ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x,
3068 &pSprite->hot.y);
3069 pSprite->hotPhys = pSprite->hot;
3070
3071 if ((pSprite->hotPhys.x != ev->root_x) ||
3072 (pSprite->hotPhys.y != ev->root_y)) {
3073#ifdef PANORAMIX
3074 if (!noPanoramiXExtension) {
3075 XineramaSetCursorPosition(pDev, pSprite->hotPhys.x,
3076 pSprite->hotPhys.y, FALSE);
3077 }
3078 else
3079#endif
3080 {
3081 (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev,
3082 pSprite->
3083 hotPhys.pScreen,
3084 pSprite->
3085 hotPhys.x,
3086 pSprite->
3087 hotPhys.y,
3088 FALSE);
3089 }
3090 }
3091
3092 ev->root_x = pSprite->hot.x;
3093 ev->root_y = pSprite->hot.y;
3094 }
3095
3096 newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
3097
3098 if (newSpriteWin != prevSpriteWin) {
3099 int sourceid;
3100
3101 if (!ev) {
3102 UpdateCurrentTimeIf();
3103 sourceid = pDev->id; /* when from WindowsRestructured */
3104 }
3105 else
3106 sourceid = ev->sourceid;
3107
3108 if (prevSpriteWin != NullWindow) {
3109 if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
3110 DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
3111 newSpriteWin, NotifyNormal);
3112 }
3113 /* set pSprite->win after ActivateEnterGrab, otherwise
3114 sprite window == grab_window and no enter/leave events are
3115 sent. */
3116 pSprite->win = newSpriteWin;
3117 PostNewCursor(pDev);
3118 return FALSE;
3119 }
3120 return TRUE;
3121}
3122
3123/**
3124 * Windows have restructured, we need to update the sprite position and the
3125 * sprite's cursor.
3126 */
3127void
3128WindowsRestructured(void)
3129{
3130 DeviceIntPtr pDev = inputInfo.devices;
3131
3132 while (pDev) {
3133 if (IsMaster(pDev) || IsFloating(pDev))
3134 CheckMotion(NULL, pDev);
3135 pDev = pDev->next;
3136 }
3137}
3138
3139#ifdef PANORAMIX
3140/* This was added to support reconfiguration under Xdmx. The problem is
3141 * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
3142 * other than 0,0, the information in the private sprite structure must
3143 * be updated accordingly, or XYToWindow (and other routines) will not
3144 * compute correctly. */
3145void
3146ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
3147{
3148 GrabPtr grab;
3149 DeviceIntPtr pDev;
3150 SpritePtr pSprite;
3151
3152 if (noPanoramiXExtension)
3153 return;
3154
3155 pDev = inputInfo.devices;
3156 while (pDev) {
3157 if (DevHasCursor(pDev)) {
3158 pSprite = pDev->spriteInfo->sprite;
3159 pSprite->hot.x -= xoff;
3160 pSprite->hot.y -= yoff;
3161
3162 pSprite->hotPhys.x -= xoff;
3163 pSprite->hotPhys.y -= yoff;
3164
3165 pSprite->hotLimits.x1 -= xoff;
3166 pSprite->hotLimits.y1 -= yoff;
3167 pSprite->hotLimits.x2 -= xoff;
3168 pSprite->hotLimits.y2 -= yoff;
3169
3170 if (RegionNotEmpty(&pSprite->Reg1))
3171 RegionTranslate(&pSprite->Reg1, xoff, yoff);
3172 if (RegionNotEmpty(&pSprite->Reg2))
3173 RegionTranslate(&pSprite->Reg2, xoff, yoff);
3174
3175 /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
3176 if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
3177 if (grab->confineTo->drawable.pScreen
3178 != pSprite->hotPhys.pScreen)
3179 pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
3180 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
3181 }
3182 else
3183 ConfineCursorToWindow(pDev,
3184 pSprite->hotPhys.pScreen->root,
3185 TRUE, FALSE);
3186
3187 }
3188 pDev = pDev->next;
3189 }
3190}
3191#endif
3192
3193/**
3194 * Initialize a sprite for the given device and set it to some sane values. If
3195 * the device already has a sprite alloc'd, don't realloc but just reset to
3196 * default values.
3197 * If a window is supplied, the sprite will be initialized with the window's
3198 * cursor and positioned in the center of the window's screen. The root window
3199 * is a good choice to pass in here.
3200 *
3201 * It's a good idea to call it only for pointer devices, unless you have a
3202 * really talented keyboard.
3203 *
3204 * @param pDev The device to initialize.
3205 * @param pWin The window where to generate the sprite in.
3206 *
3207 */
3208void
3209InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
3210{
3211 SpritePtr pSprite;
3212 ScreenPtr pScreen;
3213 CursorPtr pCursor;
3214
3215 if (!pDev->spriteInfo->sprite) {
3216 DeviceIntPtr it;
3217
3218 pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec));
3219 if (!pDev->spriteInfo->sprite)
3220 FatalError("InitializeSprite: failed to allocate sprite struct");
3221
3222 /* We may have paired another device with this device before our
3223 * device had a actual sprite. We need to check for this and reset the
3224 * sprite field for all paired devices.
3225 *
3226 * The VCK is always paired with the VCP before the VCP has a sprite.
3227 */
3228 for (it = inputInfo.devices; it; it = it->next) {
3229 if (it->spriteInfo->paired == pDev)
3230 it->spriteInfo->sprite = pDev->spriteInfo->sprite;
3231 }
3232 if (inputInfo.keyboard->spriteInfo->paired == pDev)
3233 inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
3234 }
3235
3236 pSprite = pDev->spriteInfo->sprite;
3237 pDev->spriteInfo->spriteOwner = TRUE;
3238
3239 pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL;
3240 pSprite->hot.pScreen = pScreen;
3241 pSprite->hotPhys.pScreen = pScreen;
3242 if (pScreen) {
3243 pSprite->hotPhys.x = pScreen->width / 2;
3244 pSprite->hotPhys.y = pScreen->height / 2;
3245 pSprite->hotLimits.x2 = pScreen->width;
3246 pSprite->hotLimits.y2 = pScreen->height;
3247 }
3248
3249 pSprite->hot = pSprite->hotPhys;
3250 pSprite->win = pWin;
3251
3252 if (pWin) {
3253 pCursor = wCursor(pWin);
3254 pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr));
3255 if (!pSprite->spriteTrace)
3256 FatalError("Failed to allocate spriteTrace");
3257 pSprite->spriteTraceSize = 32;
3258
3259 RootWindow(pDev->spriteInfo->sprite) = pWin;
3260 pSprite->spriteTraceGood = 1;
3261
3262 pSprite->pEnqueueScreen = pScreen;
3263 pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3264
3265 }
3266 else {
3267 pCursor = NullCursor;
3268 pSprite->spriteTrace = NULL;
3269 pSprite->spriteTraceSize = 0;
3270 pSprite->spriteTraceGood = 0;
3271 pSprite->pEnqueueScreen = screenInfo.screens[0];
3272 pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3273 }
3274 pCursor = RefCursor(pCursor);
3275 if (pSprite->current)
3276 FreeCursor(pSprite->current, None);
3277 pSprite->current = RefCursor(pCursor);
3278
3279 if (pScreen) {
3280 (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
3281 (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current,
3282 &pSprite->hotLimits, &pSprite->physLimits);
3283 pSprite->confined = FALSE;
3284
3285 (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3286 (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
3287 pSprite->hot.y, FALSE);
3288 (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3289 }
3290#ifdef PANORAMIX
3291 if (!noPanoramiXExtension) {
3292 pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3293 pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3294 pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
3295 pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3296 pSprite->physLimits = pSprite->hotLimits;
3297 pSprite->confineWin = NullWindow;
3298 pSprite->hotShape = NullRegion;
3299 pSprite->screen = pScreen;
3300 /* gotta UNINIT these someplace */
3301 RegionNull(&pSprite->Reg1);
3302 RegionNull(&pSprite->Reg2);
3303 }
3304#endif
3305}
3306
3307void FreeSprite(DeviceIntPtr dev)
3308{
3309 if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
3310 if (dev->spriteInfo->sprite->current)
3311 FreeCursor(dev->spriteInfo->sprite->current, None);
3312 free(dev->spriteInfo->sprite->spriteTrace);
3313 free(dev->spriteInfo->sprite);
3314 }
3315 dev->spriteInfo->sprite = NULL;
3316}
3317
3318
3319/**
3320 * Update the mouse sprite info when the server switches from a pScreen to another.
3321 * Otherwise, the pScreen of the mouse sprite is never updated when we switch
3322 * from a pScreen to another. Never updating the pScreen of the mouse sprite
3323 * implies that windows that are in pScreen whose pScreen->myNum >0 will never
3324 * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen
3325 * always points to the first pScreen it has been set by
3326 * DefineInitialRootWindow().
3327 *
3328 * Calling this function is useful for use cases where the server
3329 * has more than one pScreen.
3330 * This function is similar to DefineInitialRootWindow() but it does not
3331 * reset the mouse pointer position.
3332 * @param win must be the new pScreen we are switching to.
3333 */
3334void
3335UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
3336{
3337 SpritePtr pSprite = NULL;
3338 WindowPtr win = NULL;
3339 CursorPtr pCursor;
3340
3341 if (!pScreen)
3342 return;
3343
3344 if (!pDev->spriteInfo->sprite)
3345 return;
3346
3347 pSprite = pDev->spriteInfo->sprite;
3348
3349 win = pScreen->root;
3350
3351 pSprite->hotPhys.pScreen = pScreen;
3352 pSprite->hot = pSprite->hotPhys;
3353 pSprite->hotLimits.x2 = pScreen->width;
3354 pSprite->hotLimits.y2 = pScreen->height;
3355 pSprite->win = win;
3356 pCursor = RefCursor(wCursor(win));
3357 if (pSprite->current)
3358 FreeCursor(pSprite->current, 0);
3359 pSprite->current = pCursor;
3360 pSprite->spriteTraceGood = 1;
3361 pSprite->spriteTrace[0] = win;
3362 (*pScreen->CursorLimits) (pDev,
3363 pScreen,
3364 pSprite->current,
3365 &pSprite->hotLimits, &pSprite->physLimits);
3366 pSprite->confined = FALSE;
3367 (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3368 (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3369
3370#ifdef PANORAMIX
3371 if (!noPanoramiXExtension) {
3372 pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3373 pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3374 pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
3375 pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3376 pSprite->physLimits = pSprite->hotLimits;
3377 pSprite->screen = pScreen;
3378 }
3379#endif
3380}
3381
3382/*
3383 * This does not take any shortcuts, and even ignores its argument, since
3384 * it does not happen very often, and one has to walk up the tree since
3385 * this might be a newly instantiated cursor for an intermediate window
3386 * between the one the pointer is in and the one that the last cursor was
3387 * instantiated from.
3388 */
3389void
3390WindowHasNewCursor(WindowPtr pWin)
3391{
3392 DeviceIntPtr pDev;
3393
3394 for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
3395 if (DevHasCursor(pDev))
3396 PostNewCursor(pDev);
3397}
3398
3399void
3400NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
3401{
3402 DeviceIntPtr ptr;
3403 SpritePtr pSprite;
3404
3405 ptr =
3406 IsFloating(pDev) ? pDev :
3407 GetXTestDevice(GetMaster(pDev, MASTER_POINTER));
3408 pSprite = ptr->spriteInfo->sprite;
3409
3410 pSprite->hotPhys.x = x;
3411 pSprite->hotPhys.y = y;
3412#ifdef PANORAMIX
3413 if (!noPanoramiXExtension) {
3414 pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
3415 pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
3416 if (newScreen != pSprite->screen) {
3417 pSprite->screen = newScreen;
3418 /* Make sure we tell the DDX to update its copy of the screen */
3419 if (pSprite->confineWin)
3420 XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE);
3421 else
3422 XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root,
3423 TRUE);
3424 /* if the pointer wasn't confined, the DDX won't get
3425 told of the pointer warp so we reposition it here */
3426 if (!syncEvents.playingEvents)
3427 (*pSprite->screen->SetCursorPosition) (ptr,
3428 pSprite->screen,
3429 pSprite->hotPhys.x +
3430 screenInfo.screens[0]->
3431 x - pSprite->screen->x,
3432 pSprite->hotPhys.y +
3433 screenInfo.screens[0]->
3434 y - pSprite->screen->y,
3435 FALSE);
3436 }
3437 }
3438 else
3439#endif
3440 if (newScreen != pSprite->hotPhys.pScreen)
3441 ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE);
3442}
3443
3444#ifdef PANORAMIX
3445
3446static Bool
3447XineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y)
3448{
3449 BoxRec box;
3450 int i, xoff, yoff;
3451
3452 if (!pWin->realized)
3453 return FALSE;
3454
3455 if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
3456 return TRUE;
3457
3458 if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin))
3459 return FALSE;
3460
3461 xoff = x + screenInfo.screens[0]->x;
3462 yoff = y + screenInfo.screens[0]->y;
3463
3464 FOR_NSCREENS_FORWARD_SKIP(i) {
3465 pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
3466
3467 x = xoff - screenInfo.screens[i]->x;
3468 y = yoff - screenInfo.screens[i]->y;
3469
3470 if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
3471 && (!wInputShape(pWin) ||
3472 RegionContainsPoint(wInputShape(pWin),
3473 x - pWin->drawable.x,
3474 y - pWin->drawable.y, &box)))
3475 return TRUE;
3476
3477 }
3478
3479 return FALSE;
3480}
3481
3482static int
3483XineramaWarpPointer(ClientPtr client)
3484{
3485 WindowPtr dest = NULL;
3486 int x, y, rc;
3487 SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
3488
3489 REQUEST(xWarpPointerReq);
3490
3491 if (stuff->dstWid != None) {
3492 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
3493 if (rc != Success)
3494 return rc;
3495 }
3496 x = pSprite->hotPhys.x;
3497 y = pSprite->hotPhys.y;
3498
3499 if (stuff->srcWid != None) {
3500 int winX, winY;
3501 XID winID = stuff->srcWid;
3502 WindowPtr source;
3503
3504 rc = dixLookupWindow(&source, winID, client, DixReadAccess);
3505 if (rc != Success)
3506 return rc;
3507
3508 winX = source->drawable.x;
3509 winY = source->drawable.y;
3510 if (source == screenInfo.screens[0]->root) {
3511 winX -= screenInfo.screens[0]->x;
3512 winY -= screenInfo.screens[0]->y;
3513 }
3514 if (x < winX + stuff->srcX ||
3515 y < winY + stuff->srcY ||
3516 (stuff->srcWidth != 0 &&
3517 winX + stuff->srcX + (int) stuff->srcWidth < x) ||
3518 (stuff->srcHeight != 0 &&
3519 winY + stuff->srcY + (int) stuff->srcHeight < y) ||
3520 !XineramaPointInWindowIsVisible(source, x, y))
3521 return Success;
3522 }
3523 if (dest) {
3524 x = dest->drawable.x;
3525 y = dest->drawable.y;
3526 if (dest == screenInfo.screens[0]->root) {
3527 x -= screenInfo.screens[0]->x;
3528 y -= screenInfo.screens[0]->y;
3529 }
3530 }
3531
3532 x += stuff->dstX;
3533 y += stuff->dstY;
3534
3535 if (x < pSprite->physLimits.x1)
3536 x = pSprite->physLimits.x1;
3537 else if (x >= pSprite->physLimits.x2)
3538 x = pSprite->physLimits.x2 - 1;
3539 if (y < pSprite->physLimits.y1)
3540 y = pSprite->physLimits.y1;
3541 else if (y >= pSprite->physLimits.y2)
3542 y = pSprite->physLimits.y2 - 1;
3543 if (pSprite->hotShape)
3544 ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
3545
3546 XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
3547
3548 return Success;
3549}
3550
3551#endif
3552
3553/**
3554 * Server-side protocol handling for WarpPointer request.
3555 * Warps the cursor position to the coordinates given in the request.
3556 */
3557int
3558ProcWarpPointer(ClientPtr client)
3559{
3560 WindowPtr dest = NULL;
3561 int x, y, rc;
3562 ScreenPtr newScreen;
3563 DeviceIntPtr dev, tmp;
3564 SpritePtr pSprite;
3565
3566 REQUEST(xWarpPointerReq);
3567 REQUEST_SIZE_MATCH(xWarpPointerReq);
3568
3569 dev = PickPointer(client);
3570
3571 for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
3572 if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
3573 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
3574 if (rc != Success)
3575 return rc;
3576 }
3577 }
3578
3579 if (dev->lastSlave)
3580 dev = dev->lastSlave;
3581 pSprite = dev->spriteInfo->sprite;
3582
3583#ifdef PANORAMIX
3584 if (!noPanoramiXExtension)
3585 return XineramaWarpPointer(client);
3586#endif
3587
3588 if (stuff->dstWid != None) {
3589 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
3590 if (rc != Success)
3591 return rc;
3592 }
3593 x = pSprite->hotPhys.x;
3594 y = pSprite->hotPhys.y;
3595
3596 if (stuff->srcWid != None) {
3597 int winX, winY;
3598 XID winID = stuff->srcWid;
3599 WindowPtr source;
3600
3601 rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
3602 if (rc != Success)
3603 return rc;
3604
3605 winX = source->drawable.x;
3606 winY = source->drawable.y;
3607 if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
3608 x < winX + stuff->srcX ||
3609 y < winY + stuff->srcY ||
3610 (stuff->srcWidth != 0 &&
3611 winX + stuff->srcX + (int) stuff->srcWidth < x) ||
3612 (stuff->srcHeight != 0 &&
3613 winY + stuff->srcY + (int) stuff->srcHeight < y) ||
3614 !PointInWindowIsVisible(source, x, y))
3615 return Success;
3616 }
3617 if (dest) {
3618 x = dest->drawable.x;
3619 y = dest->drawable.y;
3620 newScreen = dest->drawable.pScreen;
3621 }
3622 else
3623 newScreen = pSprite->hotPhys.pScreen;
3624
3625 x += stuff->dstX;
3626 y += stuff->dstY;
3627
3628 if (x < 0)
3629 x = 0;
3630 else if (x >= newScreen->width)
3631 x = newScreen->width - 1;
3632 if (y < 0)
3633 y = 0;
3634 else if (y >= newScreen->height)
3635 y = newScreen->height - 1;
3636
3637 if (newScreen == pSprite->hotPhys.pScreen) {
3638 if (x < pSprite->physLimits.x1)
3639 x = pSprite->physLimits.x1;
3640 else if (x >= pSprite->physLimits.x2)
3641 x = pSprite->physLimits.x2 - 1;
3642 if (y < pSprite->physLimits.y1)
3643 y = pSprite->physLimits.y1;
3644 else if (y >= pSprite->physLimits.y2)
3645 y = pSprite->physLimits.y2 - 1;
3646 if (pSprite->hotShape)
3647 ConfineToShape(dev, pSprite->hotShape, &x, &y);
3648 (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE);
3649 }
3650 else if (!PointerConfinedToScreen(dev)) {
3651 NewCurrentScreen(dev, newScreen, x, y);
3652 }
3653 return Success;
3654}
3655
3656static Bool
3657BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
3658{
3659 if (RegionNotEmpty(&pWin->borderSize))
3660 return TRUE;
3661
3662#ifdef PANORAMIX
3663 if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
3664 int i;
3665
3666 FOR_NSCREENS_FORWARD_SKIP(i) {
3667 if (RegionNotEmpty
3668 (&pDev->spriteInfo->sprite->windows[i]->borderSize))
3669 return TRUE;
3670 }
3671 }
3672#endif
3673 return FALSE;
3674}
3675
3676/**
3677 * Activate the given passive grab. If the grab is activated successfully, the
3678 * event has been delivered to the client.
3679 *
3680 * @param device The device of the event to check.
3681 * @param grab The grab to check.
3682 * @param event The current device event.
3683 * @param real_event The original event, in case of touch emulation. The
3684 * real event is the one stored in the sync queue.
3685 *
3686 * @return Whether the grab has been activated.
3687 */
3688Bool
3689ActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3690 InternalEvent *real_event)
3691{
3692 SpritePtr pSprite = device->spriteInfo->sprite;
3693 GrabInfoPtr grabinfo = &device->deviceGrab;
3694 xEvent *xE = NULL;
3695 int count;
3696 int rc;
3697
3698 /* The only consumers of corestate are Xi 1.x and core events, which
3699 * are guaranteed to come from DeviceEvents. */
3700 if (grab->grabtype == XI || grab->grabtype == CORE) {
3701 DeviceIntPtr gdev;
3702
3703 event->device_event.corestate &= 0x1f00;
3704
3705 if (grab->grabtype == CORE)
3706 gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
3707 else
3708 gdev = grab->modifierDevice;
3709
3710 if (gdev && gdev->key && gdev->key->xkbInfo)
3711 event->device_event.corestate |=
3712 gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
3713 }
3714
3715 if (grab->grabtype == CORE) {
3716 rc = EventToCore(event, &xE, &count);
3717 if (rc != Success) {
3718 BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed"
3719 "(%d, %d).\n", device->name, event->any.type, rc);
3720 return FALSE;
3721 }
3722 }
3723 else if (grab->grabtype == XI2) {
3724 rc = EventToXI2(event, &xE);
3725 if (rc != Success) {
3726 if (rc != BadMatch)
3727 BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed"
3728 "(%d, %d).\n", device->name, event->any.type, rc);
3729 return FALSE;
3730 }
3731 count = 1;
3732 }
3733 else {
3734 rc = EventToXI(event, &xE, &count);
3735 if (rc != Success) {
3736 if (rc != BadMatch)
3737 BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed"
3738 "(%d, %d).\n", device->name, event->any.type, rc);
3739 return FALSE;
3740 }
3741 }
3742
3743 (*grabinfo->ActivateGrab) (device, grab,
3744 ClientTimeToServerTime(event->any.time), TRUE);
3745
3746 if (xE) {
3747 FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
3748
3749 /* XXX: XACE? */
3750 TryClientEvents(rClient(grab), device, xE, count,
3751 GetEventFilter(device, xE),
3752 GetEventFilter(device, xE), grab);
3753 }
3754
3755 if (grabinfo->sync.state == FROZEN_NO_EVENT)
3756 grabinfo->sync.state = FROZEN_WITH_EVENT;
3757 *grabinfo->sync.event = real_event->device_event;
3758
3759 free(xE);
3760 return TRUE;
3761}
3762
3763static BOOL
3764CoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
3765{
3766 DeviceIntPtr other;
3767 BOOL interfering = FALSE;
3768
3769 for (other = inputInfo.devices; other; other = other->next) {
3770 GrabPtr othergrab = other->deviceGrab.grab;
3771
3772 if (othergrab && othergrab->grabtype == CORE &&
3773 SameClient(grab, rClient(othergrab)) &&
3774 ((IsPointerDevice(grab->device) &&
3775 IsPointerDevice(othergrab->device)) ||
3776 (IsKeyboardDevice(grab->device) &&
3777 IsKeyboardDevice(othergrab->device)))) {
3778 interfering = TRUE;
3779 break;
3780 }
3781 }
3782
3783 return interfering;
3784}
3785
3786enum MatchFlags {
3787 NO_MATCH = 0x0,
3788 CORE_MATCH = 0x1,
3789 XI_MATCH = 0x2,
3790 XI2_MATCH = 0x4,
3791};
3792
3793/**
3794 * Match the grab against the temporary grab on the given input level.
3795 * Modifies the temporary grab pointer.
3796 *
3797 * @param grab The grab to match against
3798 * @param tmp The temporary grab to use for matching
3799 * @param level The input level we want to match on
3800 * @param event_type Wire protocol event type
3801 *
3802 * @return The respective matched flag or 0 for no match
3803 */
3804static enum MatchFlags
3805MatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level,
3806 int event_type)
3807{
3808 enum MatchFlags match;
3809 BOOL ignore_device = FALSE;
3810 int grabtype;
3811 int evtype;
3812
3813 switch (level) {
3814 case XI2:
3815 grabtype = XI2;
3816 evtype = GetXI2Type(event_type);
3817 BUG_WARN(!evtype);
3818 match = XI2_MATCH;
3819 break;
3820 case XI:
3821 grabtype = XI;
3822 evtype = GetXIType(event_type);
3823 match = XI_MATCH;
3824 break;
3825 case CORE:
3826 grabtype = CORE;
3827 evtype = GetCoreType(event_type);
3828 match = CORE_MATCH;
3829 ignore_device = TRUE;
3830 break;
3831 }
3832
3833 tmp->grabtype = grabtype;
3834 tmp->type = evtype;
3835
3836 if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
3837 return match;
3838
3839 return NO_MATCH;
3840}
3841
3842/**
3843 * Check an individual grab against an event to determine if a passive grab
3844 * should be activated.
3845 *
3846 * @param device The device of the event to check.
3847 * @param grab The grab to check.
3848 * @param event The current device event.
3849 * @param checkCore Check for core grabs too.
3850 * @param tempGrab A pre-allocated temporary grab record for matching. This
3851 * must have the window and device values filled in.
3852 *
3853 * @return Whether the grab matches the event.
3854 */
3855static Bool
3856CheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3857 Bool checkCore, GrabPtr tempGrab)
3858{
3859 DeviceIntPtr gdev;
3860 XkbSrvInfoPtr xkbi = NULL;
3861 enum MatchFlags match = 0;
3862 int emulated_type = 0;
3863
3864 gdev = grab->modifierDevice;
3865 if (grab->grabtype == CORE) {
3866 gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
3867 }
3868 else if (grab->grabtype == XI2) {
3869 /* if the device is an attached slave device, gdev must be the
3870 * attached master keyboard. Since the slave may have been
3871 * reattached after the grab, the modifier device may not be the
3872 * same. */
3873 if (!IsMaster(grab->device) && !IsFloating(device))
3874 gdev = GetMaster(device, MASTER_KEYBOARD);
3875 }
3876
3877 if (gdev && gdev->key)
3878 xkbi = gdev->key->xkbInfo;
3879 tempGrab->modifierDevice = grab->modifierDevice;
3880 tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
3881
3882 /* Check for XI2 and XI grabs first */
3883 match = MatchForType(grab, tempGrab, XI2, event->any.type);
3884
3885 if (!match && IsTouchEvent(event) &&
3886 (event->device_event.flags & TOUCH_POINTER_EMULATED)) {
3887 emulated_type = TouchGetPointerEventType(event);
3888 match = MatchForType(grab, tempGrab, XI2, emulated_type);
3889 }
3890
3891 if (!match)
3892 match = MatchForType(grab, tempGrab, XI, event->any.type);
3893
3894 if (!match && emulated_type)
3895 match = MatchForType(grab, tempGrab, XI, emulated_type);
3896
3897 if (!match && checkCore) {
3898 match = MatchForType(grab, tempGrab, CORE, event->any.type);
3899 if (!match && emulated_type)
3900 match = MatchForType(grab, tempGrab, CORE, emulated_type);
3901 }
3902
3903 if (!match || (grab->confineTo &&
3904 (!grab->confineTo->realized ||
3905 !BorderSizeNotEmpty(device, grab->confineTo))))
3906 return FALSE;
3907
3908 /* In some cases a passive core grab may exist, but the client
3909 * already has a core grab on some other device. In this case we
3910 * must not get the grab, otherwise we may never ungrab the
3911 * device.
3912 */
3913
3914 if (grab->grabtype == CORE) {
3915 /* A passive grab may have been created for a different device
3916 than it is assigned to at this point in time.
3917 Update the grab's device and modifier device to reflect the
3918 current state.
3919 Since XGrabDeviceButton requires to specify the
3920 modifierDevice explicitly, we don't override this choice.
3921 */
3922 if (grab->type < GenericEvent) {
3923 grab->device = device;
3924 grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
3925 }
3926
3927 if (CoreGrabInterferes(device, grab))
3928 return FALSE;
3929 }
3930
3931 return TRUE;
3932}
3933
3934/**
3935 * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
3936 * passive grab set on the window to be activated.
3937 * If activate is true and a passive grab is found, it will be activated,
3938 * and the event will be delivered to the client.
3939 *
3940 * @param pWin The window that may be subject to a passive grab.
3941 * @param device Device that caused the event.
3942 * @param event The current device event.
3943 * @param checkCore Check for core grabs too.
3944 * @param activate If a grab is found, activate it and deliver the event.
3945 */
3946
3947GrabPtr
3948CheckPassiveGrabsOnWindow(WindowPtr pWin,
3949 DeviceIntPtr device,
3950 InternalEvent *event, BOOL checkCore, BOOL activate)
3951{
3952 GrabPtr grab = wPassiveGrabs(pWin);
3953 GrabPtr tempGrab;
3954
3955 if (!grab)
3956 return NULL;
3957
3958 tempGrab = AllocGrab(NULL);
3959
3960 /* Fill out the grab details, but leave the type for later before
3961 * comparing */
3962 switch (event->any.type) {
3963 case ET_KeyPress:
3964 case ET_KeyRelease:
3965 tempGrab->detail.exact = event->device_event.detail.key;
3966 break;
3967 case ET_ButtonPress:
3968 case ET_ButtonRelease:
3969 case ET_TouchBegin:
3970 case ET_TouchEnd:
3971 tempGrab->detail.exact = event->device_event.detail.button;
3972 break;
3973 default:
3974 tempGrab->detail.exact = 0;
3975 break;
3976 }
3977 tempGrab->window = pWin;
3978 tempGrab->device = device;
3979 tempGrab->detail.pMask = NULL;
3980 tempGrab->modifiersDetail.pMask = NULL;
3981 tempGrab->next = NULL;
3982
3983 for (; grab; grab = grab->next) {
3984 if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
3985 continue;
3986
3987 if (activate && !ActivatePassiveGrab(device, grab, event, event))
3988 continue;
3989
3990 break;
3991 }
3992
3993 FreeGrab(tempGrab);
3994 return grab;
3995}
3996
3997/**
3998 * CheckDeviceGrabs handles both keyboard and pointer events that may cause
3999 * a passive grab to be activated.
4000 *
4001 * If the event is a keyboard event, the ancestors of the focus window are
4002 * traced down and tried to see if they have any passive grabs to be
4003 * activated. If the focus window itself is reached and it's descendants
4004 * contain the pointer, the ancestors of the window that the pointer is in
4005 * are then traced down starting at the focus window, otherwise no grabs are
4006 * activated.
4007 * If the event is a pointer event, the ancestors of the window that the
4008 * pointer is in are traced down starting at the root until CheckPassiveGrabs
4009 * causes a passive grab to activate or all the windows are
4010 * tried. PRH
4011 *
4012 * If a grab is activated, the event has been sent to the client already!
4013 *
4014 * The event we pass in must always be an XI event. From this, we then emulate
4015 * the core event and then check for grabs.
4016 *
4017 * @param device The device that caused the event.
4018 * @param xE The event to handle (Device{Button|Key}Press).
4019 * @param count Number of events in list.
4020 * @return TRUE if a grab has been activated or false otherwise.
4021*/
4022
4023Bool
4024CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
4025{
4026 int i;
4027 WindowPtr pWin = NULL;
4028 FocusClassPtr focus =
4029 IsPointerEvent((InternalEvent *) event) ? NULL : device->focus;
4030 BOOL sendCore = (IsMaster(device) && device->coreEvents);
4031 Bool ret = FALSE;
4032
4033 if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
4034 return FALSE;
4035
4036 if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1))
4037 return FALSE;
4038
4039 if (device->deviceGrab.grab)
4040 return FALSE;
4041
4042 i = 0;
4043 if (ancestor) {
4044 while (i < device->spriteInfo->sprite->spriteTraceGood)
4045 if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
4046 break;
4047 if (i == device->spriteInfo->sprite->spriteTraceGood)
4048 goto out;
4049 }
4050
4051 if (focus) {
4052 for (; i < focus->traceGood; i++) {
4053 pWin = focus->trace[i];
4054 if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4055 sendCore, TRUE)) {
4056 ret = TRUE;
4057 goto out;
4058 }
4059 }
4060
4061 if ((focus->win == NoneWin) ||
4062 (i >= device->spriteInfo->sprite->spriteTraceGood) ||
4063 (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1]))
4064 goto out;
4065 }
4066
4067 for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
4068 pWin = device->spriteInfo->sprite->spriteTrace[i];
4069 if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4070 sendCore, TRUE)) {
4071 ret = TRUE;
4072 goto out;
4073 }
4074 }
4075
4076 out:
4077 if (ret == TRUE && event->type == ET_KeyPress)
4078 device->deviceGrab.activatingKey = event->detail.key;
4079 return ret;
4080}
4081
4082/**
4083 * Called for keyboard events to deliver event to whatever client owns the
4084 * focus.
4085 *
4086 * The event is delivered to the keyboard's focus window, the root window or
4087 * to the window owning the input focus.
4088 *
4089 * @param keybd The keyboard originating the event.
4090 * @param event The event, not yet in wire format.
4091 * @param window Window underneath the sprite.
4092 */
4093void
4094DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
4095{
4096 DeviceIntPtr ptr;
4097 WindowPtr focus = keybd->focus->win;
4098 BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
4099 xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
4100 int count, rc;
4101 int deliveries = 0;
4102
4103 if (focus == FollowKeyboardWin)
4104 focus = inputInfo.keyboard->focus->win;
4105 if (!focus)
4106 return;
4107 if (focus == PointerRootWin) {
4108 DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
4109 return;
4110 }
4111 if ((focus == window) || IsParent(focus, window)) {
4112 if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
4113 return;
4114 }
4115
4116 /* just deliver it to the focus window */
4117 ptr = GetMaster(keybd, POINTER_OR_FLOAT);
4118
4119 rc = EventToXI2(event, &xi2);
4120 if (rc == Success) {
4121 /* XXX: XACE */
4122 int filter = GetEventFilter(keybd, xi2);
4123
4124 FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
4125 deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
4126 filter, NullGrab);
4127 if (deliveries > 0)
4128 goto unwind;
4129 }
4130 else if (rc != BadMatch)
4131 ErrorF
4132 ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
4133 keybd->name, event->any.type, rc);
4134
4135 rc = EventToXI(event, &xE, &count);
4136 if (rc == Success &&
4137 XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) {
4138 FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
4139 deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
4140 GetEventFilter(keybd, xE), NullGrab);
4141
4142 if (deliveries > 0)
4143 goto unwind;
4144 }
4145 else if (rc != BadMatch)
4146 ErrorF
4147 ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
4148 keybd->name, event->any.type, rc);
4149
4150 if (sendCore) {
4151 rc = EventToCore(event, &core, &count);
4152 if (rc == Success) {
4153 if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) ==
4154 Success) {
4155 FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
4156 None, FALSE);
4157 deliveries =
4158 DeliverEventsToWindow(keybd, focus, core, count,
4159 GetEventFilter(keybd, core),
4160 NullGrab);
4161 }
4162 }
4163 else if (rc != BadMatch)
4164 ErrorF
4165 ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
4166 keybd->name, event->any.type, rc);
4167 }
4168
4169 unwind:
4170 free(core);
4171 free(xE);
4172 free(xi2);
4173 return;
4174}
4175
4176int
4177DeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev,
4178 enum InputLevel level)
4179{
4180 SpritePtr pSprite = dev->spriteInfo->sprite;
4181 int rc;
4182 xEvent *xE = NULL;
4183 int count = 0;
4184 int deliveries = 0;
4185 Mask mask;
4186 GrabInfoPtr grabinfo = &dev->deviceGrab;
4187 GrabPtr grab = grabinfo->grab;
4188 Mask filter;
4189
4190 if (grab->grabtype != level)
4191 return 0;
4192
4193 switch (level) {
4194 case XI2:
4195 rc = EventToXI2(event, &xE);
4196 count = 1;
4197 if (rc == Success) {
4198 int evtype = xi2_get_type(xE);
4199
4200 mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
4201 filter = GetEventFilter(dev, xE);
4202 }
4203 break;
4204 case XI:
4205 if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
4206 mask = grab->deviceMask;
4207 else
4208 mask = grab->eventMask;
4209 rc = EventToXI(event, &xE, &count);
4210 if (rc == Success)
4211 filter = GetEventFilter(dev, xE);
4212 break;
4213 case CORE:
4214 rc = EventToCore(event, &xE, &count);
4215 mask = grab->eventMask;
4216 if (rc == Success)
4217 filter = GetEventFilter(dev, xE);
4218 break;
4219 default:
4220 BUG_WARN_MSG(1, "Invalid input level %d\n", level);
4221 return 0;
4222 }
4223
4224 if (rc == Success) {
4225 FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
4226 if (XaceHook(XACE_SEND_ACCESS, 0, dev,
4227 grab->window, xE, count) ||
4228 XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
4229 grab->window, xE, count))
4230 deliveries = 1; /* don't send, but pretend we did */
4231 else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) {
4232 deliveries = TryClientEvents(rClient(grab), dev,
4233 xE, count, mask, filter, grab);
4234 }
4235 }
4236 else
4237 BUG_WARN_MSG(rc != BadMatch,
4238 "%s: conversion to mode %d failed on %d with %d\n",
4239 dev->name, level, event->any.type, rc);
4240
4241 free(xE);
4242 return deliveries;
4243}
4244
4245/**
4246 * Deliver an event from a device that is currently grabbed. Uses
4247 * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
4248 * grab. If not, TryClientEvents() is used.
4249 *
4250 * @param deactivateGrab True if the device's grab should be deactivated.
4251 *
4252 * @return The number of events delivered.
4253 */
4254int
4255DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
4256 Bool deactivateGrab)
4257{
4258 GrabPtr grab;
4259 GrabInfoPtr grabinfo;
4260 int deliveries = 0;
4261 DeviceIntPtr dev;
4262 SpritePtr pSprite = thisDev->spriteInfo->sprite;
4263 BOOL sendCore = FALSE;
4264
4265 grabinfo = &thisDev->deviceGrab;
4266 grab = grabinfo->grab;
4267
4268 if (grab->ownerEvents) {
4269 WindowPtr focus;
4270
4271 /* Hack: Some pointer device have a focus class. So we need to check
4272 * for the type of event, to see if we really want to deliver it to
4273 * the focus window. For pointer events, the answer is no.
4274 */
4275 if (IsPointerEvent(event))
4276 focus = PointerRootWin;
4277 else if (thisDev->focus) {
4278 focus = thisDev->focus->win;
4279 if (focus == FollowKeyboardWin)
4280 focus = inputInfo.keyboard->focus->win;
4281 }
4282 else
4283 focus = PointerRootWin;
4284 if (focus == PointerRootWin)
4285 deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
4286 NullWindow, thisDev);
4287 else if (focus && (focus == pSprite->win ||
4288 IsParent(focus, pSprite->win)))
4289 deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
4290 thisDev);
4291 else if (focus)
4292 deliveries = DeliverDeviceEvents(focus, event, grab, focus,
4293 thisDev);
4294 }
4295 if (!deliveries) {
4296 /* XXX: In theory, we could pass the internal events through to
4297 * everything and only convert just before hitting the wire. We can't
4298 * do that yet, so DGE is the last stop for internal events. From here
4299 * onwards, we deal with core/XI events.
4300 */
4301
4302 sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
4303 /* try core event */
4304 if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
4305 deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype);
4306
4307 if (deliveries && (event->any.type == ET_Motion))
4308 thisDev->valuator->motionHintWindow = grab->window;
4309 }
4310 if (deliveries && !deactivateGrab &&
4311 (event->any.type == ET_KeyPress ||
4312 event->any.type == ET_KeyRelease ||
4313 event->any.type == ET_ButtonPress ||
4314 event->any.type == ET_ButtonRelease)) {
4315 switch (grabinfo->sync.state) {
4316 case FREEZE_BOTH_NEXT_EVENT:
4317 dev = GetPairedDevice(thisDev);
4318 if (dev) {
4319 FreezeThaw(dev, TRUE);
4320 if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
4321 (CLIENT_BITS(grab->resource) ==
4322 CLIENT_BITS(dev->deviceGrab.grab->resource)))
4323 dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
4324 else
4325 dev->deviceGrab.sync.other = grab;
4326 }
4327 /* fall through */
4328 case FREEZE_NEXT_EVENT:
4329 grabinfo->sync.state = FROZEN_WITH_EVENT;
4330 FreezeThaw(thisDev, TRUE);
4331 *grabinfo->sync.event = event->device_event;
4332 break;
4333 }
4334 }
4335
4336 return deliveries;
4337}
4338
4339/* This function is used to set the key pressed or key released state -
4340 this is only used when the pressing of keys does not cause
4341 the device's processInputProc to be called, as in for example Mouse Keys.
4342*/
4343void
4344FixKeyState(DeviceEvent *event, DeviceIntPtr keybd)
4345{
4346 int key = event->detail.key;
4347
4348 if (event->type == ET_KeyPress) {
4349 DebugF("FixKeyState: Key %d %s\n", key,
4350 ((event->type == ET_KeyPress) ? "down" : "up"));
4351 }
4352
4353 if (event->type == ET_KeyPress)
4354 set_key_down(keybd, key, KEY_PROCESSED);
4355 else if (event->type == ET_KeyRelease)
4356 set_key_up(keybd, key, KEY_PROCESSED);
4357 else
4358 FatalError("Impossible keyboard event");
4359}
4360
4361#define AtMostOneClient \
4362 (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
4363#define ManagerMask \
4364 (SubstructureRedirectMask | ResizeRedirectMask)
4365
4366/**
4367 * Recalculate which events may be deliverable for the given window.
4368 * Recalculated mask is used for quicker determination which events may be
4369 * delivered to a window.
4370 *
4371 * The otherEventMasks on a WindowOptional is the combination of all event
4372 * masks set by all clients on the window.
4373 * deliverableEventMask is the combination of the eventMask and the
4374 * otherEventMask plus the events that may be propagated to the parent.
4375 *
4376 * Traverses to siblings and parents of the window.
4377 */
4378void
4379RecalculateDeliverableEvents(WindowPtr pWin)
4380{
4381 OtherClients *others;
4382 WindowPtr pChild;
4383
4384 pChild = pWin;
4385 while (1) {
4386 if (pChild->optional) {
4387 pChild->optional->otherEventMasks = 0;
4388 for (others = wOtherClients(pChild); others; others = others->next) {
4389 pChild->optional->otherEventMasks |= others->mask;
4390 }
4391 }
4392 pChild->deliverableEvents = pChild->eventMask |
4393 wOtherEventMasks(pChild);
4394 if (pChild->parent)
4395 pChild->deliverableEvents |=
4396 (pChild->parent->deliverableEvents &
4397 ~wDontPropagateMask(pChild) & PropagateMask);
4398 if (pChild->firstChild) {
4399 pChild = pChild->firstChild;
4400 continue;
4401 }
4402 while (!pChild->nextSib && (pChild != pWin))
4403 pChild = pChild->parent;
4404 if (pChild == pWin)
4405 break;
4406 pChild = pChild->nextSib;
4407 }
4408}
4409
4410/**
4411 *
4412 * \param value must conform to DeleteType
4413 */
4414int
4415OtherClientGone(pointer value, XID id)
4416{
4417 OtherClientsPtr other, prev;
4418 WindowPtr pWin = (WindowPtr) value;
4419
4420 prev = 0;
4421 for (other = wOtherClients(pWin); other; other = other->next) {
4422 if (other->resource == id) {
4423 if (prev)
4424 prev->next = other->next;
4425 else {
4426 if (!(pWin->optional->otherClients = other->next))
4427 CheckWindowOptionalNeed(pWin);
4428 }
4429 free(other);
4430 RecalculateDeliverableEvents(pWin);
4431 return Success;
4432 }
4433 prev = other;
4434 }
4435 FatalError("client not on event list");
4436}
4437
4438int
4439EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
4440{
4441 Mask check;
4442 OtherClients *others;
4443 DeviceIntPtr dev;
4444 int rc;
4445
4446 if (mask & ~AllEventMasks) {
4447 client->errorValue = mask;
4448 return BadValue;
4449 }
4450 check = (mask & ManagerMask);
4451 if (check) {
4452 rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
4453 RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
4454 if (rc != Success)
4455 return rc;
4456 }
4457 check = (mask & AtMostOneClient);
4458 if (check & (pWin->eventMask | wOtherEventMasks(pWin))) {
4459 /* It is illegal for two different clients to select on any of the
4460 events for AtMostOneClient. However, it is OK, for some client to
4461 continue selecting on one of those events. */
4462 if ((wClient(pWin) != client) && (check & pWin->eventMask))
4463 return BadAccess;
4464 for (others = wOtherClients(pWin); others; others = others->next) {
4465 if (!SameClient(others, client) && (check & others->mask))
4466 return BadAccess;
4467 }
4468 }
4469 if (wClient(pWin) == client) {
4470 check = pWin->eventMask;
4471 pWin->eventMask = mask;
4472 }
4473 else {
4474 for (others = wOtherClients(pWin); others; others = others->next) {
4475 if (SameClient(others, client)) {
4476 check = others->mask;
4477 if (mask == 0) {
4478 FreeResource(others->resource, RT_NONE);
4479 return Success;
4480 }
4481 else
4482 others->mask = mask;
4483 goto maskSet;
4484 }
4485 }
4486 check = 0;
4487 if (!pWin->optional && !MakeWindowOptional(pWin))
4488 return BadAlloc;
4489 others = malloc(sizeof(OtherClients));
4490 if (!others)
4491 return BadAlloc;
4492 others->mask = mask;
4493 others->resource = FakeClientID(client->index);
4494 others->next = pWin->optional->otherClients;
4495 pWin->optional->otherClients = others;
4496 if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer) pWin))
4497 return BadAlloc;
4498 }
4499 maskSet:
4500 if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) {
4501 for (dev = inputInfo.devices; dev; dev = dev->next) {
4502 if (dev->valuator && dev->valuator->motionHintWindow == pWin)
4503 dev->valuator->motionHintWindow = NullWindow;
4504 }
4505 }
4506 RecalculateDeliverableEvents(pWin);
4507 return Success;
4508}
4509
4510int
4511EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
4512 Mask mask, Bool *checkOptional)
4513{
4514 int i, freed;
4515
4516 if (mask & ~PropagateMask) {
4517 client->errorValue = mask;
4518 return BadValue;
4519 }
4520 if (pWin->dontPropagate)
4521 DontPropagateRefCnts[pWin->dontPropagate]--;
4522 if (!mask)
4523 i = 0;
4524 else {
4525 for (i = DNPMCOUNT, freed = 0; --i > 0;) {
4526 if (!DontPropagateRefCnts[i])
4527 freed = i;
4528 else if (mask == DontPropagateMasks[i])
4529 break;
4530 }
4531 if (!i && freed) {
4532 i = freed;
4533 DontPropagateMasks[i] = mask;
4534 }
4535 }
4536 if (i || !mask) {
4537 pWin->dontPropagate = i;
4538 if (i)
4539 DontPropagateRefCnts[i]++;
4540 if (pWin->optional) {
4541 pWin->optional->dontPropagateMask = mask;
4542 *checkOptional = TRUE;
4543 }
4544 }
4545 else {
4546 if (!pWin->optional && !MakeWindowOptional(pWin)) {
4547 if (pWin->dontPropagate)
4548 DontPropagateRefCnts[pWin->dontPropagate]++;
4549 return BadAlloc;
4550 }
4551 pWin->dontPropagate = 0;
4552 pWin->optional->dontPropagateMask = mask;
4553 }
4554 RecalculateDeliverableEvents(pWin);
4555 return Success;
4556}
4557
4558/**
4559 * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
4560 * Uses the paired keyboard to get some additional information.
4561 */
4562void
4563CoreEnterLeaveEvent(DeviceIntPtr mouse,
4564 int type,
4565 int mode, int detail, WindowPtr pWin, Window child)
4566{
4567 xEvent event = {
4568 .u.u.type = type,
4569 .u.u.detail = detail
4570 };
4571 WindowPtr focus;
4572 DeviceIntPtr keybd;
4573 GrabPtr grab = mouse->deviceGrab.grab;
4574 Mask mask;
4575
4576 keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT);
4577
4578 if ((pWin == mouse->valuator->motionHintWindow) &&
4579 (detail != NotifyInferior))
4580 mouse->valuator->motionHintWindow = NullWindow;
4581 if (grab) {
4582 mask = (pWin == grab->window) ? grab->eventMask : 0;
4583 if (grab->ownerEvents)
4584 mask |= EventMaskForClient(pWin, rClient(grab));
4585 }
4586 else {
4587 mask = pWin->eventMask | wOtherEventMasks(pWin);
4588 }
4589
4590 event.u.enterLeave.time = currentTime.milliseconds;
4591 event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
4592 event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
4593 /* Counts on the same initial structure of crossing & button events! */
4594 FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
4595 /* Enter/Leave events always set child */
4596 event.u.enterLeave.child = child;
4597 event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
4598 ELFlagSameScreen : 0;
4599 event.u.enterLeave.state =
4600 mouse->button ? (mouse->button->state & 0x1f00) : 0;
4601 if (keybd)
4602 event.u.enterLeave.state |=
4603 XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
4604 event.u.enterLeave.mode = mode;
4605 focus = (keybd) ? keybd->focus->win : None;
4606 if ((focus != NoneWin) &&
4607 ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
4608 event.u.enterLeave.flags |= ELFlagFocus;
4609
4610 if ((mask & GetEventFilter(mouse, &event))) {
4611 if (grab)
4612 TryClientEvents(rClient(grab), mouse, &event, 1, mask,
4613 GetEventFilter(mouse, &event), grab);
4614 else
4615 DeliverEventsToWindow(mouse, pWin, &event, 1,
4616 GetEventFilter(mouse, &event), NullGrab);
4617 }
4618
4619 if ((type == EnterNotify) && (mask & KeymapStateMask)) {
4620 xKeymapEvent ke = {
4621 .type = KeymapNotify
4622 };
4623 ClientPtr client = grab ? rClient(grab) : wClient(pWin);
4624 int rc;
4625
4626 rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
4627 if (rc == Success)
4628 memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31);
4629
4630 if (grab)
4631 TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1,
4632 mask, KeymapStateMask, grab);
4633 else
4634 DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1,
4635 KeymapStateMask, NullGrab);
4636 }
4637}
4638
4639void
4640DeviceEnterLeaveEvent(DeviceIntPtr mouse,
4641 int sourceid,
4642 int type,
4643 int mode, int detail, WindowPtr pWin, Window child)
4644{
4645 GrabPtr grab = mouse->deviceGrab.grab;
4646 xXIEnterEvent *event;
4647 WindowPtr focus;
4648 int filter;
4649 int btlen, len, i;
4650 DeviceIntPtr kbd;
4651
4652 if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
4653 (mode == XINotifyPassiveUngrab && type == XI_Enter))
4654 return;
4655
4656 btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
4657 btlen = bytes_to_int32(btlen);
4658 len = sizeof(xXIEnterEvent) + btlen * 4;
4659
4660 event = calloc(1, len);
4661 event->type = GenericEvent;
4662 event->extension = IReqCode;
4663 event->evtype = type;
4664 event->length = (len - sizeof(xEvent)) / 4;
4665 event->buttons_len = btlen;
4666 event->detail = detail;
4667 event->time = currentTime.milliseconds;
4668 event->deviceid = mouse->id;
4669 event->sourceid = sourceid;
4670 event->mode = mode;
4671 event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x);
4672 event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y);
4673
4674 for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
4675 if (BitIsOn(mouse->button->down, i))
4676 SetBit(&event[1], i);
4677
4678 kbd = GetMaster(mouse, MASTER_KEYBOARD);
4679 if (kbd && kbd->key) {
4680 event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
4681 event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
4682 event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
4683
4684 event->group.base_group = kbd->key->xkbInfo->state.base_group;
4685 event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
4686 event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
4687 }
4688
4689 focus = (kbd) ? kbd->focus->win : None;
4690 if ((focus != NoneWin) &&
4691 ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
4692 event->focus = TRUE;
4693
4694 FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
4695 None, FALSE);
4696
4697 filter = GetEventFilter(mouse, (xEvent *) event);
4698
4699 if (grab && grab->grabtype == XI2) {
4700 Mask mask;
4701
4702 mask = xi2mask_isset(grab->xi2mask, mouse, type);
4703 TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1,
4704 grab);
4705 }
4706 else {
4707 if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event))
4708 goto out;
4709 DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter,
4710 NullGrab);
4711 }
4712
4713 out:
4714 free(event);
4715}
4716
4717void
4718CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
4719{
4720 xEvent event = {
4721 .u.u.type = type,
4722 .u.u.detail = detail
4723 };
4724 event.u.focus.mode = mode;
4725 event.u.focus.window = pWin->drawable.id;
4726
4727 DeliverEventsToWindow(dev, pWin, &event, 1,
4728 GetEventFilter(dev, &event), NullGrab);
4729 if ((type == FocusIn) &&
4730 ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) {
4731 xKeymapEvent ke = {
4732 .type = KeymapNotify
4733 };
4734 ClientPtr client = wClient(pWin);
4735 int rc;
4736
4737 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
4738 if (rc == Success)
4739 memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31);
4740
4741 DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1,
4742 KeymapStateMask, NullGrab);
4743 }
4744}
4745
4746/**
4747 * Set the input focus to the given window. Subsequent keyboard events will be
4748 * delivered to the given window.
4749 *
4750 * Usually called from ProcSetInputFocus as result of a client request. If so,
4751 * the device is the inputInfo.keyboard.
4752 * If called from ProcXSetInputFocus as result of a client xinput request, the
4753 * device is set to the device specified by the client.
4754 *
4755 * @param client Client that requested input focus change.
4756 * @param dev Focus device.
4757 * @param focusID The window to obtain the focus. Can be PointerRoot or None.
4758 * @param revertTo Specifies where the focus reverts to when window becomes
4759 * unviewable.
4760 * @param ctime Specifies the time.
4761 * @param followOK True if pointer is allowed to follow the keyboard.
4762 */
4763int
4764SetInputFocus(ClientPtr client,
4765 DeviceIntPtr dev,
4766 Window focusID, CARD8 revertTo, Time ctime, Bool followOK)
4767{
4768 FocusClassPtr focus;
4769 WindowPtr focusWin;
4770 int mode, rc;
4771 TimeStamp time;
4772 DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
4773
4774 UpdateCurrentTime();
4775 if ((revertTo != RevertToParent) &&
4776 (revertTo != RevertToPointerRoot) &&
4777 (revertTo != RevertToNone) &&
4778 ((revertTo != RevertToFollowKeyboard) || !followOK)) {
4779 client->errorValue = revertTo;
4780 return BadValue;
4781 }
4782 time = ClientTimeToServerTime(ctime);
4783
4784 keybd = GetMaster(dev, KEYBOARD_OR_FLOAT);
4785
4786 if ((focusID == None) || (focusID == PointerRoot))
4787 focusWin = (WindowPtr) (long) focusID;
4788 else if ((focusID == FollowKeyboard) && followOK) {
4789 focusWin = keybd->focus->win;
4790 }
4791 else {
4792 rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
4793 if (rc != Success)
4794 return rc;
4795 /* It is a match error to try to set the input focus to an
4796 unviewable window. */
4797 if (!focusWin->realized)
4798 return BadMatch;
4799 }
4800 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
4801 if (rc != Success)
4802 return Success;
4803
4804 focus = dev->focus;
4805 if ((CompareTimeStamps(time, currentTime) == LATER) ||
4806 (CompareTimeStamps(time, focus->time) == EARLIER))
4807 return Success;
4808 mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
4809 if (focus->win == FollowKeyboardWin) {
4810 if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
4811 DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
4812 }
4813 else {
4814 if (!ActivateFocusInGrab(dev, focus->win, focusWin))
4815 DoFocusEvents(dev, focus->win, focusWin, mode);
4816 }
4817 focus->time = time;
4818 focus->revert = revertTo;
4819 if (focusID == FollowKeyboard)
4820 focus->win = FollowKeyboardWin;
4821 else
4822 focus->win = focusWin;
4823 if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
4824 focus->traceGood = 0;
4825 else {
4826 int depth = 0;
4827 WindowPtr pWin;
4828
4829 for (pWin = focusWin; pWin; pWin = pWin->parent)
4830 depth++;
4831 if (depth > focus->traceSize) {
4832 focus->traceSize = depth + 1;
4833 focus->trace = realloc(focus->trace,
4834 focus->traceSize * sizeof(WindowPtr));
4835 }
4836 focus->traceGood = depth;
4837 for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
4838 focus->trace[depth] = pWin;
4839 }
4840 return Success;
4841}
4842
4843/**
4844 * Server-side protocol handling for SetInputFocus request.
4845 *
4846 * Sets the input focus for the virtual core keyboard.
4847 */
4848int
4849ProcSetInputFocus(ClientPtr client)
4850{
4851 DeviceIntPtr kbd = PickKeyboard(client);
4852
4853 REQUEST(xSetInputFocusReq);
4854
4855 REQUEST_SIZE_MATCH(xSetInputFocusReq);
4856
4857 return SetInputFocus(client, kbd, stuff->focus,
4858 stuff->revertTo, stuff->time, FALSE);
4859}
4860
4861/**
4862 * Server-side protocol handling for GetInputFocus request.
4863 *
4864 * Sends the current input focus for the client's keyboard back to the
4865 * client.
4866 */
4867int
4868ProcGetInputFocus(ClientPtr client)
4869{
4870 DeviceIntPtr kbd = PickKeyboard(client);
4871 xGetInputFocusReply rep;
4872 FocusClassPtr focus = kbd->focus;
4873 int rc;
4874
4875 /* REQUEST(xReq); */
4876 REQUEST_SIZE_MATCH(xReq);
4877
4878 rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
4879 if (rc != Success)
4880 return rc;
4881
4882 rep = (xGetInputFocusReply) {
4883 .type = X_Reply,
4884 .length = 0,
4885 .sequenceNumber = client->sequence,
4886 .revertTo = focus->revert
4887 };
4888
4889 if (focus->win == NoneWin)
4890 rep.focus = None;
4891 else if (focus->win == PointerRootWin)
4892 rep.focus = PointerRoot;
4893 else
4894 rep.focus = focus->win->drawable.id;
4895
4896 WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
4897 return Success;
4898}
4899
4900/**
4901 * Server-side protocol handling for GrabPointer request.
4902 *
4903 * Sets an active grab on the client's ClientPointer and returns success
4904 * status to client.
4905 */
4906int
4907ProcGrabPointer(ClientPtr client)
4908{
4909 xGrabPointerReply rep;
4910 DeviceIntPtr device = PickPointer(client);
4911 GrabPtr grab;
4912 GrabMask mask;
4913 WindowPtr confineTo;
4914 BYTE status;
4915
4916 REQUEST(xGrabPointerReq);
4917 int rc;
4918
4919 REQUEST_SIZE_MATCH(xGrabPointerReq);
4920 UpdateCurrentTime();
4921
4922 if (stuff->eventMask & ~PointerGrabMask) {
4923 client->errorValue = stuff->eventMask;
4924 return BadValue;
4925 }
4926
4927 if (stuff->confineTo == None)
4928 confineTo = NullWindow;
4929 else {
4930 rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4931 DixSetAttrAccess);
4932 if (rc != Success)
4933 return rc;
4934 }
4935
4936 grab = device->deviceGrab.grab;
4937
4938 if (grab && grab->confineTo && !confineTo)
4939 ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE);
4940
4941 mask.core = stuff->eventMask;
4942
4943 rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
4944 stuff->grabWindow, stuff->ownerEvents, stuff->time,
4945 &mask, CORE, stuff->cursor, stuff->confineTo, &status);
4946 if (rc != Success)
4947 return rc;
4948
4949 rep = (xGrabPointerReply) {
4950 .type = X_Reply,
4951 .status = status,
4952 .sequenceNumber = client->sequence,
4953 .length = 0
4954 };
4955 WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
4956 return Success;
4957}
4958
4959/**
4960 * Server-side protocol handling for ChangeActivePointerGrab request.
4961 *
4962 * Changes properties of the grab hold by the client. If the client does not
4963 * hold an active grab on the device, nothing happens.
4964 */
4965int
4966ProcChangeActivePointerGrab(ClientPtr client)
4967{
4968 DeviceIntPtr device;
4969 GrabPtr grab;
4970 CursorPtr newCursor, oldCursor;
4971
4972 REQUEST(xChangeActivePointerGrabReq);
4973 TimeStamp time;
4974
4975 REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
4976 if (stuff->eventMask & ~PointerGrabMask) {
4977 client->errorValue = stuff->eventMask;
4978 return BadValue;
4979 }
4980 if (stuff->cursor == None)
4981 newCursor = NullCursor;
4982 else {
4983 int rc = dixLookupResourceByType((pointer *) &newCursor, stuff->cursor,
4984 RT_CURSOR, client, DixUseAccess);
4985
4986 if (rc != Success) {
4987 client->errorValue = stuff->cursor;
4988 return rc;
4989 }
4990 }
4991
4992 device = PickPointer(client);
4993 grab = device->deviceGrab.grab;
4994
4995 if (!grab)
4996 return Success;
4997 if (!SameClient(grab, client))
4998 return Success;
4999 time = ClientTimeToServerTime(stuff->time);
5000 if ((CompareTimeStamps(time, currentTime) == LATER) ||
5001 (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
5002 return Success;
5003 oldCursor = grab->cursor;
5004 grab->cursor = RefCursor(newCursor);
5005 PostNewCursor(device);
5006 if (oldCursor)
5007 FreeCursor(oldCursor, (Cursor) 0);
5008 grab->eventMask = stuff->eventMask;
5009 return Success;
5010}
5011
5012/**
5013 * Server-side protocol handling for UngrabPointer request.
5014 *
5015 * Deletes a pointer grab on a device the client has grabbed.
5016 */
5017int
5018ProcUngrabPointer(ClientPtr client)
5019{
5020 DeviceIntPtr device = PickPointer(client);
5021 GrabPtr grab;
5022 TimeStamp time;
5023
5024 REQUEST(xResourceReq);
5025
5026 REQUEST_SIZE_MATCH(xResourceReq);
5027 UpdateCurrentTime();
5028 grab = device->deviceGrab.grab;
5029
5030 time = ClientTimeToServerTime(stuff->id);
5031 if ((CompareTimeStamps(time, currentTime) != LATER) &&
5032 (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
5033 (grab) && SameClient(grab, client))
5034 (*device->deviceGrab.DeactivateGrab) (device);
5035 return Success;
5036}
5037
5038/**
5039 * Sets a grab on the given device.
5040 *
5041 * Called from ProcGrabKeyboard to work on the client's keyboard.
5042 * Called from ProcXGrabDevice to work on the device specified by the client.
5043 *
5044 * The parameters this_mode and other_mode represent the keyboard_mode and
5045 * pointer_mode parameters of XGrabKeyboard().
5046 * See man page for details on all the parameters
5047 *
5048 * @param client Client that owns the grab.
5049 * @param dev The device to grab.
5050 * @param this_mode GrabModeSync or GrabModeAsync
5051 * @param other_mode GrabModeSync or GrabModeAsync
5052 * @param status Return code to be returned to the caller.
5053 *
5054 * @returns Success or BadValue.
5055 */
5056int
5057GrabDevice(ClientPtr client, DeviceIntPtr dev,
5058 unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
5059 unsigned ownerEvents, Time ctime, GrabMask *mask,
5060 int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
5061{
5062 WindowPtr pWin, confineTo;
5063 GrabPtr grab;
5064 TimeStamp time;
5065 Mask access_mode = DixGrabAccess;
5066 int rc;
5067 GrabInfoPtr grabInfo = &dev->deviceGrab;
5068 CursorPtr cursor;
5069
5070 UpdateCurrentTime();
5071 if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) {
5072 client->errorValue = keyboard_mode;
5073 return BadValue;
5074 }
5075 if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) {
5076 client->errorValue = pointer_mode;
5077 return BadValue;
5078 }
5079 if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
5080 client->errorValue = ownerEvents;
5081 return BadValue;
5082 }
5083
5084 rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
5085 if (rc != Success)
5086 return rc;
5087
5088 if (confineToWin == None)
5089 confineTo = NullWindow;
5090 else {
5091 rc = dixLookupWindow(&confineTo, confineToWin, client,
5092 DixSetAttrAccess);
5093 if (rc != Success)
5094 return rc;
5095 }
5096
5097 if (curs == None)
5098 cursor = NullCursor;
5099 else {
5100 rc = dixLookupResourceByType((pointer *) &cursor, curs, RT_CURSOR,
5101 client, DixUseAccess);
5102 if (rc != Success) {
5103 client->errorValue = curs;
5104 return rc;
5105 }
5106 access_mode |= DixForceAccess;
5107 }
5108
5109 if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
5110 access_mode |= DixFreezeAccess;
5111 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
5112 if (rc != Success)
5113 return rc;
5114
5115 time = ClientTimeToServerTime(ctime);
5116 grab = grabInfo->grab;
5117 if (grab && grab->grabtype != grabtype)
5118 *status = AlreadyGrabbed;
5119 else if (grab && !SameClient(grab, client))
5120 *status = AlreadyGrabbed;
5121 else if ((!pWin->realized) ||
5122 (confineTo &&
5123 !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo))))
5124 *status = GrabNotViewable;
5125 else if ((CompareTimeStamps(time, currentTime) == LATER) ||
5126 (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
5127 *status = GrabInvalidTime;
5128 else if (grabInfo->sync.frozen &&
5129 grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
5130 *status = GrabFrozen;
5131 else {
5132 GrabPtr tempGrab;
5133
5134 tempGrab = AllocGrab(NULL);
5135
5136 tempGrab->next = NULL;
5137 tempGrab->window = pWin;
5138 tempGrab->resource = client->clientAsMask;
5139 tempGrab->ownerEvents = ownerEvents;
5140 tempGrab->keyboardMode = keyboard_mode;
5141 tempGrab->pointerMode = pointer_mode;
5142 if (grabtype == CORE)
5143 tempGrab->eventMask = mask->core;
5144 else if (grabtype == XI)
5145 tempGrab->eventMask = mask->xi;
5146 else
5147 xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
5148 tempGrab->device = dev;
5149 tempGrab->cursor = RefCursor(cursor);
5150 tempGrab->confineTo = confineTo;
5151 tempGrab->grabtype = grabtype;
5152 (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE);
5153 *status = GrabSuccess;
5154
5155 FreeGrab(tempGrab);
5156 }
5157 return Success;
5158}
5159
5160/**
5161 * Server-side protocol handling for GrabKeyboard request.
5162 *
5163 * Grabs the client's keyboard and returns success status to client.
5164 */
5165int
5166ProcGrabKeyboard(ClientPtr client)
5167{
5168 xGrabKeyboardReply rep;
5169 BYTE status;
5170
5171 REQUEST(xGrabKeyboardReq);
5172 int result;
5173 DeviceIntPtr keyboard = PickKeyboard(client);
5174 GrabMask mask;
5175
5176 REQUEST_SIZE_MATCH(xGrabKeyboardReq);
5177
5178 mask.core = KeyPressMask | KeyReleaseMask;
5179
5180 result = GrabDevice(client, keyboard, stuff->pointerMode,
5181 stuff->keyboardMode, stuff->grabWindow,
5182 stuff->ownerEvents, stuff->time, &mask, CORE, None,
5183 None, &status);
5184
5185 if (result != Success)
5186 return result;
5187
5188 rep = (xGrabKeyboardReply) {
5189 .type = X_Reply,
5190 .status = status,
5191 .sequenceNumber = client->sequence,
5192 .length = 0
5193 };
5194 WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
5195 return Success;
5196}
5197
5198/**
5199 * Server-side protocol handling for UngrabKeyboard request.
5200 *
5201 * Deletes a possible grab on the client's keyboard.
5202 */
5203int
5204ProcUngrabKeyboard(ClientPtr client)
5205{
5206 DeviceIntPtr device = PickKeyboard(client);
5207 GrabPtr grab;
5208 TimeStamp time;
5209
5210 REQUEST(xResourceReq);
5211
5212 REQUEST_SIZE_MATCH(xResourceReq);
5213 UpdateCurrentTime();
5214
5215 grab = device->deviceGrab.grab;
5216
5217 time = ClientTimeToServerTime(stuff->id);
5218 if ((CompareTimeStamps(time, currentTime) != LATER) &&
5219 (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
5220 (grab) && SameClient(grab, client) && grab->grabtype == CORE)
5221 (*device->deviceGrab.DeactivateGrab) (device);
5222 return Success;
5223}
5224
5225/**
5226 * Server-side protocol handling for QueryPointer request.
5227 *
5228 * Returns the current state and position of the client's ClientPointer to the
5229 * client.
5230 */
5231int
5232ProcQueryPointer(ClientPtr client)
5233{
5234 xQueryPointerReply rep;
5235 WindowPtr pWin, t;
5236 DeviceIntPtr mouse = PickPointer(client);
5237 DeviceIntPtr keyboard;
5238 SpritePtr pSprite;
5239 int rc;
5240
5241 REQUEST(xResourceReq);
5242 REQUEST_SIZE_MATCH(xResourceReq);
5243
5244 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
5245 if (rc != Success)
5246 return rc;
5247 rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
5248 if (rc != Success && rc != BadAccess)
5249 return rc;
5250
5251 keyboard = GetMaster(mouse, MASTER_KEYBOARD);
5252
5253 pSprite = mouse->spriteInfo->sprite;
5254 if (mouse->valuator->motionHintWindow)
5255 MaybeStopHint(mouse, client);
5256 rep = (xQueryPointerReply) {
5257 .type = X_Reply,
5258 .sequenceNumber = client->sequence,
5259 .length = 0,
5260 .mask = event_get_corestate(mouse, keyboard),
5261 .root = (GetCurrentRootWindow(mouse))->drawable.id,
5262 .rootX = pSprite->hot.x,
5263 .rootY = pSprite->hot.y,
5264 .child = None
5265 };
5266 if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
5267 rep.sameScreen = xTrue;
5268 rep.winX = pSprite->hot.x - pWin->drawable.x;
5269 rep.winY = pSprite->hot.y - pWin->drawable.y;
5270 for (t = pSprite->win; t; t = t->parent)
5271 if (t->parent == pWin) {
5272 rep.child = t->drawable.id;
5273 break;
5274 }
5275 }
5276 else {
5277 rep.sameScreen = xFalse;
5278 rep.winX = 0;
5279 rep.winY = 0;
5280 }
5281
5282#ifdef PANORAMIX
5283 if (!noPanoramiXExtension) {
5284 rep.rootX += screenInfo.screens[0]->x;
5285 rep.rootY += screenInfo.screens[0]->y;
5286 if (stuff->id == rep.root) {
5287 rep.winX += screenInfo.screens[0]->x;
5288 rep.winY += screenInfo.screens[0]->y;
5289 }
5290 }
5291#endif
5292
5293 if (rc == BadAccess) {
5294 rep.mask = 0;
5295 rep.child = None;
5296 rep.rootX = 0;
5297 rep.rootY = 0;
5298 rep.winX = 0;
5299 rep.winY = 0;
5300 }
5301
5302 WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
5303
5304 return Success;
5305}
5306
5307/**
5308 * Initializes the device list and the DIX sprite to sane values. Allocates
5309 * trace memory used for quick window traversal.
5310 */
5311void
5312InitEvents(void)
5313{
5314 int i;
5315 QdEventPtr qe, tmp;
5316
5317 inputInfo.numDevices = 0;
5318 inputInfo.devices = (DeviceIntPtr) NULL;
5319 inputInfo.off_devices = (DeviceIntPtr) NULL;
5320 inputInfo.keyboard = (DeviceIntPtr) NULL;
5321 inputInfo.pointer = (DeviceIntPtr) NULL;
5322
5323 for (i = 0; i < MAXDEVICES; i++) {
5324 DeviceIntRec dummy;
5325 memcpy(&event_filters[i], default_filter, sizeof(default_filter));
5326
5327 dummy.id = i;
5328 NoticeTime(&dummy, currentTime);
5329 LastEventTimeToggleResetFlag(i, FALSE);
5330 }
5331
5332 syncEvents.replayDev = (DeviceIntPtr) NULL;
5333 syncEvents.replayWin = NullWindow;
5334 if (syncEvents.pending.next)
5335 xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
5336 free(qe);
5337 xorg_list_init(&syncEvents.pending);
5338 syncEvents.playingEvents = FALSE;
5339 syncEvents.time.months = 0;
5340 syncEvents.time.milliseconds = 0; /* hardly matters */
5341 currentTime.months = 0;
5342 currentTime.milliseconds = GetTimeInMillis();
5343 for (i = 0; i < DNPMCOUNT; i++) {
5344 DontPropagateMasks[i] = 0;
5345 DontPropagateRefCnts[i] = 0;
5346 }
5347
5348 InputEventList = InitEventList(GetMaximumEventsNum());
5349 if (!InputEventList)
5350 FatalError("[dix] Failed to allocate input event list.\n");
5351}
5352
5353void
5354CloseDownEvents(void)
5355{
5356 FreeEventList(InputEventList, GetMaximumEventsNum());
5357 InputEventList = NULL;
5358}
5359
5360#define SEND_EVENT_BIT 0x80
5361
5362/**
5363 * Server-side protocol handling for SendEvent request.
5364 *
5365 * Locates the window to send the event to and forwards the event.
5366 */
5367int
5368ProcSendEvent(ClientPtr client)
5369{
5370 WindowPtr pWin;
5371 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
5372 DeviceIntPtr dev = PickPointer(client);
5373 DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD);
5374 SpritePtr pSprite = dev->spriteInfo->sprite;
5375
5376 REQUEST(xSendEventReq);
5377
5378 REQUEST_SIZE_MATCH(xSendEventReq);
5379
5380 /* libXext and other extension libraries may set the bit indicating
5381 * that this event came from a SendEvent request so remove it
5382 * since otherwise the event type may fail the range checks
5383 * and cause an invalid BadValue error to be returned.
5384 *
5385 * This is safe to do since we later add the SendEvent bit (0x80)
5386 * back in once we send the event to the client */
5387
5388 stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5389
5390 /* The client's event type must be a core event type or one defined by an
5391 extension. */
5392
5393 if (!((stuff->event.u.u.type > X_Reply &&
5394 stuff->event.u.u.type < LASTEvent) ||
5395 (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
5396 stuff->event.u.u.type < (unsigned) lastEvent))) {
5397 client->errorValue = stuff->event.u.u.type;
5398 return BadValue;
5399 }
5400 if (stuff->event.u.u.type == ClientMessage &&
5401 stuff->event.u.u.detail != 8 &&
5402 stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) {
5403 client->errorValue = stuff->event.u.u.detail;
5404 return BadValue;
5405 }
5406 if (stuff->eventMask & ~AllEventMasks) {
5407 client->errorValue = stuff->eventMask;
5408 return BadValue;
5409 }
5410
5411 if (stuff->destination == PointerWindow)
5412 pWin = pSprite->win;
5413 else if (stuff->destination == InputFocus) {
5414 WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
5415
5416 if (inputFocus == NoneWin)
5417 return Success;
5418
5419 /* If the input focus is PointerRootWin, send the event to where
5420 the pointer is if possible, then perhaps propogate up to root. */
5421 if (inputFocus == PointerRootWin)
5422 inputFocus = GetCurrentRootWindow(dev);
5423
5424 if (IsParent(inputFocus, pSprite->win)) {
5425 effectiveFocus = inputFocus;
5426 pWin = pSprite->win;
5427 }
5428 else
5429 effectiveFocus = pWin = inputFocus;
5430 }
5431 else
5432 dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
5433
5434 if (!pWin)
5435 return BadWindow;
5436 if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) {
5437 client->errorValue = stuff->propagate;
5438 return BadValue;
5439 }
5440 stuff->event.u.u.type |= SEND_EVENT_BIT;
5441 if (stuff->propagate) {
5442 for (; pWin; pWin = pWin->parent) {
5443 if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
5444 &stuff->event, 1))
5445 return Success;
5446 if (DeliverEventsToWindow(dev, pWin,
5447 &stuff->event, 1, stuff->eventMask,
5448 NullGrab))
5449 return Success;
5450 if (pWin == effectiveFocus)
5451 return Success;
5452 stuff->eventMask &= ~wDontPropagateMask(pWin);
5453 if (!stuff->eventMask)
5454 break;
5455 }
5456 }
5457 else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
5458 DeliverEventsToWindow(dev, pWin, &stuff->event,
5459 1, stuff->eventMask, NullGrab);
5460 return Success;
5461}
5462
5463/**
5464 * Server-side protocol handling for UngrabKey request.
5465 *
5466 * Deletes a passive grab for the given key. Works on the
5467 * client's keyboard.
5468 */
5469int
5470ProcUngrabKey(ClientPtr client)
5471{
5472 REQUEST(xUngrabKeyReq);
5473 WindowPtr pWin;
5474 GrabPtr tempGrab;
5475 DeviceIntPtr keybd = PickKeyboard(client);
5476 int rc;
5477
5478 REQUEST_SIZE_MATCH(xUngrabKeyReq);
5479 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
5480 if (rc != Success)
5481 return rc;
5482
5483 if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5484 (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5485 && (stuff->key != AnyKey)) {
5486 client->errorValue = stuff->key;
5487 return BadValue;
5488 }
5489 if ((stuff->modifiers != AnyModifier) &&
5490 (stuff->modifiers & ~AllModifiersMask)) {
5491 client->errorValue = stuff->modifiers;
5492 return BadValue;
5493 }
5494 tempGrab = AllocGrab(NULL);
5495 if (!tempGrab)
5496 return BadAlloc;
5497 tempGrab->resource = client->clientAsMask;
5498 tempGrab->device = keybd;
5499 tempGrab->window = pWin;
5500 tempGrab->modifiersDetail.exact = stuff->modifiers;
5501 tempGrab->modifiersDetail.pMask = NULL;
5502 tempGrab->modifierDevice = keybd;
5503 tempGrab->type = KeyPress;
5504 tempGrab->grabtype = CORE;
5505 tempGrab->detail.exact = stuff->key;
5506 tempGrab->detail.pMask = NULL;
5507 tempGrab->next = NULL;
5508
5509 if (!DeletePassiveGrabFromList(tempGrab))
5510 rc = BadAlloc;
5511
5512 FreeGrab(tempGrab);
5513
5514 return rc;
5515}
5516
5517/**
5518 * Server-side protocol handling for GrabKey request.
5519 *
5520 * Creates a grab for the client's keyboard and adds it to the list of passive
5521 * grabs.
5522 */
5523int
5524ProcGrabKey(ClientPtr client)
5525{
5526 WindowPtr pWin;
5527
5528 REQUEST(xGrabKeyReq);
5529 GrabPtr grab;
5530 DeviceIntPtr keybd = PickKeyboard(client);
5531 int rc;
5532 GrabParameters param;
5533 GrabMask mask;
5534
5535 REQUEST_SIZE_MATCH(xGrabKeyReq);
5536
5537 param = (GrabParameters) {
5538 .grabtype = CORE,
5539 .ownerEvents = stuff->ownerEvents,
5540 .this_device_mode = stuff->keyboardMode,
5541 .other_devices_mode = stuff->pointerMode,
5542 .modifiers = stuff->modifiers
5543 };
5544
5545 rc = CheckGrabValues(client, &param);
5546 if (rc != Success)
5547 return rc;
5548
5549 if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5550 (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5551 && (stuff->key != AnyKey)) {
5552 client->errorValue = stuff->key;
5553 return BadValue;
5554 }
5555 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5556 if (rc != Success)
5557 return rc;
5558
5559 mask.core = (KeyPressMask | KeyReleaseMask);
5560
5561 grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
5562 &param, KeyPress, stuff->key, NullWindow, NullCursor);
5563 if (!grab)
5564 return BadAlloc;
5565 return AddPassiveGrabToList(client, grab);
5566}
5567
5568/**
5569 * Server-side protocol handling for GrabButton request.
5570 *
5571 * Creates a grab for the client's ClientPointer and adds it as a passive grab
5572 * to the list.
5573 */
5574int
5575ProcGrabButton(ClientPtr client)
5576{
5577 WindowPtr pWin, confineTo;
5578
5579 REQUEST(xGrabButtonReq);
5580 CursorPtr cursor;
5581 GrabPtr grab;
5582 DeviceIntPtr ptr, modifierDevice;
5583 Mask access_mode = DixGrabAccess;
5584 GrabMask mask;
5585 GrabParameters param;
5586 int rc;
5587
5588 REQUEST_SIZE_MATCH(xGrabButtonReq);
5589 if ((stuff->pointerMode != GrabModeSync) &&
5590 (stuff->pointerMode != GrabModeAsync)) {
5591 client->errorValue = stuff->pointerMode;
5592 return BadValue;
5593 }
5594 if ((stuff->keyboardMode != GrabModeSync) &&
5595 (stuff->keyboardMode != GrabModeAsync)) {
5596 client->errorValue = stuff->keyboardMode;
5597 return BadValue;
5598 }
5599 if ((stuff->modifiers != AnyModifier) &&
5600 (stuff->modifiers & ~AllModifiersMask)) {
5601 client->errorValue = stuff->modifiers;
5602 return BadValue;
5603 }
5604 if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) {
5605 client->errorValue = stuff->ownerEvents;
5606 return BadValue;
5607 }
5608 if (stuff->eventMask & ~PointerGrabMask) {
5609 client->errorValue = stuff->eventMask;
5610 return BadValue;
5611 }
5612 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5613 if (rc != Success)
5614 return rc;
5615 if (stuff->confineTo == None)
5616 confineTo = NullWindow;
5617 else {
5618 rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
5619 DixSetAttrAccess);
5620 if (rc != Success)
5621 return rc;
5622 }
5623 if (stuff->cursor == None)
5624 cursor = NullCursor;
5625 else {
5626 rc = dixLookupResourceByType((pointer *) &cursor, stuff->cursor,
5627 RT_CURSOR, client, DixUseAccess);
5628 if (rc != Success) {
5629 client->errorValue = stuff->cursor;
5630 return rc;
5631 }
5632 access_mode |= DixForceAccess;
5633 }
5634
5635 ptr = PickPointer(client);
5636 modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
5637 if (stuff->pointerMode == GrabModeSync ||
5638 stuff->keyboardMode == GrabModeSync)
5639 access_mode |= DixFreezeAccess;
5640 rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
5641 if (rc != Success)
5642 return rc;
5643
5644 param = (GrabParameters) {
5645 .grabtype = CORE,
5646 .ownerEvents = stuff->ownerEvents,
5647 .this_device_mode = stuff->keyboardMode,
5648 .other_devices_mode = stuff->pointerMode,
5649 .modifiers = stuff->modifiers
5650 };
5651
5652 mask.core = stuff->eventMask;
5653
5654 grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
5655 CORE, &mask, &param, ButtonPress,
5656 stuff->button, confineTo, cursor);
5657 if (!grab)
5658 return BadAlloc;
5659 return AddPassiveGrabToList(client, grab);
5660}
5661
5662/**
5663 * Server-side protocol handling for UngrabButton request.
5664 *
5665 * Deletes a passive grab on the client's ClientPointer from the list.
5666 */
5667int
5668ProcUngrabButton(ClientPtr client)
5669{
5670 REQUEST(xUngrabButtonReq);
5671 WindowPtr pWin;
5672 GrabPtr tempGrab;
5673 int rc;
5674 DeviceIntPtr ptr;
5675
5676 REQUEST_SIZE_MATCH(xUngrabButtonReq);
5677 if ((stuff->modifiers != AnyModifier) &&
5678 (stuff->modifiers & ~AllModifiersMask)) {
5679 client->errorValue = stuff->modifiers;
5680 return BadValue;
5681 }
5682 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
5683 if (rc != Success)
5684 return rc;
5685
5686 ptr = PickPointer(client);
5687
5688 tempGrab = AllocGrab(NULL);
5689 if (!tempGrab)
5690 return BadAlloc;
5691 tempGrab->resource = client->clientAsMask;
5692 tempGrab->device = ptr;
5693 tempGrab->window = pWin;
5694 tempGrab->modifiersDetail.exact = stuff->modifiers;
5695 tempGrab->modifiersDetail.pMask = NULL;
5696 tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
5697 tempGrab->type = ButtonPress;
5698 tempGrab->detail.exact = stuff->button;
5699 tempGrab->grabtype = CORE;
5700 tempGrab->detail.pMask = NULL;
5701 tempGrab->next = NULL;
5702
5703 if (!DeletePassiveGrabFromList(tempGrab))
5704 rc = BadAlloc;
5705
5706 FreeGrab(tempGrab);
5707 return rc;
5708}
5709
5710/**
5711 * Deactivate any grab that may be on the window, remove the focus.
5712 * Delete any XInput extension events from the window too. Does not change the
5713 * window mask. Use just before the window is deleted.
5714 *
5715 * If freeResources is set, passive grabs on the window are deleted.
5716 *
5717 * @param pWin The window to delete events from.
5718 * @param freeResources True if resources associated with the window should be
5719 * deleted.
5720 */
5721void
5722DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
5723{
5724 WindowPtr parent;
5725 DeviceIntPtr mouse = inputInfo.pointer;
5726 DeviceIntPtr keybd = inputInfo.keyboard;
5727 FocusClassPtr focus;
5728 OtherClientsPtr oc;
5729 GrabPtr passive;
5730 GrabPtr grab;
5731
5732 /* Deactivate any grabs performed on this window, before making any
5733 input focus changes. */
5734 grab = mouse->deviceGrab.grab;
5735 if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5736 (*mouse->deviceGrab.DeactivateGrab) (mouse);
5737
5738 /* Deactivating a keyboard grab should cause focus events. */
5739 grab = keybd->deviceGrab.grab;
5740 if (grab && (grab->window == pWin))
5741 (*keybd->deviceGrab.DeactivateGrab) (keybd);
5742
5743 /* And now the real devices */
5744 for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
5745 grab = mouse->deviceGrab.grab;
5746 if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5747 (*mouse->deviceGrab.DeactivateGrab) (mouse);
5748 }
5749
5750 for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
5751 if (IsKeyboardDevice(keybd)) {
5752 focus = keybd->focus;
5753
5754 /* If the focus window is a root window (ie. has no parent)
5755 then don't delete the focus from it. */
5756
5757 if ((pWin == focus->win) && (pWin->parent != NullWindow)) {
5758 int focusEventMode = NotifyNormal;
5759
5760 /* If a grab is in progress, then alter the mode of focus events. */
5761
5762 if (keybd->deviceGrab.grab)
5763 focusEventMode = NotifyWhileGrabbed;
5764
5765 switch (focus->revert) {
5766 case RevertToNone:
5767 DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
5768 focus->win = NoneWin;
5769 focus->traceGood = 0;
5770 break;
5771 case RevertToParent:
5772 parent = pWin;
5773 do {
5774 parent = parent->parent;
5775 focus->traceGood--;
5776 } while (!parent->realized
5777 /* This would be a good protocol change -- windows being
5778 reparented during SaveSet processing would cause the
5779 focus to revert to the nearest enclosing window which
5780 will survive the death of the exiting client, instead
5781 of ending up reverting to a dying window and thence
5782 to None */
5783#ifdef NOTDEF
5784 || wClient(parent)->clientGone
5785#endif
5786 );
5787 if (!ActivateFocusInGrab(keybd, pWin, parent))
5788 DoFocusEvents(keybd, pWin, parent, focusEventMode);
5789 focus->win = parent;
5790 focus->revert = RevertToNone;
5791 break;
5792 case RevertToPointerRoot:
5793 if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
5794 DoFocusEvents(keybd, pWin, PointerRootWin,
5795 focusEventMode);
5796 focus->win = PointerRootWin;
5797 focus->traceGood = 0;
5798 break;
5799 }
5800 }
5801 }
5802
5803 if (IsPointerDevice(keybd)) {
5804 if (keybd->valuator->motionHintWindow == pWin)
5805 keybd->valuator->motionHintWindow = NullWindow;
5806 }
5807 }
5808
5809 if (freeResources) {
5810 if (pWin->dontPropagate)
5811 DontPropagateRefCnts[pWin->dontPropagate]--;
5812 while ((oc = wOtherClients(pWin)))
5813 FreeResource(oc->resource, RT_NONE);
5814 while ((passive = wPassiveGrabs(pWin)))
5815 FreeResource(passive->resource, RT_NONE);
5816 }
5817
5818 DeleteWindowFromAnyExtEvents(pWin, freeResources);
5819}
5820
5821/**
5822 * Call this whenever some window at or below pWin has changed geometry. If
5823 * there is a grab on the window, the cursor will be re-confined into the
5824 * window.
5825 */
5826void
5827CheckCursorConfinement(WindowPtr pWin)
5828{
5829 GrabPtr grab;
5830 WindowPtr confineTo;
5831 DeviceIntPtr pDev;
5832
5833#ifdef PANORAMIX
5834 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
5835 return;
5836#endif
5837
5838 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
5839 if (DevHasCursor(pDev)) {
5840 grab = pDev->deviceGrab.grab;
5841 if (grab && (confineTo = grab->confineTo)) {
5842 if (!BorderSizeNotEmpty(pDev, confineTo))
5843 (*pDev->deviceGrab.DeactivateGrab) (pDev);
5844 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
5845 ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
5846 }
5847 }
5848 }
5849}
5850
5851Mask
5852EventMaskForClient(WindowPtr pWin, ClientPtr client)
5853{
5854 OtherClientsPtr other;
5855
5856 if (wClient(pWin) == client)
5857 return pWin->eventMask;
5858 for (other = wOtherClients(pWin); other; other = other->next) {
5859 if (SameClient(other, client))
5860 return other->mask;
5861 }
5862 return 0;
5863}
5864
5865/**
5866 * Server-side protocol handling for RecolorCursor request.
5867 */
5868int
5869ProcRecolorCursor(ClientPtr client)
5870{
5871 CursorPtr pCursor;
5872 int rc, nscr;
5873 ScreenPtr pscr;
5874 Bool displayed;
5875 SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
5876
5877 REQUEST(xRecolorCursorReq);
5878
5879 REQUEST_SIZE_MATCH(xRecolorCursorReq);
5880 rc = dixLookupResourceByType((pointer *) &pCursor, stuff->cursor, RT_CURSOR,
5881 client, DixWriteAccess);
5882 if (rc != Success) {
5883 client->errorValue = stuff->cursor;
5884 return rc;
5885 }
5886
5887 pCursor->foreRed = stuff->foreRed;
5888 pCursor->foreGreen = stuff->foreGreen;
5889 pCursor->foreBlue = stuff->foreBlue;
5890
5891 pCursor->backRed = stuff->backRed;
5892 pCursor->backGreen = stuff->backGreen;
5893 pCursor->backBlue = stuff->backBlue;
5894
5895 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
5896 pscr = screenInfo.screens[nscr];
5897#ifdef PANORAMIX
5898 if (!noPanoramiXExtension)
5899 displayed = (pscr == pSprite->screen);
5900 else
5901#endif
5902 displayed = (pscr == pSprite->hotPhys.pScreen);
5903 (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor,
5904 (pCursor == pSprite->current) && displayed);
5905 }
5906 return Success;
5907}
5908
5909/**
5910 * Write the given events to a client, swapping the byte order if necessary.
5911 * To swap the byte ordering, a callback is called that has to be set up for
5912 * the given event type.
5913 *
5914 * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
5915 * can be more than one. Usually it's just one event.
5916 *
5917 * Do not modify the event structure passed in. See comment below.
5918 *
5919 * @param pClient Client to send events to.
5920 * @param count Number of events.
5921 * @param events The event list.
5922 */
5923void
5924WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
5925{
5926#ifdef PANORAMIX
5927 xEvent eventCopy;
5928#endif
5929 xEvent *eventTo, *eventFrom;
5930 int i, eventlength = sizeof(xEvent);
5931
5932 if (!pClient || pClient == serverClient || pClient->clientGone)
5933 return;
5934
5935 for (i = 0; i < count; i++)
5936 if ((events[i].u.u.type & 0x7f) != KeymapNotify)
5937 events[i].u.u.sequenceNumber = pClient->sequence;
5938
5939 /* Let XKB rewrite the state, as it depends on client preferences. */
5940 XkbFilterEvents(pClient, count, events);
5941
5942#ifdef PANORAMIX
5943 if (!noPanoramiXExtension &&
5944 (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) {
5945 switch (events->u.u.type) {
5946 case MotionNotify:
5947 case ButtonPress:
5948 case ButtonRelease:
5949 case KeyPress:
5950 case KeyRelease:
5951 case EnterNotify:
5952 case LeaveNotify:
5953 /*
5954 When multiple clients want the same event DeliverEventsToWindow
5955 passes the same event structure multiple times so we can't
5956 modify the one passed to us
5957 */
5958 count = 1; /* should always be 1 */
5959 memcpy(&eventCopy, events, sizeof(xEvent));
5960 eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
5961 eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
5962 if (eventCopy.u.keyButtonPointer.event ==
5963 eventCopy.u.keyButtonPointer.root) {
5964 eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
5965 eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
5966 }
5967 events = &eventCopy;
5968 break;
5969 default:
5970 break;
5971 }
5972 }
5973#endif
5974
5975 if (EventCallback) {
5976 EventInfoRec eventinfo;
5977
5978 eventinfo.client = pClient;
5979 eventinfo.events = events;
5980 eventinfo.count = count;
5981 CallCallbacks(&EventCallback, (pointer) &eventinfo);
5982 }
5983#ifdef XSERVER_DTRACE
5984 if (XSERVER_SEND_EVENT_ENABLED()) {
5985 for (i = 0; i < count; i++) {
5986 XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
5987 }
5988 }
5989#endif
5990 /* Just a safety check to make sure we only have one GenericEvent, it just
5991 * makes things easier for me right now. (whot) */
5992 for (i = 1; i < count; i++) {
5993 if (events[i].u.u.type == GenericEvent) {
5994 ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
5995 return;
5996 }
5997 }
5998
5999 if (events->u.u.type == GenericEvent) {
6000 eventlength += ((xGenericEvent *) events)->length * 4;
6001 }
6002
6003 if (pClient->swapped) {
6004 if (eventlength > swapEventLen) {
6005 swapEventLen = eventlength;
6006 swapEvent = realloc(swapEvent, swapEventLen);
6007 if (!swapEvent) {
6008 FatalError("WriteEventsToClient: Out of memory.\n");
6009 return;
6010 }
6011 }
6012
6013 for (i = 0; i < count; i++) {
6014 eventFrom = &events[i];
6015 eventTo = swapEvent;
6016
6017 /* Remember to strip off the leading bit of type in case
6018 this event was sent with "SendEvent." */
6019 (*EventSwapVector[eventFrom->u.u.type & 0177])
6020 (eventFrom, eventTo);
6021
6022 WriteToClient(pClient, eventlength, eventTo);
6023 }
6024 }
6025 else {
6026 /* only one GenericEvent, remember? that means either count is 1 and
6027 * eventlength is arbitrary or eventlength is 32 and count doesn't
6028 * matter. And we're all set. Woohoo. */
6029 WriteToClient(pClient, count * eventlength, events);
6030 }
6031}
6032
6033/*
6034 * Set the client pointer for the given client.
6035 *
6036 * A client can have exactly one ClientPointer. Each time a
6037 * request/reply/event is processed and the choice of devices is ambiguous
6038 * (e.g. QueryPointer request), the server will pick the ClientPointer (see
6039 * PickPointer()).
6040 * If a keyboard is needed, the first keyboard paired with the CP is used.
6041 */
6042int
6043SetClientPointer(ClientPtr client, DeviceIntPtr device)
6044{
6045 int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
6046
6047 if (rc != Success)
6048 return rc;
6049
6050 if (!IsMaster(device)) {
6051 ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
6052 return BadDevice;
6053 }
6054 else if (!device->spriteInfo->spriteOwner) {
6055 ErrorF("[dix] Device %d does not have a sprite. "
6056 "Cannot be ClientPointer\n", device->id);
6057 return BadDevice;
6058 }
6059 client->clientPtr = device;
6060 return Success;
6061}
6062
6063/* PickPointer will pick an appropriate pointer for the given client.
6064 *
6065 * An "appropriate device" is (in order of priority):
6066 * 1) A device the given client has a core grab on.
6067 * 2) A device set as ClientPointer for the given client.
6068 * 3) The first master device.
6069 */
6070DeviceIntPtr
6071PickPointer(ClientPtr client)
6072{
6073 DeviceIntPtr it = inputInfo.devices;
6074
6075 /* First, check if the client currently has a grab on a device. Even
6076 * keyboards count. */
6077 for (it = inputInfo.devices; it; it = it->next) {
6078 GrabPtr grab = it->deviceGrab.grab;
6079
6080 if (grab && grab->grabtype == CORE && SameClient(grab, client)) {
6081 it = GetMaster(it, MASTER_POINTER);
6082 return it; /* Always return a core grabbed device */
6083 }
6084 }
6085
6086 if (!client->clientPtr) {
6087 it = inputInfo.devices;
6088 while (it) {
6089 if (IsMaster(it) && it->spriteInfo->spriteOwner) {
6090 client->clientPtr = it;
6091 break;
6092 }
6093 it = it->next;
6094 }
6095 }
6096 return client->clientPtr;
6097}
6098
6099/* PickKeyboard will pick an appropriate keyboard for the given client by
6100 * searching the list of devices for the keyboard device that is paired with
6101 * the client's pointer.
6102 */
6103DeviceIntPtr
6104PickKeyboard(ClientPtr client)
6105{
6106 DeviceIntPtr ptr = PickPointer(client);
6107 DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
6108
6109 if (!kbd) {
6110 ErrorF("[dix] ClientPointer not paired with a keyboard. This "
6111 "is a bug.\n");
6112 }
6113
6114 return kbd;
6115}
6116
6117/* A client that has one or more core grabs does not get core events from
6118 * devices it does not have a grab on. Legacy applications behave bad
6119 * otherwise because they are not used to it and the events interfere.
6120 * Only applies for core events.
6121 *
6122 * Return true if a core event from the device would interfere and should not
6123 * be delivered.
6124 */
6125Bool
6126IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
6127{
6128 DeviceIntPtr it = inputInfo.devices;
6129
6130 switch (event->u.u.type) {
6131 case KeyPress:
6132 case KeyRelease:
6133 case ButtonPress:
6134 case ButtonRelease:
6135 case MotionNotify:
6136 case EnterNotify:
6137 case LeaveNotify:
6138 break;
6139 default:
6140 return FALSE;
6141 }
6142
6143 if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
6144 return FALSE;
6145
6146 while (it) {
6147 if (it != dev) {
6148 if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
6149 && !it->deviceGrab.fromPassiveGrab) {
6150 if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
6151 (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
6152 return TRUE;
6153 }
6154 }
6155 it = it->next;
6156 }
6157
6158 return FALSE;
6159}
6160
6161/* PointerBarrier events are only delivered to the client that created that
6162 * barrier */
6163static Bool
6164IsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
6165{
6166 xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
6167
6168 if (ev->type != GenericEvent || ev->extension != IReqCode)
6169 return FALSE;
6170
6171 if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave)
6172 return FALSE;
6173
6174 return client->index != CLIENT_ID(ev->barrier);
6175}