1 /************************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 ********************************************************/
47 /* The panoramix components contained the following notice */
48 /*****************************************************************
50 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
52 Permission is hereby granted, free of charge, to any person obtaining a copy
53 of this software and associated documentation files (the "Software"), to deal
54 in the Software without restriction, including without limitation the rights
55 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56 copies of the Software.
58 The above copyright notice and this permission notice shall be included in
59 all copies or substantial portions of the Software.
61 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
64 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
65 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
66 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
67 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
69 Except as contained in this notice, the name of Digital Equipment Corporation
70 shall not be used in advertising or otherwise to promote the sale, use or other
71 dealings in this Software without prior written authorization from Digital
72 Equipment Corporation.
74 ******************************************************************/
77 * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
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:
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
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.
100 * This file handles event delivery and a big part of the server-side protocol
101 * handling (the parts for input devices).
104 #ifdef HAVE_DIX_CONFIG_H
105 #include <dix-config.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"
118 #include "dixstruct.h"
120 #include "panoramiX.h"
121 #include "panoramiXsrv.h"
125 #include <X11/extensions/XKBproto.h>
129 #ifdef XSERVER_DTRACE
130 #include <sys/types.h>
131 typedef const char *string
;
133 #include "Xserver-dtrace.h"
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"
144 #include "dixevents.h"
145 #include "dixgrabs.h"
146 #include "dispatch.h"
148 #include <X11/extensions/ge.h>
152 #include "eventstr.h"
153 #include "enterleave.h"
154 #include "eventconvert.h"
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 | \
169 #define PointerGrabMask ( \
170 ButtonPressMask | ButtonReleaseMask | \
171 EnterWindowMask | LeaveWindowMask | \
172 PointerMotionHintMask | KeymapStateMask | \
174 #define AllModifiersMask ( \
175 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
176 Mod3Mask | Mod4Mask | Mod5Mask )
177 #define LastEventMask OwnerGrabButtonMask
178 #define AllEventMasks (LastEventMask|(LastEventMask-1))
180 /* @return the core event type or 0 if the event is not a core event */
182 core_get_type(const xEvent
*event
)
184 int type
= event
->u
.u
.type
;
186 return ((type
& EXTENSION_EVENT_BASE
) || type
== GenericEvent
) ? 0 : type
;
189 /* @return the XI2 event type or 0 if the event is not a XI2 event */
191 xi2_get_type(const xEvent
*event
)
193 const xGenericEvent
*e
= (const xGenericEvent
*) event
;
195 return (e
->type
!= GenericEvent
||
196 e
->extension
!= IReqCode
) ? 0 : e
->evtype
;
200 * Used to indicate a implicit passive grab created by a ButtonPress event.
201 * See DeliverEventsToWindow().
203 #define ImplicitGrabMask (1 << 7)
205 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
207 #define XE_KBPTR (xE->u.keyButtonPointer)
209 CallbackListPtr EventCallback
;
210 CallbackListPtr DeviceEventCallback
;
214 Mask DontPropagateMasks
[DNPMCOUNT
];
215 static int DontPropagateRefCnts
[DNPMCOUNT
];
217 static void CheckVirtualMotion(DeviceIntPtr pDev
, QdEventPtr qe
,
219 static void CheckPhysLimits(DeviceIntPtr pDev
, CursorPtr cursor
,
220 Bool generateEvents
, Bool confineToScreen
,
222 static Bool
IsWrongPointerBarrierClient(ClientPtr client
,
226 /** Key repeat hack. Do not use but in TryClientEvents */
227 extern BOOL
EventIsKeyRepeat(xEvent
*event
);
230 * Main input device struct.
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.
237 * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
238 * See inputInfo.pointer.
241 * linked list containing all devices including VCP and VCK.
243 * inputInfo.off_devices
244 * Devices that have not been initialized and are thus turned off.
246 * inputInfo.numDevices
247 * Total number of devices.
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
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
263 EventSyncInfoRec syncEvents
;
265 static struct DeviceEventTime
{
268 } lastDeviceEventTime
[MAXDEVICES
];
271 * The root window the given device is currently on.
273 #define RootWindow(sprite) sprite->spriteTrace[0]
275 static xEvent
*swapEvent
= NULL
;
276 static int swapEventLen
= 0;
279 NotImplemented(xEvent
*from
, xEvent
*to
)
281 FatalError("Not implemented");
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.
290 XItoCoreType(int xitype
)
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
)
302 else if (xitype
== DeviceKeyRelease
)
303 coretype
= KeyRelease
;
309 * @return true if the device owns a cursor, false if device shares a cursor
310 * sprite with another device.
313 DevHasCursor(DeviceIntPtr pDev
)
315 return pDev
->spriteInfo
->spriteOwner
;
319 * @return true if a device is a pointer, check is the same as used by XI to
320 * fill the 'use' field.
323 IsPointerDevice(DeviceIntPtr dev
)
325 return (dev
->type
== MASTER_POINTER
) ||
326 (dev
->valuator
&& dev
->button
) || (dev
->valuator
&& !dev
->key
);
330 * @return true if a device is a keyboard, check is the same as used by XI to
331 * fill the 'use' field.
333 * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
334 * count them as keyboard devices.
337 IsKeyboardDevice(DeviceIntPtr dev
)
339 return (dev
->type
== MASTER_KEYBOARD
) ||
340 ((dev
->key
&& dev
->kbdfeed
) && !IsPointerDevice(dev
));
344 IsMaster(DeviceIntPtr dev
)
346 return dev
->type
== MASTER_POINTER
|| dev
->type
== MASTER_KEYBOARD
;
350 IsFloating(DeviceIntPtr dev
)
352 return !IsMaster(dev
) && GetMaster(dev
, MASTER_KEYBOARD
) == NULL
;
358 extern int lastEvent
;
360 #define CantBeFiltered NoEventMask
362 * Event masks for each event type.
364 * One set of filters for each device, initialized by memcpy of
365 * default_filter in InitEvents.
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.
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.
374 Mask event_filters
[MAXDEVICES
][MAXEVENTS
];
376 static const Mask default_filter
[MAXEVENTS
] = {
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 */
415 * For the given event, return the matching event filter. This filter may then
416 * be AND'ed with the selected event mask.
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
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.
430 GetEventFilter(DeviceIntPtr dev
, xEvent
*event
)
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
);
443 * Return the single byte of the device's XI2 mask that contains the mask
444 * for the event_type.
447 GetXI2MaskByte(XI2Mask
*mask
, DeviceIntPtr dev
, int event_type
)
449 /* we just return the matching filter because that's the only use
450 * for this mask anyway.
452 if (xi2mask_isset(mask
, dev
, event_type
))
453 return event_get_filter_from_xi2type(event_type
);
459 * @return TRUE if the mask is set for this event from this device on the
460 * window, or FALSE otherwise.
463 WindowXI2MaskIsset(DeviceIntPtr dev
, WindowPtr win
, xEvent
*ev
)
465 OtherInputMasks
*inputMasks
= wOtherInputMasks(win
);
468 if (!inputMasks
|| xi2_get_type(ev
) == 0)
471 evtype
= ((xGenericEvent
*) ev
)->evtype
;
473 return xi2mask_isset(inputMasks
->xi2mask
, dev
, evtype
);
477 GetEventMask(DeviceIntPtr dev
, xEvent
*event
, InputClients
* other
)
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
);
485 else if (core_get_type(event
) != 0)
486 return other
->mask
[XIAllDevices
];
488 return other
->mask
[dev
->id
];
491 static CARD8 criticalEvents
[32] = {
492 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */
496 SyntheticMotion(DeviceIntPtr dev
, int x
, int y
)
501 if (!noPanoramiXExtension
)
502 screenno
= dev
->spriteInfo
->sprite
->screen
->myNum
;
504 PostSyntheticMotion(dev
, x
, y
, screenno
,
505 (syncEvents
.playingEvents
) ? syncEvents
.time
.
506 milliseconds
: currentTime
.milliseconds
);
511 static void PostNewCursor(DeviceIntPtr pDev
);
514 XineramaSetCursorPosition(DeviceIntPtr pDev
, int x
, int y
, Bool generateEvent
)
518 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
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
524 pScreen
= pSprite
->screen
;
525 x
+= screenInfo
.screens
[0]->x
;
526 y
+= screenInfo
.screens
[0]->y
;
528 if (!point_on_screen(pScreen
, x
, y
)) {
530 if (i
== pScreen
->myNum
)
532 if (point_on_screen(screenInfo
.screens
[i
], x
, y
)) {
533 pScreen
= screenInfo
.screens
[i
];
539 pSprite
->screen
= pScreen
;
540 pSprite
->hotPhys
.x
= x
- screenInfo
.screens
[0]->x
;
541 pSprite
->hotPhys
.y
= y
- screenInfo
.screens
[0]->y
;
545 return (*pScreen
->SetCursorPosition
) (pDev
, pScreen
, x
, y
, generateEvent
);
549 XineramaConstrainCursor(DeviceIntPtr pDev
)
551 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
555 pScreen
= pSprite
->screen
;
556 newBox
= pSprite
->physLimits
;
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
;
565 (*pScreen
->ConstrainCursor
) (pDev
, pScreen
, &newBox
);
569 XineramaSetWindowPntrs(DeviceIntPtr pDev
, WindowPtr pWin
)
571 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
573 if (pWin
== screenInfo
.screens
[0]->root
) {
577 pSprite
->windows
[i
] = screenInfo
.screens
[i
]->root
;
583 rc
= dixLookupResourceByType((pointer
*) &win
, pWin
->drawable
.id
,
584 XRT_WINDOW
, serverClient
, DixReadAccess
);
589 rc
= dixLookupWindow(pSprite
->windows
+ i
, win
->info
[i
].id
,
590 serverClient
, DixReadAccess
);
591 if (rc
!= Success
) /* window is being unmapped */
599 XineramaConfineCursorToWindow(DeviceIntPtr pDev
,
600 WindowPtr pWin
, Bool generateEvents
)
602 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
604 int x
, y
, off_x
, off_y
, i
;
606 if (!XineramaSetWindowPntrs(pDev
, pWin
))
609 i
= PanoramiXNumScreens
- 1;
611 RegionCopy(&pSprite
->Reg1
, &pSprite
->windows
[i
]->borderSize
);
612 off_x
= screenInfo
.screens
[i
]->x
;
613 off_y
= screenInfo
.screens
[i
]->y
;
616 x
= off_x
- screenInfo
.screens
[i
]->x
;
617 y
= off_y
- screenInfo
.screens
[i
]->y
;
620 RegionTranslate(&pSprite
->Reg1
, x
, y
);
622 RegionUnion(&pSprite
->Reg1
, &pSprite
->Reg1
,
623 &pSprite
->windows
[i
]->borderSize
);
625 off_x
= screenInfo
.screens
[i
]->x
;
626 off_y
= screenInfo
.screens
[i
]->y
;
629 pSprite
->hotLimits
= *RegionExtents(&pSprite
->Reg1
);
631 if (RegionNumRects(&pSprite
->Reg1
) > 1)
632 pSprite
->hotShape
= &pSprite
->Reg1
;
634 pSprite
->hotShape
= NullRegion
;
636 pSprite
->confined
= FALSE
;
637 pSprite
->confineWin
=
638 (pWin
== screenInfo
.screens
[0]->root
) ? NullWindow
: pWin
;
640 CheckPhysLimits(pDev
, pSprite
->current
, generateEvents
, FALSE
, NULL
);
643 #endif /* PANORAMIX */
646 * Modifies the filter for the given protocol event type to the given masks.
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
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
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.
660 SetMaskForEvent(int deviceid
, Mask mask
, int event
)
662 if (deviceid
< 0 || deviceid
>= MAXDEVICES
)
663 FatalError("SetMaskForEvent: bogus device id");
664 event_filters
[deviceid
][event
] = mask
;
668 SetCriticalEvent(int event
)
670 if (event
>= MAXEVENTS
)
671 FatalError("SetCriticalEvent: bogus event number");
672 criticalEvents
[event
>> 3] |= 1 << (event
& 7);
676 ConfineToShape(DeviceIntPtr pDev
, RegionPtr shape
, int *px
, int *py
)
679 int x
= *px
, y
= *py
;
680 int incx
= 1, incy
= 1;
682 if (RegionContainsPoint(shape
, x
, y
, &box
))
684 box
= *RegionExtents(shape
);
685 /* this is rather crude */
692 else if (x
< box
.x1
) {
701 return; /* should never get here! */
703 } while (!RegionContainsPoint(shape
, x
, y
, &box
));
709 CheckPhysLimits(DeviceIntPtr pDev
, CursorPtr cursor
, Bool generateEvents
,
710 Bool confineToScreen
, /* unused if PanoramiX on */
711 ScreenPtr pScreen
) /* unused if PanoramiX on */
714 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
718 new = pSprite
->hotPhys
;
720 if (!noPanoramiXExtension
)
721 /* I don't care what the DDX has to say about it */
722 pSprite
->physLimits
= pSprite
->hotLimits
;
727 new.pScreen
= pScreen
;
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
);
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
);
749 noPanoramiXExtension
&&
751 (pScreen
!= pSprite
->hotPhys
.pScreen
)) ||
752 (new.x
!= pSprite
->hotPhys
.x
) || (new.y
!= pSprite
->hotPhys
.y
)) {
754 if (!noPanoramiXExtension
)
755 XineramaSetCursorPosition(pDev
, new.x
, new.y
, generateEvents
);
759 if (pScreen
!= pSprite
->hotPhys
.pScreen
)
760 pSprite
->hotPhys
= new;
761 (*pScreen
->SetCursorPosition
)
762 (pDev
, pScreen
, new.x
, new.y
, generateEvents
);
765 SyntheticMotion(pDev
, new.x
, new.y
);
769 /* Tell DDX what the limits are */
770 if (!noPanoramiXExtension
)
771 XineramaConstrainCursor(pDev
);
776 CheckVirtualMotion(DeviceIntPtr pDev
, QdEventPtr qe
, WindowPtr pWin
)
778 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
779 RegionPtr reg
= NULL
;
780 DeviceEvent
*ev
= NULL
;
783 ev
= &qe
->event
->device_event
;
787 case ET_ButtonRelease
:
791 case ET_ProximityOut
:
792 pSprite
->hot
.pScreen
= qe
->pScreen
;
793 pSprite
->hot
.x
= ev
->root_x
;
794 pSprite
->hot
.y
= ev
->root_y
;
796 pDev
->deviceGrab
.grab
? pDev
->deviceGrab
.grab
->
797 confineTo
: NullWindow
;
807 if (!noPanoramiXExtension
) {
808 int x
, y
, off_x
, off_y
, i
;
810 if (!XineramaSetWindowPntrs(pDev
, pWin
))
813 i
= PanoramiXNumScreens
- 1;
815 RegionCopy(&pSprite
->Reg2
, &pSprite
->windows
[i
]->borderSize
);
816 off_x
= screenInfo
.screens
[i
]->x
;
817 off_y
= screenInfo
.screens
[i
]->y
;
820 x
= off_x
- screenInfo
.screens
[i
]->x
;
821 y
= off_y
- screenInfo
.screens
[i
]->y
;
824 RegionTranslate(&pSprite
->Reg2
, x
, y
);
826 RegionUnion(&pSprite
->Reg2
, &pSprite
->Reg2
,
827 &pSprite
->windows
[i
]->borderSize
);
829 off_x
= screenInfo
.screens
[i
]->x
;
830 off_y
= screenInfo
.screens
[i
]->y
;
836 if (pSprite
->hot
.pScreen
!= pWin
->drawable
.pScreen
) {
837 pSprite
->hot
.pScreen
= pWin
->drawable
.pScreen
;
838 pSprite
->hot
.x
= pSprite
->hot
.y
= 0;
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;
853 if (!noPanoramiXExtension
) {
854 if (RegionNumRects(&pSprite
->Reg2
) > 1)
855 reg
= &pSprite
->Reg2
;
861 if (wBoundingShape(pWin
))
862 reg
= &pWin
->borderSize
;
866 ConfineToShape(pDev
, reg
, &pSprite
->hot
.x
, &pSprite
->hot
.y
);
869 qe
->pScreen
= pSprite
->hot
.pScreen
;
870 ev
->root_x
= pSprite
->hot
.x
;
871 ev
->root_y
= pSprite
->hot
.y
;
875 if (noPanoramiXExtension
) /* No typo. Only set the root win if disabled */
877 RootWindow(pDev
->spriteInfo
->sprite
) = pSprite
->hot
.pScreen
->root
;
881 ConfineCursorToWindow(DeviceIntPtr pDev
, WindowPtr pWin
, Bool generateEvents
,
882 Bool confineToScreen
)
884 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
886 if (syncEvents
.playingEvents
) {
887 CheckVirtualMotion(pDev
, (QdEventPtr
) NULL
, pWin
);
888 SyntheticMotion(pDev
, pSprite
->hot
.x
, pSprite
->hot
.y
);
892 if (!noPanoramiXExtension
) {
893 XineramaConfineCursorToWindow(pDev
, pWin
, generateEvents
);
897 pSprite
->hotLimits
= *RegionExtents(&pWin
->borderSize
);
898 pSprite
->hotShape
= wBoundingShape(pWin
) ? &pWin
->borderSize
900 CheckPhysLimits(pDev
, pSprite
->current
, generateEvents
,
901 confineToScreen
, pWin
->drawable
.pScreen
);
906 PointerConfinedToScreen(DeviceIntPtr pDev
)
908 return pDev
->spriteInfo
->sprite
->confined
;
912 * Update the sprite cursor to the given cursor.
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
919 ChangeToCursor(DeviceIntPtr pDev
, CursorPtr cursor
)
921 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
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
,
930 /* XXX: is this really necessary?? (whot) */
931 if (!noPanoramiXExtension
)
932 pScreen
= pSprite
->screen
;
935 pScreen
= pSprite
->hotPhys
.pScreen
;
937 (*pScreen
->DisplayCursor
) (pDev
, pScreen
, cursor
);
938 FreeCursor(pSprite
->current
, (Cursor
) 0);
939 pSprite
->current
= RefCursor(cursor
);
944 * @returns true if b is a descendent of a
947 IsParent(WindowPtr a
, WindowPtr b
)
949 for (b
= b
->parent
; b
; b
= b
->parent
)
956 * Update the cursor displayed on the screen.
958 * Called whenever a cursor may have changed shape or position.
961 PostNewCursor(DeviceIntPtr pDev
)
964 GrabPtr grab
= pDev
->deviceGrab
.grab
;
965 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
968 if (syncEvents
.playingEvents
)
972 ChangeToCursor(pDev
, grab
->cursor
);
975 if (IsParent(grab
->window
, pSprite
->win
))
982 for (; win
; win
= win
->parent
) {
984 pCursor
= WindowGetDeviceCursor(win
, pDev
);
985 if (!pCursor
&& win
->optional
->cursor
!= NullCursor
)
986 pCursor
= win
->optional
->cursor
;
988 ChangeToCursor(pDev
, pCursor
);
996 * @param dev device which you want to know its current root window
997 * @return root window where dev's sprite is located
1000 GetCurrentRootWindow(DeviceIntPtr dev
)
1002 return RootWindow(dev
->spriteInfo
->sprite
);
1006 * @return window underneath the cursor sprite.
1009 GetSpriteWindow(DeviceIntPtr pDev
)
1011 return pDev
->spriteInfo
->sprite
->win
;
1015 * @return current sprite cursor.
1018 GetSpriteCursor(DeviceIntPtr pDev
)
1020 return pDev
->spriteInfo
->sprite
->current
;
1024 * Set x/y current sprite position in screen coordinates.
1027 GetSpritePosition(DeviceIntPtr pDev
, int *px
, int *py
)
1029 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
1031 *px
= pSprite
->hotPhys
.x
;
1032 *py
= pSprite
->hotPhys
.y
;
1037 XineramaGetCursorScreen(DeviceIntPtr pDev
)
1039 if (!noPanoramiXExtension
) {
1040 return pDev
->spriteInfo
->sprite
->screen
->myNum
;
1046 #endif /* PANORAMIX */
1048 #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
1051 MonthChangedOrBadTime(CARD32
*ms
)
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.
1057 if ((currentTime
.milliseconds
- *ms
) > TIMESLOP
)
1058 currentTime
.months
++;
1060 *ms
= currentTime
.milliseconds
;
1064 NoticeTime(const DeviceIntPtr dev
, TimeStamp time
)
1066 lastDeviceEventTime
[XIAllDevices
].time
= currentTime
;
1067 lastDeviceEventTime
[dev
->id
].time
= currentTime
;
1069 LastEventTimeToggleResetFlag(dev
->id
, TRUE
);
1070 LastEventTimeToggleResetFlag(XIAllDevices
, TRUE
);
1074 NoticeTimeMillis(const DeviceIntPtr dev
, CARD32
*ms
)
1077 if (*ms
< currentTime
.milliseconds
)
1078 MonthChangedOrBadTime(ms
);
1079 time
.months
= currentTime
.months
;
1080 time
.milliseconds
= *ms
;
1081 NoticeTime(dev
, time
);
1085 NoticeEventTime(InternalEvent
*ev
, DeviceIntPtr dev
)
1087 if (!syncEvents
.playingEvents
)
1088 NoticeTimeMillis(dev
, &ev
->any
.time
);
1092 LastEventTime(int deviceid
)
1094 return lastDeviceEventTime
[deviceid
].time
;
1098 LastEventTimeWasReset(int deviceid
)
1100 return lastDeviceEventTime
[deviceid
].reset
;
1104 LastEventTimeToggleResetFlag(int deviceid
, Bool state
)
1106 lastDeviceEventTime
[deviceid
].reset
= state
;
1110 LastEventTimeToggleResetAll(Bool state
)
1113 nt_list_for_each_entry(dev
, inputInfo
.devices
, next
) {
1114 LastEventTimeToggleResetFlag(dev
->id
, FALSE
);
1116 LastEventTimeToggleResetFlag(XIAllDevices
, FALSE
);
1117 LastEventTimeToggleResetFlag(XIAllMasterDevices
, FALSE
);
1120 /**************************************************************************
1121 * The following procedures deal with synchronous events *
1122 **************************************************************************/
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.
1130 EnqueueEvent(InternalEvent
*ev
, DeviceIntPtr device
)
1132 QdEventPtr tail
= NULL
;
1134 SpritePtr pSprite
= device
->spriteInfo
->sprite
;
1136 DeviceEvent
*event
= &ev
->device_event
;
1138 if (!xorg_list_is_empty(&syncEvents
.pending
))
1139 tail
= xorg_list_last_entry(&syncEvents
.pending
, QdEventRec
, next
);
1141 NoticeTimeMillis(device
, &ev
->any
.time
);
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
);
1148 if (DeviceEventCallback
) {
1149 DeviceEventInfoRec eventinfo
;
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
1160 if (ev
->any
.type
== ET_Motion
)
1161 ev
->device_event
.root
= pSprite
->hotPhys
.pScreen
->root
->drawable
.id
;
1163 eventinfo
.event
= ev
;
1164 eventinfo
.device
= device
;
1165 CallCallbacks(&DeviceEventCallback
, (pointer
) &eventinfo
);
1168 if (event
->type
== ET_Motion
) {
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
;
1175 pSprite
->hotPhys
.x
= event
->root_x
;
1176 pSprite
->hotPhys
.y
= event
->root_y
;
1177 /* do motion compression, but not if from different devices */
1179 (tail
->event
->any
.type
== ET_Motion
) &&
1180 (tail
->device
== device
) &&
1181 (tail
->pScreen
== pSprite
->hotPhys
.pScreen
)) {
1182 DeviceEvent
*tailev
= &tail
->event
->device_event
;
1184 tailev
->root_x
= pSprite
->hotPhys
.x
;
1185 tailev
->root_y
= pSprite
->hotPhys
.y
;
1186 tailev
->time
= event
->time
;
1187 tail
->months
= currentTime
.months
;
1192 eventlen
= event
->length
;
1194 qe
= malloc(sizeof(QdEventRec
) + eventlen
);
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
);
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
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.
1216 PlayReleasedEvents(void)
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
);
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
;
1233 /* Translate back to the sprite screen since processInputProc
1234 will translate from sprite screen to screen 0 upon reentry
1236 if (!noPanoramiXExtension
) {
1237 DeviceEvent
*ev
= &qe
->event
->device_event
;
1241 case ET_ButtonPress
:
1242 case ET_ButtonRelease
:
1245 case ET_ProximityIn
:
1246 case ET_ProximityOut
:
1248 case ET_TouchUpdate
:
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
;
1261 (*qe
->device
->public.processInputProc
) (qe
->event
, qe
->device
);
1263 for (dev
= inputInfo
.devices
; dev
&& dev
->deviceGrab
.sync
.frozen
;
1268 /* Playing the event may have unfrozen another device. */
1269 /* So to play it safe, restart at the head of the queue */
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()).
1280 * @param dev The device to freeze/thaw
1281 * @param frozen True to freeze or false to thaw.
1284 FreezeThaw(DeviceIntPtr dev
, Bool frozen
)
1286 dev
->deviceGrab
.sync
.frozen
= frozen
;
1288 dev
->public.processInputProc
= dev
->public.enqueueInputProc
;
1290 dev
->public.processInputProc
= dev
->public.realInputProc
;
1294 * Unfreeze devices and replay all events to the respective clients.
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.
1302 ComputeFreezes(void)
1304 DeviceIntPtr replayDev
= syncEvents
.replayDev
;
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
)))
1315 syncEvents
.playingEvents
= TRUE
;
1317 DeviceEvent
*event
= replayDev
->deviceGrab
.sync
.event
;
1319 syncEvents
.replayDev
= (DeviceIntPtr
) NULL
;
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
);
1329 TouchListenerAcceptReject(replayDev
, ti
, 0, XIRejectTouch
);
1331 else if (replayDev
->focus
&&
1332 !IsPointerEvent((InternalEvent
*) event
))
1333 DeliverFocusedEvent(replayDev
, (InternalEvent
*) event
, w
);
1335 DeliverDeviceEvents(w
, (InternalEvent
*) event
, NullGrab
,
1336 NullWindow
, replayDev
);
1339 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
1340 if (!dev
->deviceGrab
.sync
.frozen
) {
1341 PlayReleasedEvents();
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,
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
);
1358 ConfineCursorToWindow(dev
,
1359 dev
->spriteInfo
->sprite
->hotPhys
.pScreen
->
1368 ScreenRestructured(ScreenPtr pScreen
)
1373 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
1374 if (!IsFloating(pDev
) && !DevHasCursor(pDev
))
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
);
1387 ConfineCursorToWindow(pDev
,
1388 pDev
->spriteInfo
->sprite
->hotPhys
.pScreen
->
1395 CheckGrabForSyncs(DeviceIntPtr thisDev
, Bool thisMode
, Bool otherMode
)
1397 GrabPtr grab
= thisDev
->deviceGrab
.grab
;
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
;
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
;
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
1430 * We store the ID of the master device only in case the master disappears
1431 * while the device has a grab.
1434 DetachFromMaster(DeviceIntPtr dev
)
1436 if (IsFloating(dev
))
1439 dev
->saved_master_id
= GetMaster(dev
, MASTER_ATTACHED
)->id
;
1441 AttachDevice(NULL
, dev
, NULL
);
1445 ReattachToOldMaster(DeviceIntPtr dev
)
1447 DeviceIntPtr master
= NULL
;
1452 dixLookupDevice(&master
, dev
->saved_master_id
, serverClient
, DixUseAccess
);
1455 AttachDevice(serverClient
, dev
, master
);
1456 dev
->saved_master_id
= 0;
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.
1465 UpdateTouchesForGrab(DeviceIntPtr mouse
)
1469 if (!mouse
->touch
|| mouse
->deviceGrab
.fromPassiveGrab
)
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
;
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
;
1484 if (grab
->grabtype
== CORE
|| grab
->grabtype
== XI
||
1485 !xi2mask_isset(grab
->xi2mask
, mouse
, XI_TouchBegin
))
1486 listener
->type
= LISTENER_POINTER_GRAB
;
1488 listener
->type
= LISTENER_GRAB
;
1490 FreeGrab(listener
->grab
);
1491 listener
->grab
= AllocGrab(grab
);
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.
1503 * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
1504 * is an implicit grab caused by a ButtonPress event.
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.
1512 ActivatePointerGrab(DeviceIntPtr mouse
, GrabPtr grab
,
1513 TimeStamp time
, Bool autoGrab
)
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
;
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
);
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
);
1533 DoEnterLeaveEvents(mouse
, mouse
->id
, oldWin
, grab
->window
, NotifyGrab
);
1534 mouse
->valuator
->motionHintWindow
= NullWindow
;
1535 if (syncEvents
.playingEvents
)
1536 grabinfo
->grabTime
= syncEvents
.time
;
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
);
1551 * Delete grab on given device, update the sprite.
1553 * Extension devices are set up for ActivateKeyboardGrab().
1556 DeactivatePointerGrab(DeviceIntPtr mouse
)
1558 GrabPtr grab
= mouse
->deviceGrab
.grab
;
1560 Bool wasPassive
= mouse
->deviceGrab
.fromPassiveGrab
;
1561 Bool wasImplicit
= (mouse
->deviceGrab
.fromPassiveGrab
&&
1562 mouse
->deviceGrab
.implicitGrab
);
1563 XID grab_resource
= grab
->resource
;
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
;
1584 TouchListenerAcceptReject(mouse
, ti
, 0, mode
);
1588 TouchRemovePointerGrab(mouse
);
1590 mouse
->valuator
->motionHintWindow
= NullWindow
;
1591 mouse
->deviceGrab
.grab
= NullGrab
;
1592 mouse
->deviceGrab
.sync
.state
= NOT_GRABBED
;
1593 mouse
->deviceGrab
.fromPassiveGrab
= FALSE
;
1595 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
1596 if (dev
->deviceGrab
.sync
.other
== grab
)
1597 dev
->deviceGrab
.sync
.other
= NullGrab
;
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
);
1605 if (!wasImplicit
&& grab
->grabtype
== XI2
)
1606 ReattachToOldMaster(mouse
);
1614 * Activate a keyboard grab on the given device.
1616 * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1619 ActivateKeyboardGrab(DeviceIntPtr keybd
, GrabPtr grab
, TimeStamp time
,
1622 GrabInfoPtr grabinfo
= &keybd
->deviceGrab
;
1623 GrabPtr oldgrab
= grabinfo
->grab
;
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
);
1631 if (!keybd
->enabled
)
1633 else if (grabinfo
->grab
)
1634 oldWin
= grabinfo
->grab
->window
;
1635 else if (keybd
->focus
)
1636 oldWin
= keybd
->focus
->win
;
1638 oldWin
= keybd
->spriteInfo
->sprite
->win
;
1639 if (oldWin
== FollowKeyboardWin
)
1640 oldWin
= keybd
->focus
->win
;
1641 if (keybd
->valuator
)
1642 keybd
->valuator
->motionHintWindow
= NullWindow
;
1644 DoFocusEvents(keybd
, oldWin
, grab
->window
, NotifyGrab
);
1645 if (syncEvents
.playingEvents
)
1646 grabinfo
->grabTime
= syncEvents
.time
;
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
);
1659 * Delete keyboard grab for the given device.
1662 DeactivateKeyboardGrab(DeviceIntPtr keybd
)
1664 GrabPtr grab
= keybd
->deviceGrab
.grab
;
1667 Bool wasImplicit
= (keybd
->deviceGrab
.fromPassiveGrab
&&
1668 keybd
->deviceGrab
.implicitGrab
);
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
;
1676 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
1677 if (dev
->deviceGrab
.sync
.other
== grab
)
1678 dev
->deviceGrab
.sync
.other
= NullGrab
;
1682 focusWin
= keybd
->focus
->win
;
1683 else if (keybd
->spriteInfo
->sprite
)
1684 focusWin
= keybd
->spriteInfo
->sprite
->win
;
1686 focusWin
= NullWindow
;
1688 if (focusWin
== FollowKeyboardWin
)
1689 focusWin
= inputInfo
.keyboard
->focus
->win
;
1691 DoFocusEvents(keybd
, grab
->window
, focusWin
, NotifyUngrab
);
1693 if (!wasImplicit
&& grab
->grabtype
== XI2
)
1694 ReattachToOldMaster(keybd
);
1702 AllowSome(ClientPtr client
, TimeStamp time
, DeviceIntPtr thisDev
, int newState
)
1704 Bool thisGrabbed
, otherGrabbed
, othersFrozen
, thisSynced
;
1707 GrabInfoPtr devgrabinfo
, grabinfo
= &thisDev
->deviceGrab
;
1709 thisGrabbed
= grabinfo
->grab
&& SameClient(grabinfo
->grab
, client
);
1711 otherGrabbed
= FALSE
;
1712 othersFrozen
= FALSE
;
1713 grabTime
= grabinfo
->grabTime
;
1714 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
1715 devgrabinfo
= &dev
->deviceGrab
;
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
)
1726 if (devgrabinfo
->sync
.state
>= FROZEN
)
1727 othersFrozen
= TRUE
;
1730 if (!((thisGrabbed
&& grabinfo
->sync
.state
>= FROZEN
) || thisSynced
))
1732 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
1733 (CompareTimeStamps(time
, grabTime
) == EARLIER
))
1736 case THAWED
: /* Async */
1738 grabinfo
->sync
.state
= THAWED
;
1740 grabinfo
->sync
.other
= NullGrab
;
1743 case FREEZE_NEXT_EVENT
: /* Sync */
1745 grabinfo
->sync
.state
= FREEZE_NEXT_EVENT
;
1747 grabinfo
->sync
.other
= NullGrab
;
1751 case THAWED_BOTH
: /* AsyncBoth */
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
;
1764 case FREEZE_BOTH_NEXT_EVENT
: /* SyncBoth */
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
;
1777 case NOT_GRABBED
: /* Replay */
1778 if (thisGrabbed
&& grabinfo
->sync
.state
== FROZEN_WITH_EVENT
) {
1780 grabinfo
->sync
.other
= NullGrab
;
1781 syncEvents
.replayDev
= thisDev
;
1782 syncEvents
.replayWin
= grabinfo
->grab
->window
;
1783 (*grabinfo
->DeactivateGrab
) (thisDev
);
1784 syncEvents
.replayDev
= (DeviceIntPtr
) NULL
;
1787 case THAW_OTHERS
: /* AsyncOthers */
1789 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
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
;
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.
1809 if (newState
!= NOT_GRABBED
/* Replay */ &&
1810 IsTouchEvent((InternalEvent
*)grabinfo
->sync
.event
)) {
1811 TouchAcceptAndEnd(thisDev
, grabinfo
->sync
.event
->touchid
);
1816 * Server-side protocol handling for AllowEvents request.
1818 * Release some events from a frozen device.
1821 ProcAllowEvents(ClientPtr client
)
1824 DeviceIntPtr mouse
= NULL
;
1825 DeviceIntPtr keybd
= NULL
;
1827 REQUEST(xAllowEventsReq
);
1829 REQUEST_SIZE_MATCH(xAllowEventsReq
);
1830 time
= ClientTimeToServerTime(stuff
->time
);
1832 mouse
= PickPointer(client
);
1833 keybd
= PickKeyboard(client
);
1835 switch (stuff
->mode
) {
1837 AllowSome(client
, time
, mouse
, NOT_GRABBED
);
1840 AllowSome(client
, time
, mouse
, FREEZE_NEXT_EVENT
);
1843 AllowSome(client
, time
, mouse
, THAWED
);
1845 case ReplayKeyboard
:
1846 AllowSome(client
, time
, keybd
, NOT_GRABBED
);
1849 AllowSome(client
, time
, keybd
, FREEZE_NEXT_EVENT
);
1852 AllowSome(client
, time
, keybd
, THAWED
);
1855 AllowSome(client
, time
, keybd
, FREEZE_BOTH_NEXT_EVENT
);
1858 AllowSome(client
, time
, keybd
, THAWED_BOTH
);
1861 client
->errorValue
= stuff
->mode
;
1868 * Deactivate grabs from any device that has been grabbed by the client.
1871 ReleaseActiveGrabs(ClientPtr client
)
1876 /* XXX CloseDownClient should remove passive grabs before
1877 * releasing active grabs.
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
);
1891 /**************************************************************************
1892 * The following procedures deal with delivering events *
1893 **************************************************************************/
1896 * Deliver the given events to the given client.
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.
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
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.
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.
1917 * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1921 TryClientEvents(ClientPtr client
, DeviceIntPtr dev
, xEvent
*pEvents
,
1922 int count
, Mask mask
, Mask filter
, GrabPtr grab
)
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)" : "");
1933 if (!client
|| client
== serverClient
|| client
->clientGone
) {
1935 ErrorF(" not delivered to fake/dead client\n");
1940 if (filter
!= CantBeFiltered
&& !(mask
& filter
)) {
1942 ErrorF(" filtered\n");
1947 if (grab
&& !SameClient(grab
, client
)) {
1949 ErrorF(" not delivered due to grab\n");
1951 return -1; /* don't send, but notify caller */
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
) {
1961 ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
1963 return 1; /* don't send, but pretend we did */
1965 pEvents
->u
.u
.detail
= NotifyHint
;
1968 pEvents
->u
.u
.detail
= NotifyNormal
;
1971 else if (type
== DeviceMotionNotify
) {
1972 if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer
*) pEvents
,
1976 else if (type
== KeyPress
) {
1977 if (EventIsKeyRepeat(pEvents
)) {
1978 if (!_XkbWantsDetectableAutoRepeat(client
)) {
1979 xEvent release
= *pEvents
;
1981 release
.u
.u
.type
= KeyRelease
;
1982 WriteEventsToClient(client
, 1, &release
);
1984 ErrorF(" (plus fake core release for repeat)");
1989 ErrorF(" (detectable autorepeat for core)");
1995 else if (type
== DeviceKeyPress
) {
1996 if (EventIsKeyRepeat(pEvents
)) {
1997 if (!_XkbWantsDetectableAutoRepeat(client
)) {
1998 deviceKeyButtonPointer release
=
1999 *(deviceKeyButtonPointer
*) pEvents
;
2000 release
.type
= DeviceKeyRelease
;
2002 ErrorF(" (plus fake xi1 release for repeat)");
2004 WriteEventsToClient(client
, 1, (xEvent
*) &release
);
2008 ErrorF(" (detectable autorepeat for core)");
2014 if (BitIsOn(criticalEvents
, type
)) {
2015 if (client
->smart_priority
< SMART_MAX_PRIORITY
)
2016 client
->smart_priority
++;
2017 SetCriticalOutputPending();
2020 WriteEventsToClient(client
, count
, pEvents
);
2022 ErrorF("[dix] delivered\n");
2028 ActivateImplicitGrab(DeviceIntPtr dev
, ClientPtr client
, WindowPtr win
,
2029 xEvent
*event
, Mask deliveryMask
)
2032 OtherInputMasks
*inputMasks
;
2033 CARD8 type
= event
->u
.u
.type
;
2034 enum InputLevel grabtype
;
2036 if (type
== ButtonPress
)
2038 else if (type
== DeviceButtonPress
)
2040 else if ((type
= xi2_get_type(event
)) == XI_ButtonPress
)
2045 tempGrab
= AllocGrab(NULL
);
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
;
2061 /* get the XI and XI2 device mask */
2062 inputMasks
= wOtherInputMasks(win
);
2063 tempGrab
->deviceMask
= (inputMasks
) ? inputMasks
->inputEvents
[dev
->id
] : 0;
2066 xi2mask_merge(tempGrab
->xi2mask
, inputMasks
->xi2mask
);
2068 (*dev
->deviceGrab
.ActivateGrab
) (dev
, tempGrab
,
2069 currentTime
, TRUE
| ImplicitGrabMask
);
2075 * Attempt event delivery to the client owning the window.
2077 static enum EventDeliveryState
2078 DeliverToWindowOwner(DeviceIntPtr dev
, WindowPtr win
,
2079 xEvent
*events
, int count
, Mask filter
, GrabPtr grab
)
2081 /* if nobody ever wants to see this event, skip some work */
2082 if (filter
!= CantBeFiltered
&&
2083 !((wOtherEventMasks(win
) | win
->eventMask
) & filter
))
2086 if (IsInterferingGrab(wClient(win
), dev
, events
))
2089 if (!XaceHook(XACE_RECEIVE_ACCESS
, wClient(win
), win
, events
, count
)) {
2090 int attempt
= TryClientEvents(wClient(win
), dev
, events
,
2091 count
, win
->eventMask
,
2095 return EVENT_DELIVERED
;
2097 return EVENT_REJECTED
;
2100 return EVENT_NOT_DELIVERED
;
2104 * Get the list of clients that should be tried for event delivery on the
2107 * @return 1 if the client list should be traversed, zero if the event
2108 * should be skipped.
2111 GetClientsForDelivery(DeviceIntPtr dev
, WindowPtr win
,
2112 xEvent
*events
, Mask filter
, InputClients
** iclients
)
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
);
2121 /* Has any client selected for the event? */
2122 if (!WindowXI2MaskIsset(dev
, win
, events
))
2124 *iclients
= inputMasks
->inputClients
;
2127 OtherInputMasks
*inputMasks
= wOtherInputMasks(win
);
2129 /* Has any client selected for the event? */
2130 if (!inputMasks
|| !(inputMasks
->inputEvents
[dev
->id
] & filter
))
2133 *iclients
= inputMasks
->inputClients
;
2142 * Try delivery on each client in inputclients, provided the event mask
2143 * accepts it and there is no interfering core grab..
2145 static enum EventDeliveryState
2146 DeliverEventToInputClients(DeviceIntPtr dev
, InputClients
* inputclients
,
2147 WindowPtr win
, xEvent
*events
,
2148 int count
, Mask filter
, GrabPtr grab
,
2149 ClientPtr
*client_return
, Mask
*mask_return
)
2152 enum EventDeliveryState rc
= EVENT_NOT_DELIVERED
;
2153 Bool have_device_button_grab_class_client
= FALSE
;
2155 for (; inputclients
; inputclients
= inputclients
->next
) {
2157 ClientPtr client
= rClient(inputclients
);
2159 if (IsInterferingGrab(client
, dev
, events
))
2162 if (IsWrongPointerBarrierClient(client
, dev
, events
))
2165 mask
= GetEventMask(dev
, events
, inputclients
);
2167 if (XaceHook(XACE_RECEIVE_ACCESS
, client
, win
, events
, count
))
2169 else if ((attempt
= TryClientEvents(client
, dev
,
2171 mask
, filter
, grab
))) {
2174 * The order of clients is arbitrary therefore if one
2175 * client belongs to DeviceButtonGrabClass make sure to
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
;
2187 } else if (rc
== EVENT_NOT_DELIVERED
)
2188 rc
= EVENT_REJECTED
;
2196 * Deliver events to clients registered on the window.
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.
2202 static enum EventDeliveryState
2203 DeliverEventToWindowMask(DeviceIntPtr dev
, WindowPtr win
, xEvent
*events
,
2204 int count
, Mask filter
, GrabPtr grab
,
2205 ClientPtr
*client_return
, Mask
*mask_return
)
2207 InputClients
*iclients
;
2209 if (!GetClientsForDelivery(dev
, win
, events
, filter
, &iclients
))
2212 return DeliverEventToInputClients(dev
, iclients
, win
, events
, count
, filter
,
2213 grab
, client_return
, mask_return
);
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
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.
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.
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.
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.
2240 DeliverEventsToWindow(DeviceIntPtr pDev
, WindowPtr pWin
, xEvent
2241 *pEvents
, int count
, Mask filter
, GrabPtr grab
)
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
;
2249 /* Deliver to window owner */
2250 if ((filter
== CantBeFiltered
) || core_get_type(pEvents
) != 0) {
2251 enum EventDeliveryState rc
;
2253 rc
= DeliverToWindowOwner(pDev
, pWin
, pEvents
, count
, filter
, grab
);
2258 case EVENT_REJECTED
:
2261 case EVENT_DELIVERED
:
2262 /* We delivered to the owner, with our event mask */
2264 client
= wClient(pWin
);
2265 deliveryMask
= pWin
->eventMask
;
2267 case EVENT_NOT_DELIVERED
:
2272 /* CantBeFiltered means only window owner gets the event */
2273 if (filter
!= CantBeFiltered
) {
2274 enum EventDeliveryState rc
;
2276 rc
= DeliverEventToWindowMask(pDev
, pWin
, pEvents
, count
, filter
,
2277 grab
, &client
, &deliveryMask
);
2282 case EVENT_REJECTED
:
2285 case EVENT_DELIVERED
:
2288 case EVENT_NOT_DELIVERED
:
2295 * Note that since core events are delivered first, an implicit grab may
2296 * be activated on a core grab, stopping the XI events.
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
);
2309 return nondeliveries
;
2313 * Filter out raw events for XI 2.0 and XI 2.1 clients.
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.
2318 * @return TRUE if the event should be discarded, FALSE otherwise.
2321 FilterRawEvents(const ClientPtr client
, const GrabPtr grab
, WindowPtr root
)
2323 XIClientPtr client_xi_version
;
2326 /* device not grabbed -> don't filter */
2331 dixLookupPrivate(&client
->devPrivates
, XIClientPrivateKey
);
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 */
2340 return (grab
->window
!= root
) ? FALSE
: SameClient(grab
, client
);
2344 * Deliver a raw event to the grab owner (if any) and to all root windows.
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
2349 * XI 2.1: events delivered to all root windows, regardless of grabbing
2353 DeliverRawEvent(RawDeviceEvent
*ev
, DeviceIntPtr device
)
2355 GrabPtr grab
= device
->deviceGrab
.grab
;
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
);
2368 DeliverGrabbedEvent((InternalEvent
*) ev
, device
, FALSE
);
2370 filter
= GetEventFilter(device
, xi
);
2372 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
2374 InputClients
*inputclients
;
2376 root
= screenInfo
.screens
[i
]->root
;
2377 if (!GetClientsForDelivery(device
, root
, xi
, filter
, &inputclients
))
2380 for (; inputclients
; inputclients
= inputclients
->next
) {
2381 ClientPtr c
; /* unused */
2382 Mask m
; /* unused */
2383 InputClients ic
= *inputclients
;
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
2393 if (!FilterRawEvents(rClient(&ic
), grab
, root
))
2394 DeliverEventToInputClients(device
, &ic
, root
, xi
, 1,
2395 filter
, NULL
, &c
, &m
);
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.
2409 XineramaTryClientEventsResult(ClientPtr client
,
2410 GrabPtr grab
, Mask mask
, Mask filter
)
2412 if ((client
) && (client
!= serverClient
) && (!client
->clientGone
) &&
2413 ((filter
== CantBeFiltered
) || (mask
& filter
))) {
2414 if (grab
&& !SameClient(grab
, client
))
2424 * Try to deliver events to the interested parties.
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.
2433 MaybeDeliverEventsToClient(WindowPtr pWin
, xEvent
*pEvents
,
2434 int count
, Mask filter
, ClientPtr dontClient
)
2436 OtherClients
*other
;
2438 if (pWin
->eventMask
& filter
) {
2439 if (wClient(pWin
) == dontClient
)
2442 if (!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
)
2443 return XineramaTryClientEventsResult(wClient(pWin
), NullGrab
,
2444 pWin
->eventMask
, filter
);
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
);
2451 for (other
= wOtherClients(pWin
); other
; other
= other
->next
) {
2452 if (other
->mask
& filter
) {
2453 if (SameClient(other
, dontClient
))
2456 if (!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
)
2457 return XineramaTryClientEventsResult(rClient(other
), NullGrab
,
2458 other
->mask
, filter
);
2460 if (XaceHook(XACE_RECEIVE_ACCESS
, rClient(other
), pWin
, pEvents
,
2462 return 1; /* don't send, but pretend we did */
2463 return TryClientEvents(rClient(other
), NULL
, pEvents
, count
,
2464 other
->mask
, filter
, NullGrab
);
2471 FindChildForEvent(SpritePtr pSprite
, WindowPtr event
)
2473 WindowPtr w
= DeepestSpriteWin(pSprite
);
2474 Window child
= None
;
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. */
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. */
2489 if (w
->parent
== event
) {
2490 child
= w
->drawable
.id
;
2499 * Adjust event fields to comply with the window properties.
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.
2507 FixUpEventFromWindow(SpritePtr pSprite
,
2508 xEvent
*xE
, WindowPtr pWin
, Window child
, Bool calcChild
)
2513 child
= FindChildForEvent(pSprite
, pWin
);
2515 if ((evtype
= xi2_get_type(xE
))) {
2516 xXIDeviceEvent
*event
= (xXIDeviceEvent
*) xE
;
2519 case XI_RawKeyPress
:
2520 case XI_RawKeyRelease
:
2521 case XI_RawButtonPress
:
2522 case XI_RawButtonRelease
:
2524 case XI_RawTouchBegin
:
2525 case XI_RawTouchUpdate
:
2526 case XI_RawTouchEnd
:
2527 case XI_DeviceChanged
:
2528 case XI_HierarchyChanged
:
2529 case XI_PropertyEvent
:
2531 case XI_BarrierLeave
:
2537 event
->root
= RootWindow(pSprite
)->drawable
.id
;
2538 event
->event
= pWin
->drawable
.id
;
2540 if (evtype
== XI_TouchOwnership
) {
2541 event
->child
= child
;
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
;
2553 event
->child
= None
;
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
);
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
;
2572 XE_KBPTR
.sameScreen
= xFalse
;
2573 XE_KBPTR
.child
= None
;
2574 XE_KBPTR
.eventX
= 0;
2575 XE_KBPTR
.eventY
= 0;
2581 * Check if a given event is deliverable at all on a given window.
2583 * This function only checks if any client wants it, not for a specific
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.
2590 * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
2591 * ::EVENT_DONT_PROPAGATE_MASK.
2594 EventIsDeliverable(DeviceIntPtr dev
, int evtype
, WindowPtr win
)
2599 OtherInputMasks
*inputMasks
= wOtherInputMasks(win
);
2601 if ((type
= GetXI2Type(evtype
)) != 0) {
2602 if (inputMasks
&& xi2mask_isset(inputMasks
->xi2mask
, dev
, type
))
2603 rc
|= EVENT_XI2_MASK
;
2606 if ((type
= GetXIType(evtype
)) != 0) {
2607 filter
= event_get_filter_from_type(dev
, type
);
2609 /* Check for XI mask */
2611 (inputMasks
->deliverableEvents
[dev
->id
] & filter
) &&
2612 (inputMasks
->inputEvents
[dev
->id
] & filter
))
2613 rc
|= EVENT_XI1_MASK
;
2615 /* Check for XI DontPropagate mask */
2616 if (inputMasks
&& (inputMasks
->dontPropagateMask
[dev
->id
] & filter
))
2617 rc
|= EVENT_DONT_PROPAGATE_MASK
;
2621 if ((type
= GetCoreType(evtype
)) != 0) {
2622 filter
= event_get_filter_from_type(dev
, type
);
2624 /* Check for core mask */
2625 if ((win
->deliverableEvents
& filter
) &&
2626 ((wOtherEventMasks(win
) | win
->eventMask
) & filter
))
2627 rc
|= EVENT_CORE_MASK
;
2629 /* Check for core DontPropagate mask */
2630 if (filter
& wDontPropagateMask(win
))
2631 rc
|= EVENT_DONT_PROPAGATE_MASK
;
2638 DeliverEvent(DeviceIntPtr dev
, xEvent
*xE
, int count
,
2639 WindowPtr win
, Window child
, GrabPtr grab
)
2641 SpritePtr pSprite
= dev
->spriteInfo
->sprite
;
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
);
2655 DeliverOneEvent(InternalEvent
*event
, DeviceIntPtr dev
, enum InputLevel level
,
2656 WindowPtr win
, Window child
, GrabPtr grab
)
2665 rc
= EventToXI2(event
, &xE
);
2669 rc
= EventToXI(event
, &xE
, &count
);
2672 rc
= EventToCore(event
, &xE
, &count
);
2676 if (rc
== Success
) {
2677 deliveries
= DeliverEvent(dev
, xE
, count
, win
, child
, grab
);
2681 BUG_WARN_MSG(rc
!= BadMatch
,
2682 "%s: conversion to level %d failed with rc %d\n",
2683 dev
->name
, level
, rc
);
2688 * Deliver events caused by input devices.
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.
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.
2703 * @see DeliverGrabbedEvent
2704 * @see DeliverFocusedEvent
2707 DeliverDeviceEvents(WindowPtr pWin
, InternalEvent
*event
, GrabPtr grab
,
2708 WindowPtr stopAt
, DeviceIntPtr dev
)
2710 Window child
= None
;
2714 verify_internal_event(event
);
2717 if ((mask
= EventIsDeliverable(dev
, event
->any
.type
, pWin
))) {
2718 /* XI2 events first */
2719 if (mask
& EVENT_XI2_MASK
) {
2721 DeliverOneEvent(event
, dev
, XI2
, pWin
, child
, grab
);
2727 if (mask
& EVENT_XI1_MASK
) {
2728 deliveries
= DeliverOneEvent(event
, dev
, XI
, pWin
, child
, grab
);
2734 if ((mask
& EVENT_CORE_MASK
) && IsMaster(dev
) && dev
->coreEvents
) {
2736 DeliverOneEvent(event
, dev
, CORE
, pWin
, child
, grab
);
2743 if ((deliveries
< 0) || (pWin
== stopAt
) ||
2744 (mask
& EVENT_DONT_PROPAGATE_MASK
)) {
2749 child
= pWin
->drawable
.id
;
2750 pWin
= pWin
->parent
;
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
2761 * In case of a ReparentNotify event, the event will be delivered to the
2762 * otherParent as well.
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.
2770 DeliverEvents(WindowPtr pWin
, xEvent
*xE
, int count
, WindowPtr otherParent
)
2776 if (!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
)
2783 dummy
.id
= XIAllDevices
;
2785 switch (xE
->u
.u
.type
) {
2790 case ReparentNotify
:
2791 case ConfigureNotify
:
2792 case ConfigureRequest
:
2794 case CirculateNotify
:
2795 case CirculateRequest
:
2796 xE
->u
.destroyNotify
.event
= pWin
->drawable
.id
;
2800 switch (xE
->u
.u
.type
) {
2804 case ReparentNotify
:
2805 case ConfigureNotify
:
2807 case CirculateNotify
:
2813 filter
= GetEventFilter(&dummy
, xE
);
2814 return DeliverEventsToWindow(&dummy
, pWin
, xE
, count
, filter
, NullGrab
);
2818 deliveries
= DeliverEventsToWindow(&dummy
, pWin
, xE
, count
,
2819 StructureNotifyMask
, NullGrab
);
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
,
2836 PointInBorderSize(WindowPtr pWin
, int x
, int y
)
2840 if (RegionContainsPoint(&pWin
->borderSize
, x
, y
, &box
))
2844 if (!noPanoramiXExtension
&&
2845 XineramaSetWindowPntrs(inputInfo
.pointer
, pWin
)) {
2846 SpritePtr pSprite
= inputInfo
.pointer
->spriteInfo
->sprite
;
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
))
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
2869 * spriteTrace[spriteTraceGood - 1] ... window at x/y
2871 * @returns the window at the given coordinates.
2874 XYToWindow(SpritePtr pSprite
, int x
, int y
)
2879 pSprite
->spriteTraceGood
= 1; /* root window still there */
2880 pWin
= RootWindow(pSprite
)->firstChild
;
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
+
2889 /* When a window is shaped, a further check
2890 * is made to see if the point is inside
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
))
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).
2903 && !pWin
->rootlessUnhittable
2906 if (pSprite
->spriteTraceGood
>= pSprite
->spriteTraceSize
) {
2907 pSprite
->spriteTraceSize
+= 10;
2908 pSprite
->spriteTrace
= realloc(pSprite
->spriteTrace
,
2909 pSprite
->spriteTraceSize
*
2912 pSprite
->spriteTrace
[pSprite
->spriteTraceGood
++] = pWin
;
2913 pWin
= pWin
->firstChild
;
2916 pWin
= pWin
->nextSib
;
2918 return DeepestSpriteWin(pSprite
);
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.
2926 * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2929 ActivateFocusInGrab(DeviceIntPtr dev
, WindowPtr old
, WindowPtr win
)
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
))
2940 DoEnterLeaveEvents(dev
, dev
->id
, old
, win
, XINotifyPassiveUngrab
);
2941 (*dev
->deviceGrab
.DeactivateGrab
) (dev
);
2944 if (win
== NoneWin
|| win
== PointerRootWin
)
2947 event
= (DeviceEvent
) {
2948 .header
= ET_Internal
,
2950 .length
= sizeof(DeviceEvent
),
2951 .time
= GetTimeInMillis(),
2952 .deviceid
= dev
->id
,
2953 .sourceid
= dev
->id
,
2956 rc
= (CheckPassiveGrabsOnWindow(win
, dev
, (InternalEvent
*) &event
, FALSE
,
2959 DoEnterLeaveEvents(dev
, dev
->id
, old
, win
, XINotifyPassiveUngrab
);
2964 * Ungrab a currently Enter grabbed device and grab the device for the given
2967 * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2970 ActivateEnterGrab(DeviceIntPtr dev
, WindowPtr old
, WindowPtr win
)
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
))
2981 DoEnterLeaveEvents(dev
, dev
->id
, old
, win
, XINotifyPassiveUngrab
);
2982 (*dev
->deviceGrab
.DeactivateGrab
) (dev
);
2985 event
= (DeviceEvent
) {
2986 .header
= ET_Internal
,
2988 .length
= sizeof(DeviceEvent
),
2989 .time
= GetTimeInMillis(),
2990 .deviceid
= dev
->id
,
2991 .sourceid
= dev
->id
,
2994 rc
= (CheckPassiveGrabsOnWindow(win
, dev
, (InternalEvent
*) &event
, FALSE
,
2997 DoEnterLeaveEvents(dev
, dev
->id
, old
, win
, XINotifyPassiveGrab
);
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.
3007 * CheckMotion() will not do anything and return FALSE if the event is not a
3010 * @return TRUE if the sprite has moved or FALSE otherwise.
3013 CheckMotion(DeviceEvent
*ev
, DeviceIntPtr pDev
)
3015 WindowPtr prevSpriteWin
, newSpriteWin
;
3016 SpritePtr pSprite
= pDev
->spriteInfo
->sprite
;
3018 verify_internal_event((InternalEvent
*) ev
);
3020 prevSpriteWin
= pSprite
->win
;
3022 if (ev
&& !syncEvents
.playingEvents
) {
3023 /* GetPointerEvents() guarantees that pointer events have the correct
3024 rootX/Y set already. */
3026 case ET_ButtonPress
:
3027 case ET_ButtonRelease
:
3030 case ET_TouchUpdate
:
3034 /* all other events return FALSE */
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
;
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
;
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
,
3069 pSprite
->hotPhys
= pSprite
->hot
;
3071 if ((pSprite
->hotPhys
.x
!= ev
->root_x
) ||
3072 (pSprite
->hotPhys
.y
!= ev
->root_y
)) {
3074 if (!noPanoramiXExtension
) {
3075 XineramaSetCursorPosition(pDev
, pSprite
->hotPhys
.x
,
3076 pSprite
->hotPhys
.y
, FALSE
);
3081 (*pSprite
->hotPhys
.pScreen
->SetCursorPosition
) (pDev
,
3092 ev
->root_x
= pSprite
->hot
.x
;
3093 ev
->root_y
= pSprite
->hot
.y
;
3096 newSpriteWin
= XYToWindow(pSprite
, pSprite
->hot
.x
, pSprite
->hot
.y
);
3098 if (newSpriteWin
!= prevSpriteWin
) {
3102 UpdateCurrentTimeIf();
3103 sourceid
= pDev
->id
; /* when from WindowsRestructured */
3106 sourceid
= ev
->sourceid
;
3108 if (prevSpriteWin
!= NullWindow
) {
3109 if (!ActivateEnterGrab(pDev
, prevSpriteWin
, newSpriteWin
))
3110 DoEnterLeaveEvents(pDev
, sourceid
, prevSpriteWin
,
3111 newSpriteWin
, NotifyNormal
);
3113 /* set pSprite->win after ActivateEnterGrab, otherwise
3114 sprite window == grab_window and no enter/leave events are
3116 pSprite
->win
= newSpriteWin
;
3117 PostNewCursor(pDev
);
3124 * Windows have restructured, we need to update the sprite position and the
3128 WindowsRestructured(void)
3130 DeviceIntPtr pDev
= inputInfo
.devices
;
3133 if (IsMaster(pDev
) || IsFloating(pDev
))
3134 CheckMotion(NULL
, pDev
);
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. */
3146 ReinitializeRootWindow(WindowPtr win
, int xoff
, int yoff
)
3152 if (noPanoramiXExtension
)
3155 pDev
= inputInfo
.devices
;
3157 if (DevHasCursor(pDev
)) {
3158 pSprite
= pDev
->spriteInfo
->sprite
;
3159 pSprite
->hot
.x
-= xoff
;
3160 pSprite
->hot
.y
-= yoff
;
3162 pSprite
->hotPhys
.x
-= xoff
;
3163 pSprite
->hotPhys
.y
-= yoff
;
3165 pSprite
->hotLimits
.x1
-= xoff
;
3166 pSprite
->hotLimits
.y1
-= yoff
;
3167 pSprite
->hotLimits
.x2
-= xoff
;
3168 pSprite
->hotLimits
.y2
-= yoff
;
3170 if (RegionNotEmpty(&pSprite
->Reg1
))
3171 RegionTranslate(&pSprite
->Reg1
, xoff
, yoff
);
3172 if (RegionNotEmpty(&pSprite
->Reg2
))
3173 RegionTranslate(&pSprite
->Reg2
, xoff
, yoff
);
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
);
3183 ConfineCursorToWindow(pDev
,
3184 pSprite
->hotPhys
.pScreen
->root
,
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
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.
3201 * It's a good idea to call it only for pointer devices, unless you have a
3202 * really talented keyboard.
3204 * @param pDev The device to initialize.
3205 * @param pWin The window where to generate the sprite in.
3209 InitializeSprite(DeviceIntPtr pDev
, WindowPtr pWin
)
3215 if (!pDev
->spriteInfo
->sprite
) {
3218 pDev
->spriteInfo
->sprite
= (SpritePtr
) calloc(1, sizeof(SpriteRec
));
3219 if (!pDev
->spriteInfo
->sprite
)
3220 FatalError("InitializeSprite: failed to allocate sprite struct");
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.
3226 * The VCK is always paired with the VCP before the VCP has a sprite.
3228 for (it
= inputInfo
.devices
; it
; it
= it
->next
) {
3229 if (it
->spriteInfo
->paired
== pDev
)
3230 it
->spriteInfo
->sprite
= pDev
->spriteInfo
->sprite
;
3232 if (inputInfo
.keyboard
->spriteInfo
->paired
== pDev
)
3233 inputInfo
.keyboard
->spriteInfo
->sprite
= pDev
->spriteInfo
->sprite
;
3236 pSprite
= pDev
->spriteInfo
->sprite
;
3237 pDev
->spriteInfo
->spriteOwner
= TRUE
;
3239 pScreen
= (pWin
) ? pWin
->drawable
.pScreen
: (ScreenPtr
) NULL
;
3240 pSprite
->hot
.pScreen
= pScreen
;
3241 pSprite
->hotPhys
.pScreen
= 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
;
3249 pSprite
->hot
= pSprite
->hotPhys
;
3250 pSprite
->win
= 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;
3259 RootWindow(pDev
->spriteInfo
->sprite
) = pWin
;
3260 pSprite
->spriteTraceGood
= 1;
3262 pSprite
->pEnqueueScreen
= pScreen
;
3263 pSprite
->pDequeueScreen
= pSprite
->pEnqueueScreen
;
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
;
3274 pCursor
= RefCursor(pCursor
);
3275 if (pSprite
->current
)
3276 FreeCursor(pSprite
->current
, None
);
3277 pSprite
->current
= RefCursor(pCursor
);
3280 (*pScreen
->RealizeCursor
) (pDev
, pScreen
, pSprite
->current
);
3281 (*pScreen
->CursorLimits
) (pDev
, pScreen
, pSprite
->current
,
3282 &pSprite
->hotLimits
, &pSprite
->physLimits
);
3283 pSprite
->confined
= FALSE
;
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
);
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
);
3307 void FreeSprite(DeviceIntPtr dev
)
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
);
3315 dev
->spriteInfo
->sprite
= NULL
;
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().
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.
3335 UpdateSpriteForScreen(DeviceIntPtr pDev
, ScreenPtr pScreen
)
3337 SpritePtr pSprite
= NULL
;
3338 WindowPtr win
= NULL
;
3344 if (!pDev
->spriteInfo
->sprite
)
3347 pSprite
= pDev
->spriteInfo
->sprite
;
3349 win
= pScreen
->root
;
3351 pSprite
->hotPhys
.pScreen
= pScreen
;
3352 pSprite
->hot
= pSprite
->hotPhys
;
3353 pSprite
->hotLimits
.x2
= pScreen
->width
;
3354 pSprite
->hotLimits
.y2
= pScreen
->height
;
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
,
3365 &pSprite
->hotLimits
, &pSprite
->physLimits
);
3366 pSprite
->confined
= FALSE
;
3367 (*pScreen
->ConstrainCursor
) (pDev
, pScreen
, &pSprite
->physLimits
);
3368 (*pScreen
->DisplayCursor
) (pDev
, pScreen
, pSprite
->current
);
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
;
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.
3390 WindowHasNewCursor(WindowPtr pWin
)
3394 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
)
3395 if (DevHasCursor(pDev
))
3396 PostNewCursor(pDev
);
3400 NewCurrentScreen(DeviceIntPtr pDev
, ScreenPtr newScreen
, int x
, int y
)
3406 IsFloating(pDev
) ? pDev
:
3407 GetXTestDevice(GetMaster(pDev
, MASTER_POINTER
));
3408 pSprite
= ptr
->spriteInfo
->sprite
;
3410 pSprite
->hotPhys
.x
= x
;
3411 pSprite
->hotPhys
.y
= y
;
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
);
3422 XineramaConfineCursorToWindow(ptr
, screenInfo
.screens
[0]->root
,
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
,
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
,
3440 if (newScreen
!= pSprite
->hotPhys
.pScreen
)
3441 ConfineCursorToWindow(ptr
, newScreen
->root
, TRUE
, FALSE
);
3447 XineramaPointInWindowIsVisible(WindowPtr pWin
, int x
, int y
)
3452 if (!pWin
->realized
)
3455 if (RegionContainsPoint(&pWin
->borderClip
, x
, y
, &box
))
3458 if (!XineramaSetWindowPntrs(inputInfo
.pointer
, pWin
))
3461 xoff
= x
+ screenInfo
.screens
[0]->x
;
3462 yoff
= y
+ screenInfo
.screens
[0]->y
;
3464 FOR_NSCREENS_FORWARD_SKIP(i
) {
3465 pWin
= inputInfo
.pointer
->spriteInfo
->sprite
->windows
[i
];
3467 x
= xoff
- screenInfo
.screens
[i
]->x
;
3468 y
= yoff
- screenInfo
.screens
[i
]->y
;
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
)))
3483 XineramaWarpPointer(ClientPtr client
)
3485 WindowPtr dest
= NULL
;
3487 SpritePtr pSprite
= PickPointer(client
)->spriteInfo
->sprite
;
3489 REQUEST(xWarpPointerReq
);
3491 if (stuff
->dstWid
!= None
) {
3492 rc
= dixLookupWindow(&dest
, stuff
->dstWid
, client
, DixReadAccess
);
3496 x
= pSprite
->hotPhys
.x
;
3497 y
= pSprite
->hotPhys
.y
;
3499 if (stuff
->srcWid
!= None
) {
3501 XID winID
= stuff
->srcWid
;
3504 rc
= dixLookupWindow(&source
, winID
, client
, DixReadAccess
);
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
;
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
))
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
;
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
);
3546 XineramaSetCursorPosition(PickPointer(client
), x
, y
, TRUE
);
3554 * Server-side protocol handling for WarpPointer request.
3555 * Warps the cursor position to the coordinates given in the request.
3558 ProcWarpPointer(ClientPtr client
)
3560 WindowPtr dest
= NULL
;
3562 ScreenPtr newScreen
;
3563 DeviceIntPtr dev
, tmp
;
3566 REQUEST(xWarpPointerReq
);
3567 REQUEST_SIZE_MATCH(xWarpPointerReq
);
3569 dev
= PickPointer(client
);
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
);
3580 dev
= dev
->lastSlave
;
3581 pSprite
= dev
->spriteInfo
->sprite
;
3584 if (!noPanoramiXExtension
)
3585 return XineramaWarpPointer(client
);
3588 if (stuff
->dstWid
!= None
) {
3589 rc
= dixLookupWindow(&dest
, stuff
->dstWid
, client
, DixGetAttrAccess
);
3593 x
= pSprite
->hotPhys
.x
;
3594 y
= pSprite
->hotPhys
.y
;
3596 if (stuff
->srcWid
!= None
) {
3598 XID winID
= stuff
->srcWid
;
3601 rc
= dixLookupWindow(&source
, winID
, client
, DixGetAttrAccess
);
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
))
3618 x
= dest
->drawable
.x
;
3619 y
= dest
->drawable
.y
;
3620 newScreen
= dest
->drawable
.pScreen
;
3623 newScreen
= pSprite
->hotPhys
.pScreen
;
3630 else if (x
>= newScreen
->width
)
3631 x
= newScreen
->width
- 1;
3634 else if (y
>= newScreen
->height
)
3635 y
= newScreen
->height
- 1;
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
);
3650 else if (!PointerConfinedToScreen(dev
)) {
3651 NewCurrentScreen(dev
, newScreen
, x
, y
);
3657 BorderSizeNotEmpty(DeviceIntPtr pDev
, WindowPtr pWin
)
3659 if (RegionNotEmpty(&pWin
->borderSize
))
3663 if (!noPanoramiXExtension
&& XineramaSetWindowPntrs(pDev
, pWin
)) {
3666 FOR_NSCREENS_FORWARD_SKIP(i
) {
3668 (&pDev
->spriteInfo
->sprite
->windows
[i
]->borderSize
))
3677 * Activate the given passive grab. If the grab is activated successfully, the
3678 * event has been delivered to the client.
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.
3686 * @return Whether the grab has been activated.
3689 ActivatePassiveGrab(DeviceIntPtr device
, GrabPtr grab
, InternalEvent
*event
,
3690 InternalEvent
*real_event
)
3692 SpritePtr pSprite
= device
->spriteInfo
->sprite
;
3693 GrabInfoPtr grabinfo
= &device
->deviceGrab
;
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
) {
3703 event
->device_event
.corestate
&= 0x1f00;
3705 if (grab
->grabtype
== CORE
)
3706 gdev
= GetMaster(device
, KEYBOARD_OR_FLOAT
);
3708 gdev
= grab
->modifierDevice
;
3710 if (gdev
&& gdev
->key
&& gdev
->key
->xkbInfo
)
3711 event
->device_event
.corestate
|=
3712 gdev
->key
->xkbInfo
->state
.grab_mods
& (~0x1f00);
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
);
3723 else if (grab
->grabtype
== XI2
) {
3724 rc
= EventToXI2(event
, &xE
);
3725 if (rc
!= Success
) {
3727 BUG_WARN_MSG(rc
!= BadMatch
, "[dix] %s: XI2 conversion failed"
3728 "(%d, %d).\n", device
->name
, event
->any
.type
, rc
);
3734 rc
= EventToXI(event
, &xE
, &count
);
3735 if (rc
!= Success
) {
3737 BUG_WARN_MSG(rc
!= BadMatch
, "[dix] %s: XI conversion failed"
3738 "(%d, %d).\n", device
->name
, event
->any
.type
, rc
);
3743 (*grabinfo
->ActivateGrab
) (device
, grab
,
3744 ClientTimeToServerTime(event
->any
.time
), TRUE
);
3747 FixUpEventFromWindow(pSprite
, xE
, grab
->window
, None
, TRUE
);
3750 TryClientEvents(rClient(grab
), device
, xE
, count
,
3751 GetEventFilter(device
, xE
),
3752 GetEventFilter(device
, xE
), grab
);
3755 if (grabinfo
->sync
.state
== FROZEN_NO_EVENT
)
3756 grabinfo
->sync
.state
= FROZEN_WITH_EVENT
;
3757 *grabinfo
->sync
.event
= real_event
->device_event
;
3764 CoreGrabInterferes(DeviceIntPtr device
, GrabPtr grab
)
3767 BOOL interfering
= FALSE
;
3769 for (other
= inputInfo
.devices
; other
; other
= other
->next
) {
3770 GrabPtr othergrab
= other
->deviceGrab
.grab
;
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
)))) {
3794 * Match the grab against the temporary grab on the given input level.
3795 * Modifies the temporary grab pointer.
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
3802 * @return The respective matched flag or 0 for no match
3804 static enum MatchFlags
3805 MatchForType(const GrabPtr grab
, GrabPtr tmp
, enum InputLevel level
,
3808 enum MatchFlags match
;
3809 BOOL ignore_device
= FALSE
;
3816 evtype
= GetXI2Type(event_type
);
3822 evtype
= GetXIType(event_type
);
3827 evtype
= GetCoreType(event_type
);
3829 ignore_device
= TRUE
;
3833 tmp
->grabtype
= grabtype
;
3836 if (tmp
->type
&& GrabMatchesSecond(tmp
, grab
, ignore_device
))
3843 * Check an individual grab against an event to determine if a passive grab
3844 * should be activated.
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.
3853 * @return Whether the grab matches the event.
3856 CheckPassiveGrab(DeviceIntPtr device
, GrabPtr grab
, InternalEvent
*event
,
3857 Bool checkCore
, GrabPtr tempGrab
)
3860 XkbSrvInfoPtr xkbi
= NULL
;
3861 enum MatchFlags match
= 0;
3862 int emulated_type
= 0;
3864 gdev
= grab
->modifierDevice
;
3865 if (grab
->grabtype
== CORE
) {
3866 gdev
= GetMaster(device
, KEYBOARD_OR_FLOAT
);
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
3873 if (!IsMaster(grab
->device
) && !IsFloating(device
))
3874 gdev
= GetMaster(device
, MASTER_KEYBOARD
);
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;
3882 /* Check for XI2 and XI grabs first */
3883 match
= MatchForType(grab
, tempGrab
, XI2
, event
->any
.type
);
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
);
3892 match
= MatchForType(grab
, tempGrab
, XI
, event
->any
.type
);
3894 if (!match
&& emulated_type
)
3895 match
= MatchForType(grab
, tempGrab
, XI
, emulated_type
);
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
);
3903 if (!match
|| (grab
->confineTo
&&
3904 (!grab
->confineTo
->realized
||
3905 !BorderSizeNotEmpty(device
, grab
->confineTo
))))
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
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
3919 Since XGrabDeviceButton requires to specify the
3920 modifierDevice explicitly, we don't override this choice.
3922 if (grab
->type
< GenericEvent
) {
3923 grab
->device
= device
;
3924 grab
->modifierDevice
= GetMaster(device
, MASTER_KEYBOARD
);
3927 if (CoreGrabInterferes(device
, grab
))
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.
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.
3948 CheckPassiveGrabsOnWindow(WindowPtr pWin
,
3949 DeviceIntPtr device
,
3950 InternalEvent
*event
, BOOL checkCore
, BOOL activate
)
3952 GrabPtr grab
= wPassiveGrabs(pWin
);
3958 tempGrab
= AllocGrab(NULL
);
3960 /* Fill out the grab details, but leave the type for later before
3962 switch (event
->any
.type
) {
3965 tempGrab
->detail
.exact
= event
->device_event
.detail
.key
;
3967 case ET_ButtonPress
:
3968 case ET_ButtonRelease
:
3971 tempGrab
->detail
.exact
= event
->device_event
.detail
.button
;
3974 tempGrab
->detail
.exact
= 0;
3977 tempGrab
->window
= pWin
;
3978 tempGrab
->device
= device
;
3979 tempGrab
->detail
.pMask
= NULL
;
3980 tempGrab
->modifiersDetail
.pMask
= NULL
;
3981 tempGrab
->next
= NULL
;
3983 for (; grab
; grab
= grab
->next
) {
3984 if (!CheckPassiveGrab(device
, grab
, event
, checkCore
, tempGrab
))
3987 if (activate
&& !ActivatePassiveGrab(device
, grab
, event
, event
))
3998 * CheckDeviceGrabs handles both keyboard and pointer events that may cause
3999 * a passive grab to be activated.
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
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
4012 * If a grab is activated, the event has been sent to the client already!
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.
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.
4024 CheckDeviceGrabs(DeviceIntPtr device
, DeviceEvent
*event
, WindowPtr ancestor
)
4027 WindowPtr pWin
= NULL
;
4028 FocusClassPtr focus
=
4029 IsPointerEvent((InternalEvent
*) event
) ? NULL
: device
->focus
;
4030 BOOL sendCore
= (IsMaster(device
) && device
->coreEvents
);
4033 if (event
->type
!= ET_ButtonPress
&& event
->type
!= ET_KeyPress
)
4036 if (event
->type
== ET_ButtonPress
&& (device
->button
->buttonsDown
!= 1))
4039 if (device
->deviceGrab
.grab
)
4044 while (i
< device
->spriteInfo
->sprite
->spriteTraceGood
)
4045 if (device
->spriteInfo
->sprite
->spriteTrace
[i
++] == ancestor
)
4047 if (i
== device
->spriteInfo
->sprite
->spriteTraceGood
)
4052 for (; i
< focus
->traceGood
; i
++) {
4053 pWin
= focus
->trace
[i
];
4054 if (CheckPassiveGrabsOnWindow(pWin
, device
, (InternalEvent
*) event
,
4061 if ((focus
->win
== NoneWin
) ||
4062 (i
>= device
->spriteInfo
->sprite
->spriteTraceGood
) ||
4063 (pWin
&& pWin
!= device
->spriteInfo
->sprite
->spriteTrace
[i
- 1]))
4067 for (; i
< device
->spriteInfo
->sprite
->spriteTraceGood
; i
++) {
4068 pWin
= device
->spriteInfo
->sprite
->spriteTrace
[i
];
4069 if (CheckPassiveGrabsOnWindow(pWin
, device
, (InternalEvent
*) event
,
4077 if (ret
== TRUE
&& event
->type
== ET_KeyPress
)
4078 device
->deviceGrab
.activatingKey
= event
->detail
.key
;
4083 * Called for keyboard events to deliver event to whatever client owns the
4086 * The event is delivered to the keyboard's focus window, the root window or
4087 * to the window owning the input focus.
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.
4094 DeliverFocusedEvent(DeviceIntPtr keybd
, InternalEvent
*event
, WindowPtr window
)
4097 WindowPtr focus
= keybd
->focus
->win
;
4098 BOOL sendCore
= (IsMaster(keybd
) && keybd
->coreEvents
);
4099 xEvent
*core
= NULL
, *xE
= NULL
, *xi2
= NULL
;
4103 if (focus
== FollowKeyboardWin
)
4104 focus
= inputInfo
.keyboard
->focus
->win
;
4107 if (focus
== PointerRootWin
) {
4108 DeliverDeviceEvents(window
, event
, NullGrab
, NullWindow
, keybd
);
4111 if ((focus
== window
) || IsParent(focus
, window
)) {
4112 if (DeliverDeviceEvents(window
, event
, NullGrab
, focus
, keybd
))
4116 /* just deliver it to the focus window */
4117 ptr
= GetMaster(keybd
, POINTER_OR_FLOAT
);
4119 rc
= EventToXI2(event
, &xi2
);
4120 if (rc
== Success
) {
4122 int filter
= GetEventFilter(keybd
, xi2
);
4124 FixUpEventFromWindow(ptr
->spriteInfo
->sprite
, xi2
, focus
, None
, FALSE
);
4125 deliveries
= DeliverEventsToWindow(keybd
, focus
, xi2
, 1,
4130 else if (rc
!= BadMatch
)
4132 ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
4133 keybd
->name
, event
->any
.type
, rc
);
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
);
4145 else if (rc
!= BadMatch
)
4147 ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
4148 keybd
->name
, event
->any
.type
, rc
);
4151 rc
= EventToCore(event
, &core
, &count
);
4152 if (rc
== Success
) {
4153 if (XaceHook(XACE_SEND_ACCESS
, NULL
, keybd
, focus
, core
, count
) ==
4155 FixUpEventFromWindow(keybd
->spriteInfo
->sprite
, core
, focus
,
4158 DeliverEventsToWindow(keybd
, focus
, core
, count
,
4159 GetEventFilter(keybd
, core
),
4163 else if (rc
!= BadMatch
)
4165 ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
4166 keybd
->name
, event
->any
.type
, rc
);
4177 DeliverOneGrabbedEvent(InternalEvent
*event
, DeviceIntPtr dev
,
4178 enum InputLevel level
)
4180 SpritePtr pSprite
= dev
->spriteInfo
->sprite
;
4186 GrabInfoPtr grabinfo
= &dev
->deviceGrab
;
4187 GrabPtr grab
= grabinfo
->grab
;
4190 if (grab
->grabtype
!= level
)
4195 rc
= EventToXI2(event
, &xE
);
4197 if (rc
== Success
) {
4198 int evtype
= xi2_get_type(xE
);
4200 mask
= GetXI2MaskByte(grab
->xi2mask
, dev
, evtype
);
4201 filter
= GetEventFilter(dev
, xE
);
4205 if (grabinfo
->fromPassiveGrab
&& grabinfo
->implicitGrab
)
4206 mask
= grab
->deviceMask
;
4208 mask
= grab
->eventMask
;
4209 rc
= EventToXI(event
, &xE
, &count
);
4211 filter
= GetEventFilter(dev
, xE
);
4214 rc
= EventToCore(event
, &xE
, &count
);
4215 mask
= grab
->eventMask
;
4217 filter
= GetEventFilter(dev
, xE
);
4220 BUG_WARN_MSG(1, "Invalid input level %d\n", level
);
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
);
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
);
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.
4250 * @param deactivateGrab True if the device's grab should be deactivated.
4252 * @return The number of events delivered.
4255 DeliverGrabbedEvent(InternalEvent
*event
, DeviceIntPtr thisDev
,
4256 Bool deactivateGrab
)
4259 GrabInfoPtr grabinfo
;
4262 SpritePtr pSprite
= thisDev
->spriteInfo
->sprite
;
4263 BOOL sendCore
= FALSE
;
4265 grabinfo
= &thisDev
->deviceGrab
;
4266 grab
= grabinfo
->grab
;
4268 if (grab
->ownerEvents
) {
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.
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
;
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
,
4292 deliveries
= DeliverDeviceEvents(focus
, event
, grab
, focus
,
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.
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
);
4307 if (deliveries
&& (event
->any
.type
== ET_Motion
))
4308 thisDev
->valuator
->motionHintWindow
= grab
->window
;
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
);
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
;
4325 dev
->deviceGrab
.sync
.other
= grab
;
4328 case FREEZE_NEXT_EVENT
:
4329 grabinfo
->sync
.state
= FROZEN_WITH_EVENT
;
4330 FreezeThaw(thisDev
, TRUE
);
4331 *grabinfo
->sync
.event
= event
->device_event
;
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.
4344 FixKeyState(DeviceEvent
*event
, DeviceIntPtr keybd
)
4346 int key
= event
->detail
.key
;
4348 if (event
->type
== ET_KeyPress
) {
4349 DebugF("FixKeyState: Key %d %s\n", key
,
4350 ((event
->type
== ET_KeyPress
) ? "down" : "up"));
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
);
4358 FatalError("Impossible keyboard event");
4361 #define AtMostOneClient \
4362 (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
4363 #define ManagerMask \
4364 (SubstructureRedirectMask | ResizeRedirectMask)
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.
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.
4376 * Traverses to siblings and parents of the window.
4379 RecalculateDeliverableEvents(WindowPtr pWin
)
4381 OtherClients
*others
;
4386 if (pChild
->optional
) {
4387 pChild
->optional
->otherEventMasks
= 0;
4388 for (others
= wOtherClients(pChild
); others
; others
= others
->next
) {
4389 pChild
->optional
->otherEventMasks
|= others
->mask
;
4392 pChild
->deliverableEvents
= pChild
->eventMask
|
4393 wOtherEventMasks(pChild
);
4395 pChild
->deliverableEvents
|=
4396 (pChild
->parent
->deliverableEvents
&
4397 ~wDontPropagateMask(pChild
) & PropagateMask
);
4398 if (pChild
->firstChild
) {
4399 pChild
= pChild
->firstChild
;
4402 while (!pChild
->nextSib
&& (pChild
!= pWin
))
4403 pChild
= pChild
->parent
;
4406 pChild
= pChild
->nextSib
;
4412 * \param value must conform to DeleteType
4415 OtherClientGone(pointer value
, XID id
)
4417 OtherClientsPtr other
, prev
;
4418 WindowPtr pWin
= (WindowPtr
) value
;
4421 for (other
= wOtherClients(pWin
); other
; other
= other
->next
) {
4422 if (other
->resource
== id
) {
4424 prev
->next
= other
->next
;
4426 if (!(pWin
->optional
->otherClients
= other
->next
))
4427 CheckWindowOptionalNeed(pWin
);
4430 RecalculateDeliverableEvents(pWin
);
4435 FatalError("client not on event list");
4439 EventSelectForWindow(WindowPtr pWin
, ClientPtr client
, Mask mask
)
4442 OtherClients
*others
;
4446 if (mask
& ~AllEventMasks
) {
4447 client
->errorValue
= mask
;
4450 check
= (mask
& ManagerMask
);
4452 rc
= XaceHook(XACE_RESOURCE_ACCESS
, client
, pWin
->drawable
.id
,
4453 RT_WINDOW
, pWin
, RT_NONE
, NULL
, DixManageAccess
);
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
))
4464 for (others
= wOtherClients(pWin
); others
; others
= others
->next
) {
4465 if (!SameClient(others
, client
) && (check
& others
->mask
))
4469 if (wClient(pWin
) == client
) {
4470 check
= pWin
->eventMask
;
4471 pWin
->eventMask
= mask
;
4474 for (others
= wOtherClients(pWin
); others
; others
= others
->next
) {
4475 if (SameClient(others
, client
)) {
4476 check
= others
->mask
;
4478 FreeResource(others
->resource
, RT_NONE
);
4482 others
->mask
= mask
;
4487 if (!pWin
->optional
&& !MakeWindowOptional(pWin
))
4489 others
= malloc(sizeof(OtherClients
));
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
))
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
;
4506 RecalculateDeliverableEvents(pWin
);
4511 EventSuppressForWindow(WindowPtr pWin
, ClientPtr client
,
4512 Mask mask
, Bool
*checkOptional
)
4516 if (mask
& ~PropagateMask
) {
4517 client
->errorValue
= mask
;
4520 if (pWin
->dontPropagate
)
4521 DontPropagateRefCnts
[pWin
->dontPropagate
]--;
4525 for (i
= DNPMCOUNT
, freed
= 0; --i
> 0;) {
4526 if (!DontPropagateRefCnts
[i
])
4528 else if (mask
== DontPropagateMasks
[i
])
4533 DontPropagateMasks
[i
] = mask
;
4537 pWin
->dontPropagate
= i
;
4539 DontPropagateRefCnts
[i
]++;
4540 if (pWin
->optional
) {
4541 pWin
->optional
->dontPropagateMask
= mask
;
4542 *checkOptional
= TRUE
;
4546 if (!pWin
->optional
&& !MakeWindowOptional(pWin
)) {
4547 if (pWin
->dontPropagate
)
4548 DontPropagateRefCnts
[pWin
->dontPropagate
]++;
4551 pWin
->dontPropagate
= 0;
4552 pWin
->optional
->dontPropagateMask
= mask
;
4554 RecalculateDeliverableEvents(pWin
);
4559 * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
4560 * Uses the paired keyboard to get some additional information.
4563 CoreEnterLeaveEvent(DeviceIntPtr mouse
,
4565 int mode
, int detail
, WindowPtr pWin
, Window child
)
4569 .u
.u
.detail
= detail
4573 GrabPtr grab
= mouse
->deviceGrab
.grab
;
4576 keybd
= GetMaster(mouse
, KEYBOARD_OR_FLOAT
);
4578 if ((pWin
== mouse
->valuator
->motionHintWindow
) &&
4579 (detail
!= NotifyInferior
))
4580 mouse
->valuator
->motionHintWindow
= NullWindow
;
4582 mask
= (pWin
== grab
->window
) ? grab
->eventMask
: 0;
4583 if (grab
->ownerEvents
)
4584 mask
|= EventMaskForClient(pWin
, rClient(grab
));
4587 mask
= pWin
->eventMask
| wOtherEventMasks(pWin
);
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;
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
;
4610 if ((mask
& GetEventFilter(mouse
, &event
))) {
4612 TryClientEvents(rClient(grab
), mouse
, &event
, 1, mask
,
4613 GetEventFilter(mouse
, &event
), grab
);
4615 DeliverEventsToWindow(mouse
, pWin
, &event
, 1,
4616 GetEventFilter(mouse
, &event
), NullGrab
);
4619 if ((type
== EnterNotify
) && (mask
& KeymapStateMask
)) {
4621 .type
= KeymapNotify
4623 ClientPtr client
= grab
? rClient(grab
) : wClient(pWin
);
4626 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, keybd
, DixReadAccess
);
4628 memcpy((char *) &ke
.map
[0], (char *) &keybd
->key
->down
[1], 31);
4631 TryClientEvents(rClient(grab
), keybd
, (xEvent
*) &ke
, 1,
4632 mask
, KeymapStateMask
, grab
);
4634 DeliverEventsToWindow(mouse
, pWin
, (xEvent
*) &ke
, 1,
4635 KeymapStateMask
, NullGrab
);
4640 DeviceEnterLeaveEvent(DeviceIntPtr mouse
,
4643 int mode
, int detail
, WindowPtr pWin
, Window child
)
4645 GrabPtr grab
= mouse
->deviceGrab
.grab
;
4646 xXIEnterEvent
*event
;
4652 if ((mode
== XINotifyPassiveGrab
&& type
== XI_Leave
) ||
4653 (mode
== XINotifyPassiveUngrab
&& type
== XI_Enter
))
4656 btlen
= (mouse
->button
) ? bits_to_bytes(mouse
->button
->numButtons
) : 0;
4657 btlen
= bytes_to_int32(btlen
);
4658 len
= sizeof(xXIEnterEvent
) + btlen
* 4;
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
;
4671 event
->root_x
= double_to_fp1616(mouse
->spriteInfo
->sprite
->hot
.x
);
4672 event
->root_y
= double_to_fp1616(mouse
->spriteInfo
->sprite
->hot
.y
);
4674 for (i
= 0; mouse
&& mouse
->button
&& i
< mouse
->button
->numButtons
; i
++)
4675 if (BitIsOn(mouse
->button
->down
, i
))
4676 SetBit(&event
[1], i
);
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
;
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
;
4689 focus
= (kbd
) ? kbd
->focus
->win
: None
;
4690 if ((focus
!= NoneWin
) &&
4691 ((pWin
== focus
) || (focus
== PointerRootWin
) || IsParent(focus
, pWin
)))
4692 event
->focus
= TRUE
;
4694 FixUpEventFromWindow(mouse
->spriteInfo
->sprite
, (xEvent
*) event
, pWin
,
4697 filter
= GetEventFilter(mouse
, (xEvent
*) event
);
4699 if (grab
&& grab
->grabtype
== XI2
) {
4702 mask
= xi2mask_isset(grab
->xi2mask
, mouse
, type
);
4703 TryClientEvents(rClient(grab
), mouse
, (xEvent
*) event
, 1, mask
, 1,
4707 if (!WindowXI2MaskIsset(mouse
, pWin
, (xEvent
*) event
))
4709 DeliverEventsToWindow(mouse
, pWin
, (xEvent
*) event
, 1, filter
,
4718 CoreFocusEvent(DeviceIntPtr dev
, int type
, int mode
, int detail
, WindowPtr pWin
)
4722 .u
.u
.detail
= detail
4724 event
.u
.focus
.mode
= mode
;
4725 event
.u
.focus
.window
= pWin
->drawable
.id
;
4727 DeliverEventsToWindow(dev
, pWin
, &event
, 1,
4728 GetEventFilter(dev
, &event
), NullGrab
);
4729 if ((type
== FocusIn
) &&
4730 ((pWin
->eventMask
| wOtherEventMasks(pWin
)) & KeymapStateMask
)) {
4732 .type
= KeymapNotify
4734 ClientPtr client
= wClient(pWin
);
4737 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, DixReadAccess
);
4739 memcpy((char *) &ke
.map
[0], (char *) &dev
->key
->down
[1], 31);
4741 DeliverEventsToWindow(dev
, pWin
, (xEvent
*) &ke
, 1,
4742 KeymapStateMask
, NullGrab
);
4747 * Set the input focus to the given window. Subsequent keyboard events will be
4748 * delivered to the given window.
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.
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
4760 * @param ctime Specifies the time.
4761 * @param followOK True if pointer is allowed to follow the keyboard.
4764 SetInputFocus(ClientPtr client
,
4766 Window focusID
, CARD8 revertTo
, Time ctime
, Bool followOK
)
4768 FocusClassPtr focus
;
4772 DeviceIntPtr keybd
; /* used for FollowKeyboard or FollowKeyboardWin */
4774 UpdateCurrentTime();
4775 if ((revertTo
!= RevertToParent
) &&
4776 (revertTo
!= RevertToPointerRoot
) &&
4777 (revertTo
!= RevertToNone
) &&
4778 ((revertTo
!= RevertToFollowKeyboard
) || !followOK
)) {
4779 client
->errorValue
= revertTo
;
4782 time
= ClientTimeToServerTime(ctime
);
4784 keybd
= GetMaster(dev
, KEYBOARD_OR_FLOAT
);
4786 if ((focusID
== None
) || (focusID
== PointerRoot
))
4787 focusWin
= (WindowPtr
) (long) focusID
;
4788 else if ((focusID
== FollowKeyboard
) && followOK
) {
4789 focusWin
= keybd
->focus
->win
;
4792 rc
= dixLookupWindow(&focusWin
, focusID
, client
, DixSetAttrAccess
);
4795 /* It is a match error to try to set the input focus to an
4796 unviewable window. */
4797 if (!focusWin
->realized
)
4800 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, DixSetFocusAccess
);
4805 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
4806 (CompareTimeStamps(time
, focus
->time
) == EARLIER
))
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
);
4814 if (!ActivateFocusInGrab(dev
, focus
->win
, focusWin
))
4815 DoFocusEvents(dev
, focus
->win
, focusWin
, mode
);
4818 focus
->revert
= revertTo
;
4819 if (focusID
== FollowKeyboard
)
4820 focus
->win
= FollowKeyboardWin
;
4822 focus
->win
= focusWin
;
4823 if ((focusWin
== NoneWin
) || (focusWin
== PointerRootWin
))
4824 focus
->traceGood
= 0;
4829 for (pWin
= focusWin
; pWin
; pWin
= pWin
->parent
)
4831 if (depth
> focus
->traceSize
) {
4832 focus
->traceSize
= depth
+ 1;
4833 focus
->trace
= realloc(focus
->trace
,
4834 focus
->traceSize
* sizeof(WindowPtr
));
4836 focus
->traceGood
= depth
;
4837 for (pWin
= focusWin
, depth
--; pWin
; pWin
= pWin
->parent
, depth
--)
4838 focus
->trace
[depth
] = pWin
;
4844 * Server-side protocol handling for SetInputFocus request.
4846 * Sets the input focus for the virtual core keyboard.
4849 ProcSetInputFocus(ClientPtr client
)
4851 DeviceIntPtr kbd
= PickKeyboard(client
);
4853 REQUEST(xSetInputFocusReq
);
4855 REQUEST_SIZE_MATCH(xSetInputFocusReq
);
4857 return SetInputFocus(client
, kbd
, stuff
->focus
,
4858 stuff
->revertTo
, stuff
->time
, FALSE
);
4862 * Server-side protocol handling for GetInputFocus request.
4864 * Sends the current input focus for the client's keyboard back to the
4868 ProcGetInputFocus(ClientPtr client
)
4870 DeviceIntPtr kbd
= PickKeyboard(client
);
4871 xGetInputFocusReply rep
;
4872 FocusClassPtr focus
= kbd
->focus
;
4875 /* REQUEST(xReq); */
4876 REQUEST_SIZE_MATCH(xReq
);
4878 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, kbd
, DixGetFocusAccess
);
4882 rep
= (xGetInputFocusReply
) {
4885 .sequenceNumber
= client
->sequence
,
4886 .revertTo
= focus
->revert
4889 if (focus
->win
== NoneWin
)
4891 else if (focus
->win
== PointerRootWin
)
4892 rep
.focus
= PointerRoot
;
4894 rep
.focus
= focus
->win
->drawable
.id
;
4896 WriteReplyToClient(client
, sizeof(xGetInputFocusReply
), &rep
);
4901 * Server-side protocol handling for GrabPointer request.
4903 * Sets an active grab on the client's ClientPointer and returns success
4907 ProcGrabPointer(ClientPtr client
)
4909 xGrabPointerReply rep
;
4910 DeviceIntPtr device
= PickPointer(client
);
4913 WindowPtr confineTo
;
4916 REQUEST(xGrabPointerReq
);
4919 REQUEST_SIZE_MATCH(xGrabPointerReq
);
4920 UpdateCurrentTime();
4922 if (stuff
->eventMask
& ~PointerGrabMask
) {
4923 client
->errorValue
= stuff
->eventMask
;
4927 if (stuff
->confineTo
== None
)
4928 confineTo
= NullWindow
;
4930 rc
= dixLookupWindow(&confineTo
, stuff
->confineTo
, client
,
4936 grab
= device
->deviceGrab
.grab
;
4938 if (grab
&& grab
->confineTo
&& !confineTo
)
4939 ConfineCursorToWindow(device
, GetCurrentRootWindow(device
), FALSE
, FALSE
);
4941 mask
.core
= stuff
->eventMask
;
4943 rc
= GrabDevice(client
, device
, stuff
->pointerMode
, stuff
->keyboardMode
,
4944 stuff
->grabWindow
, stuff
->ownerEvents
, stuff
->time
,
4945 &mask
, CORE
, stuff
->cursor
, stuff
->confineTo
, &status
);
4949 rep
= (xGrabPointerReply
) {
4952 .sequenceNumber
= client
->sequence
,
4955 WriteReplyToClient(client
, sizeof(xGrabPointerReply
), &rep
);
4960 * Server-side protocol handling for ChangeActivePointerGrab request.
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.
4966 ProcChangeActivePointerGrab(ClientPtr client
)
4968 DeviceIntPtr device
;
4970 CursorPtr newCursor
, oldCursor
;
4972 REQUEST(xChangeActivePointerGrabReq
);
4975 REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq
);
4976 if (stuff
->eventMask
& ~PointerGrabMask
) {
4977 client
->errorValue
= stuff
->eventMask
;
4980 if (stuff
->cursor
== None
)
4981 newCursor
= NullCursor
;
4983 int rc
= dixLookupResourceByType((pointer
*) &newCursor
, stuff
->cursor
,
4984 RT_CURSOR
, client
, DixUseAccess
);
4986 if (rc
!= Success
) {
4987 client
->errorValue
= stuff
->cursor
;
4992 device
= PickPointer(client
);
4993 grab
= device
->deviceGrab
.grab
;
4997 if (!SameClient(grab
, client
))
4999 time
= ClientTimeToServerTime(stuff
->time
);
5000 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
5001 (CompareTimeStamps(time
, device
->deviceGrab
.grabTime
) == EARLIER
))
5003 oldCursor
= grab
->cursor
;
5004 grab
->cursor
= RefCursor(newCursor
);
5005 PostNewCursor(device
);
5007 FreeCursor(oldCursor
, (Cursor
) 0);
5008 grab
->eventMask
= stuff
->eventMask
;
5013 * Server-side protocol handling for UngrabPointer request.
5015 * Deletes a pointer grab on a device the client has grabbed.
5018 ProcUngrabPointer(ClientPtr client
)
5020 DeviceIntPtr device
= PickPointer(client
);
5024 REQUEST(xResourceReq
);
5026 REQUEST_SIZE_MATCH(xResourceReq
);
5027 UpdateCurrentTime();
5028 grab
= device
->deviceGrab
.grab
;
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
);
5039 * Sets a grab on the given device.
5041 * Called from ProcGrabKeyboard to work on the client's keyboard.
5042 * Called from ProcXGrabDevice to work on the device specified by the client.
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
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.
5054 * @returns Success or BadValue.
5057 GrabDevice(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
)
5062 WindowPtr pWin
, confineTo
;
5065 Mask access_mode
= DixGrabAccess
;
5067 GrabInfoPtr grabInfo
= &dev
->deviceGrab
;
5070 UpdateCurrentTime();
5071 if ((keyboard_mode
!= GrabModeSync
) && (keyboard_mode
!= GrabModeAsync
)) {
5072 client
->errorValue
= keyboard_mode
;
5075 if ((pointer_mode
!= GrabModeSync
) && (pointer_mode
!= GrabModeAsync
)) {
5076 client
->errorValue
= pointer_mode
;
5079 if ((ownerEvents
!= xFalse
) && (ownerEvents
!= xTrue
)) {
5080 client
->errorValue
= ownerEvents
;
5084 rc
= dixLookupWindow(&pWin
, grabWindow
, client
, DixSetAttrAccess
);
5088 if (confineToWin
== None
)
5089 confineTo
= NullWindow
;
5091 rc
= dixLookupWindow(&confineTo
, confineToWin
, client
,
5098 cursor
= NullCursor
;
5100 rc
= dixLookupResourceByType((pointer
*) &cursor
, curs
, RT_CURSOR
,
5101 client
, DixUseAccess
);
5102 if (rc
!= Success
) {
5103 client
->errorValue
= curs
;
5106 access_mode
|= DixForceAccess
;
5109 if (keyboard_mode
== GrabModeSync
|| pointer_mode
== GrabModeSync
)
5110 access_mode
|= DixFreezeAccess
;
5111 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, access_mode
);
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
) ||
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
;
5134 tempGrab
= AllocGrab(NULL
);
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
;
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
;
5161 * Server-side protocol handling for GrabKeyboard request.
5163 * Grabs the client's keyboard and returns success status to client.
5166 ProcGrabKeyboard(ClientPtr client
)
5168 xGrabKeyboardReply rep
;
5171 REQUEST(xGrabKeyboardReq
);
5173 DeviceIntPtr keyboard
= PickKeyboard(client
);
5176 REQUEST_SIZE_MATCH(xGrabKeyboardReq
);
5178 mask
.core
= KeyPressMask
| KeyReleaseMask
;
5180 result
= GrabDevice(client
, keyboard
, stuff
->pointerMode
,
5181 stuff
->keyboardMode
, stuff
->grabWindow
,
5182 stuff
->ownerEvents
, stuff
->time
, &mask
, CORE
, None
,
5185 if (result
!= Success
)
5188 rep
= (xGrabKeyboardReply
) {
5191 .sequenceNumber
= client
->sequence
,
5194 WriteReplyToClient(client
, sizeof(xGrabKeyboardReply
), &rep
);
5199 * Server-side protocol handling for UngrabKeyboard request.
5201 * Deletes a possible grab on the client's keyboard.
5204 ProcUngrabKeyboard(ClientPtr client
)
5206 DeviceIntPtr device
= PickKeyboard(client
);
5210 REQUEST(xResourceReq
);
5212 REQUEST_SIZE_MATCH(xResourceReq
);
5213 UpdateCurrentTime();
5215 grab
= device
->deviceGrab
.grab
;
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
);
5226 * Server-side protocol handling for QueryPointer request.
5228 * Returns the current state and position of the client's ClientPointer to the
5232 ProcQueryPointer(ClientPtr client
)
5234 xQueryPointerReply rep
;
5236 DeviceIntPtr mouse
= PickPointer(client
);
5237 DeviceIntPtr keyboard
;
5241 REQUEST(xResourceReq
);
5242 REQUEST_SIZE_MATCH(xResourceReq
);
5244 rc
= dixLookupWindow(&pWin
, stuff
->id
, client
, DixGetAttrAccess
);
5247 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, mouse
, DixReadAccess
);
5248 if (rc
!= Success
&& rc
!= BadAccess
)
5251 keyboard
= GetMaster(mouse
, MASTER_KEYBOARD
);
5253 pSprite
= mouse
->spriteInfo
->sprite
;
5254 if (mouse
->valuator
->motionHintWindow
)
5255 MaybeStopHint(mouse
, client
);
5256 rep
= (xQueryPointerReply
) {
5258 .sequenceNumber
= client
->sequence
,
5260 .mask
= event_get_corestate(mouse
, keyboard
),
5261 .root
= (GetCurrentRootWindow(mouse
))->drawable
.id
,
5262 .rootX
= pSprite
->hot
.x
,
5263 .rootY
= pSprite
->hot
.y
,
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
;
5277 rep
.sameScreen
= xFalse
;
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
;
5293 if (rc
== BadAccess
) {
5302 WriteReplyToClient(client
, sizeof(xQueryPointerReply
), &rep
);
5308 * Initializes the device list and the DIX sprite to sane values. Allocates
5309 * trace memory used for quick window traversal.
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
;
5323 for (i
= 0; i
< MAXDEVICES
; i
++) {
5325 memcpy(&event_filters
[i
], default_filter
, sizeof(default_filter
));
5328 NoticeTime(&dummy
, currentTime
);
5329 LastEventTimeToggleResetFlag(i
, FALSE
);
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
)
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;
5348 InputEventList
= InitEventList(GetMaximumEventsNum());
5349 if (!InputEventList
)
5350 FatalError("[dix] Failed to allocate input event list.\n");
5354 CloseDownEvents(void)
5356 FreeEventList(InputEventList
, GetMaximumEventsNum());
5357 InputEventList
= NULL
;
5360 #define SEND_EVENT_BIT 0x80
5363 * Server-side protocol handling for SendEvent request.
5365 * Locates the window to send the event to and forwards the event.
5368 ProcSendEvent(ClientPtr client
)
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
;
5376 REQUEST(xSendEventReq
);
5378 REQUEST_SIZE_MATCH(xSendEventReq
);
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.
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 */
5388 stuff
->event
.u
.u
.type
&= ~(SEND_EVENT_BIT
);
5390 /* The client's event type must be a core event type or one defined by an
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
;
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
;
5406 if (stuff
->eventMask
& ~AllEventMasks
) {
5407 client
->errorValue
= stuff
->eventMask
;
5411 if (stuff
->destination
== PointerWindow
)
5412 pWin
= pSprite
->win
;
5413 else if (stuff
->destination
== InputFocus
) {
5414 WindowPtr inputFocus
= (keybd
) ? keybd
->focus
->win
: NoneWin
;
5416 if (inputFocus
== NoneWin
)
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
);
5424 if (IsParent(inputFocus
, pSprite
->win
)) {
5425 effectiveFocus
= inputFocus
;
5426 pWin
= pSprite
->win
;
5429 effectiveFocus
= pWin
= inputFocus
;
5432 dixLookupWindow(&pWin
, stuff
->destination
, client
, DixSendAccess
);
5436 if ((stuff
->propagate
!= xFalse
) && (stuff
->propagate
!= xTrue
)) {
5437 client
->errorValue
= stuff
->propagate
;
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
,
5446 if (DeliverEventsToWindow(dev
, pWin
,
5447 &stuff
->event
, 1, stuff
->eventMask
,
5450 if (pWin
== effectiveFocus
)
5452 stuff
->eventMask
&= ~wDontPropagateMask(pWin
);
5453 if (!stuff
->eventMask
)
5457 else if (!XaceHook(XACE_SEND_ACCESS
, client
, NULL
, pWin
, &stuff
->event
, 1))
5458 DeliverEventsToWindow(dev
, pWin
, &stuff
->event
,
5459 1, stuff
->eventMask
, NullGrab
);
5464 * Server-side protocol handling for UngrabKey request.
5466 * Deletes a passive grab for the given key. Works on the
5467 * client's keyboard.
5470 ProcUngrabKey(ClientPtr client
)
5472 REQUEST(xUngrabKeyReq
);
5475 DeviceIntPtr keybd
= PickKeyboard(client
);
5478 REQUEST_SIZE_MATCH(xUngrabKeyReq
);
5479 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixGetAttrAccess
);
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
;
5489 if ((stuff
->modifiers
!= AnyModifier
) &&
5490 (stuff
->modifiers
& ~AllModifiersMask
)) {
5491 client
->errorValue
= stuff
->modifiers
;
5494 tempGrab
= AllocGrab(NULL
);
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
;
5509 if (!DeletePassiveGrabFromList(tempGrab
))
5518 * Server-side protocol handling for GrabKey request.
5520 * Creates a grab for the client's keyboard and adds it to the list of passive
5524 ProcGrabKey(ClientPtr client
)
5528 REQUEST(xGrabKeyReq
);
5530 DeviceIntPtr keybd
= PickKeyboard(client
);
5532 GrabParameters param
;
5535 REQUEST_SIZE_MATCH(xGrabKeyReq
);
5537 param
= (GrabParameters
) {
5539 .ownerEvents
= stuff
->ownerEvents
,
5540 .this_device_mode
= stuff
->keyboardMode
,
5541 .other_devices_mode
= stuff
->pointerMode
,
5542 .modifiers
= stuff
->modifiers
5545 rc
= CheckGrabValues(client
, ¶m
);
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
;
5555 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixSetAttrAccess
);
5559 mask
.core
= (KeyPressMask
| KeyReleaseMask
);
5561 grab
= CreateGrab(client
->index
, keybd
, keybd
, pWin
, CORE
, &mask
,
5562 ¶m
, KeyPress
, stuff
->key
, NullWindow
, NullCursor
);
5565 return AddPassiveGrabToList(client
, grab
);
5569 * Server-side protocol handling for GrabButton request.
5571 * Creates a grab for the client's ClientPointer and adds it as a passive grab
5575 ProcGrabButton(ClientPtr client
)
5577 WindowPtr pWin
, confineTo
;
5579 REQUEST(xGrabButtonReq
);
5582 DeviceIntPtr ptr
, modifierDevice
;
5583 Mask access_mode
= DixGrabAccess
;
5585 GrabParameters param
;
5588 REQUEST_SIZE_MATCH(xGrabButtonReq
);
5589 if ((stuff
->pointerMode
!= GrabModeSync
) &&
5590 (stuff
->pointerMode
!= GrabModeAsync
)) {
5591 client
->errorValue
= stuff
->pointerMode
;
5594 if ((stuff
->keyboardMode
!= GrabModeSync
) &&
5595 (stuff
->keyboardMode
!= GrabModeAsync
)) {
5596 client
->errorValue
= stuff
->keyboardMode
;
5599 if ((stuff
->modifiers
!= AnyModifier
) &&
5600 (stuff
->modifiers
& ~AllModifiersMask
)) {
5601 client
->errorValue
= stuff
->modifiers
;
5604 if ((stuff
->ownerEvents
!= xFalse
) && (stuff
->ownerEvents
!= xTrue
)) {
5605 client
->errorValue
= stuff
->ownerEvents
;
5608 if (stuff
->eventMask
& ~PointerGrabMask
) {
5609 client
->errorValue
= stuff
->eventMask
;
5612 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixSetAttrAccess
);
5615 if (stuff
->confineTo
== None
)
5616 confineTo
= NullWindow
;
5618 rc
= dixLookupWindow(&confineTo
, stuff
->confineTo
, client
,
5623 if (stuff
->cursor
== None
)
5624 cursor
= NullCursor
;
5626 rc
= dixLookupResourceByType((pointer
*) &cursor
, stuff
->cursor
,
5627 RT_CURSOR
, client
, DixUseAccess
);
5628 if (rc
!= Success
) {
5629 client
->errorValue
= stuff
->cursor
;
5632 access_mode
|= DixForceAccess
;
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
);
5644 param
= (GrabParameters
) {
5646 .ownerEvents
= stuff
->ownerEvents
,
5647 .this_device_mode
= stuff
->keyboardMode
,
5648 .other_devices_mode
= stuff
->pointerMode
,
5649 .modifiers
= stuff
->modifiers
5652 mask
.core
= stuff
->eventMask
;
5654 grab
= CreateGrab(client
->index
, ptr
, modifierDevice
, pWin
,
5655 CORE
, &mask
, ¶m
, ButtonPress
,
5656 stuff
->button
, confineTo
, cursor
);
5659 return AddPassiveGrabToList(client
, grab
);
5663 * Server-side protocol handling for UngrabButton request.
5665 * Deletes a passive grab on the client's ClientPointer from the list.
5668 ProcUngrabButton(ClientPtr client
)
5670 REQUEST(xUngrabButtonReq
);
5676 REQUEST_SIZE_MATCH(xUngrabButtonReq
);
5677 if ((stuff
->modifiers
!= AnyModifier
) &&
5678 (stuff
->modifiers
& ~AllModifiersMask
)) {
5679 client
->errorValue
= stuff
->modifiers
;
5682 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixReadAccess
);
5686 ptr
= PickPointer(client
);
5688 tempGrab
= AllocGrab(NULL
);
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
;
5703 if (!DeletePassiveGrabFromList(tempGrab
))
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.
5715 * If freeResources is set, passive grabs on the window are deleted.
5717 * @param pWin The window to delete events from.
5718 * @param freeResources True if resources associated with the window should be
5722 DeleteWindowFromAnyEvents(WindowPtr pWin
, Bool freeResources
)
5725 DeviceIntPtr mouse
= inputInfo
.pointer
;
5726 DeviceIntPtr keybd
= inputInfo
.keyboard
;
5727 FocusClassPtr focus
;
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
);
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
);
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
);
5750 for (keybd
= inputInfo
.devices
; keybd
; keybd
= keybd
->next
) {
5751 if (IsKeyboardDevice(keybd
)) {
5752 focus
= keybd
->focus
;
5754 /* If the focus window is a root window (ie. has no parent)
5755 then don't delete the focus from it. */
5757 if ((pWin
== focus
->win
) && (pWin
->parent
!= NullWindow
)) {
5758 int focusEventMode
= NotifyNormal
;
5760 /* If a grab is in progress, then alter the mode of focus events. */
5762 if (keybd
->deviceGrab
.grab
)
5763 focusEventMode
= NotifyWhileGrabbed
;
5765 switch (focus
->revert
) {
5767 DoFocusEvents(keybd
, pWin
, NoneWin
, focusEventMode
);
5768 focus
->win
= NoneWin
;
5769 focus
->traceGood
= 0;
5771 case RevertToParent
:
5774 parent
= parent
->parent
;
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
5784 || wClient(parent
)->clientGone
5787 if (!ActivateFocusInGrab(keybd
, pWin
, parent
))
5788 DoFocusEvents(keybd
, pWin
, parent
, focusEventMode
);
5789 focus
->win
= parent
;
5790 focus
->revert
= RevertToNone
;
5792 case RevertToPointerRoot
:
5793 if (!ActivateFocusInGrab(keybd
, pWin
, PointerRootWin
))
5794 DoFocusEvents(keybd
, pWin
, PointerRootWin
,
5796 focus
->win
= PointerRootWin
;
5797 focus
->traceGood
= 0;
5803 if (IsPointerDevice(keybd
)) {
5804 if (keybd
->valuator
->motionHintWindow
== pWin
)
5805 keybd
->valuator
->motionHintWindow
= NullWindow
;
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
);
5818 DeleteWindowFromAnyExtEvents(pWin
, freeResources
);
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
5827 CheckCursorConfinement(WindowPtr pWin
)
5830 WindowPtr confineTo
;
5834 if (!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
)
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
);
5852 EventMaskForClient(WindowPtr pWin
, ClientPtr client
)
5854 OtherClientsPtr other
;
5856 if (wClient(pWin
) == client
)
5857 return pWin
->eventMask
;
5858 for (other
= wOtherClients(pWin
); other
; other
= other
->next
) {
5859 if (SameClient(other
, client
))
5866 * Server-side protocol handling for RecolorCursor request.
5869 ProcRecolorCursor(ClientPtr client
)
5875 SpritePtr pSprite
= PickPointer(client
)->spriteInfo
->sprite
;
5877 REQUEST(xRecolorCursorReq
);
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
;
5887 pCursor
->foreRed
= stuff
->foreRed
;
5888 pCursor
->foreGreen
= stuff
->foreGreen
;
5889 pCursor
->foreBlue
= stuff
->foreBlue
;
5891 pCursor
->backRed
= stuff
->backRed
;
5892 pCursor
->backGreen
= stuff
->backGreen
;
5893 pCursor
->backBlue
= stuff
->backBlue
;
5895 for (nscr
= 0; nscr
< screenInfo
.numScreens
; nscr
++) {
5896 pscr
= screenInfo
.screens
[nscr
];
5898 if (!noPanoramiXExtension
)
5899 displayed
= (pscr
== pSprite
->screen
);
5902 displayed
= (pscr
== pSprite
->hotPhys
.pScreen
);
5903 (*pscr
->RecolorCursor
) (PickPointer(client
), pscr
, pCursor
,
5904 (pCursor
== pSprite
->current
) && displayed
);
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.
5914 * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
5915 * can be more than one. Usually it's just one event.
5917 * Do not modify the event structure passed in. See comment below.
5919 * @param pClient Client to send events to.
5920 * @param count Number of events.
5921 * @param events The event list.
5924 WriteEventsToClient(ClientPtr pClient
, int count
, xEvent
*events
)
5929 xEvent
*eventTo
, *eventFrom
;
5930 int i
, eventlength
= sizeof(xEvent
);
5932 if (!pClient
|| pClient
== serverClient
|| pClient
->clientGone
)
5935 for (i
= 0; i
< count
; i
++)
5936 if ((events
[i
].u
.u
.type
& 0x7f) != KeymapNotify
)
5937 events
[i
].u
.u
.sequenceNumber
= pClient
->sequence
;
5939 /* Let XKB rewrite the state, as it depends on client preferences. */
5940 XkbFilterEvents(pClient
, count
, events
);
5943 if (!noPanoramiXExtension
&&
5944 (screenInfo
.screens
[0]->x
|| screenInfo
.screens
[0]->y
)) {
5945 switch (events
->u
.u
.type
) {
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
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
;
5967 events
= &eventCopy
;
5975 if (EventCallback
) {
5976 EventInfoRec eventinfo
;
5978 eventinfo
.client
= pClient
;
5979 eventinfo
.events
= events
;
5980 eventinfo
.count
= count
;
5981 CallCallbacks(&EventCallback
, (pointer
) &eventinfo
);
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
]);
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");
5999 if (events
->u
.u
.type
== GenericEvent
) {
6000 eventlength
+= ((xGenericEvent
*) events
)->length
* 4;
6003 if (pClient
->swapped
) {
6004 if (eventlength
> swapEventLen
) {
6005 swapEventLen
= eventlength
;
6006 swapEvent
= realloc(swapEvent
, swapEventLen
);
6008 FatalError("WriteEventsToClient: Out of memory.\n");
6013 for (i
= 0; i
< count
; i
++) {
6014 eventFrom
= &events
[i
];
6015 eventTo
= swapEvent
;
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
);
6022 WriteToClient(pClient
, eventlength
, eventTo
);
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
);
6034 * Set the client pointer for the given client.
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
6040 * If a keyboard is needed, the first keyboard paired with the CP is used.
6043 SetClientPointer(ClientPtr client
, DeviceIntPtr device
)
6045 int rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, device
, DixUseAccess
);
6050 if (!IsMaster(device
)) {
6051 ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
6054 else if (!device
->spriteInfo
->spriteOwner
) {
6055 ErrorF("[dix] Device %d does not have a sprite. "
6056 "Cannot be ClientPointer\n", device
->id
);
6059 client
->clientPtr
= device
;
6063 /* PickPointer will pick an appropriate pointer for the given client.
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.
6071 PickPointer(ClientPtr client
)
6073 DeviceIntPtr it
= inputInfo
.devices
;
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
;
6080 if (grab
&& grab
->grabtype
== CORE
&& SameClient(grab
, client
)) {
6081 it
= GetMaster(it
, MASTER_POINTER
);
6082 return it
; /* Always return a core grabbed device */
6086 if (!client
->clientPtr
) {
6087 it
= inputInfo
.devices
;
6089 if (IsMaster(it
) && it
->spriteInfo
->spriteOwner
) {
6090 client
->clientPtr
= it
;
6096 return client
->clientPtr
;
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.
6104 PickKeyboard(ClientPtr client
)
6106 DeviceIntPtr ptr
= PickPointer(client
);
6107 DeviceIntPtr kbd
= GetMaster(ptr
, MASTER_KEYBOARD
);
6110 ErrorF("[dix] ClientPointer not paired with a keyboard. This "
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.
6122 * Return true if a core event from the device would interfere and should not
6126 IsInterferingGrab(ClientPtr client
, DeviceIntPtr dev
, xEvent
*event
)
6128 DeviceIntPtr it
= inputInfo
.devices
;
6130 switch (event
->u
.u
.type
) {
6143 if (dev
->deviceGrab
.grab
&& SameClient(dev
->deviceGrab
.grab
, client
))
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
)))
6161 /* PointerBarrier events are only delivered to the client that created that
6164 IsWrongPointerBarrierClient(ClientPtr client
, DeviceIntPtr dev
, xEvent
*event
)
6166 xXIBarrierEvent
*ev
= (xXIBarrierEvent
*)event
;
6168 if (ev
->type
!= GenericEvent
|| ev
->extension
!= IReqCode
)
6171 if (ev
->evtype
!= XI_BarrierHit
&& ev
->evtype
!= XI_BarrierLeave
)
6174 return client
->index
!= CLIENT_ID(ev
->barrier
);