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