Bug Summary

File:dix/events.c
Location:line 4119, column 17
Description:Value stored to 'deliveries' is never read

Annotated Source Code

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