Bug Summary

File:dix/events.c
Location:line 4121, 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 = ((void*)0), 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 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
())))
==
1401 CLIENT_BITS(grab->resource)((grab->resource) & (((1 << ResourceClientBits()
) - 1) << (29 - ResourceClientBits())))
))
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 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
())))
==
1412 CLIENT_BITS(grab->resource)((grab->resource) & (((1 << ResourceClientBits()
) - 1) << (29 - ResourceClientBits())))
))
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 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits())))
== 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 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (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 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (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 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
1751 devgrabinfo->sync.state = THAWED1;
1752 if (devgrabinfo->sync.other &&
1753 SameClient(devgrabinfo->sync.other, client)((((devgrabinfo->sync.other)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) == (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 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (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 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) == (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 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
1789 devgrabinfo->sync.state = THAWED1;
1790 if (devgrabinfo->sync.other
1791 && SameClient(devgrabinfo->sync.other, client)((((devgrabinfo->sync.other)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) == (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 UpdateCurrentTime();
1826 time = ClientTimeToServerTime(stuff->time);
1827
1828 mouse = PickPointer(client);
1829 keybd = PickKeyboard(client);
1830
1831 switch (stuff->mode) {
1832 case ReplayPointer2:
1833 AllowSome(client, time, mouse, NOT_GRABBED0);
1834 break;
1835 case SyncPointer1:
1836 AllowSome(client, time, mouse, FREEZE_NEXT_EVENT3);
1837 break;
1838 case AsyncPointer0:
1839 AllowSome(client, time, mouse, THAWED1);
1840 break;
1841 case ReplayKeyboard5:
1842 AllowSome(client, time, keybd, NOT_GRABBED0);
1843 break;
1844 case SyncKeyboard4:
1845 AllowSome(client, time, keybd, FREEZE_NEXT_EVENT3);
1846 break;
1847 case AsyncKeyboard3:
1848 AllowSome(client, time, keybd, THAWED1);
1849 break;
1850 case SyncBoth7:
1851 AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT4);
1852 break;
1853 case AsyncBoth6:
1854 AllowSome(client, time, keybd, THAWED_BOTH2);
1855 break;
1856 default:
1857 client->errorValue = stuff->mode;
1858 return BadValue2;
1859 }
1860 return Success0;
1861}
1862
1863/**
1864 * Deactivate grabs from any device that has been grabbed by the client.
1865 */
1866void
1867ReleaseActiveGrabs(ClientPtr client)
1868{
1869 DeviceIntPtr dev;
1870 Bool done;
1871
1872 /* XXX CloseDownClient should remove passive grabs before
1873 * releasing active grabs.
1874 */
1875 do {
1876 done = TRUE1;
1877 for (dev = inputInfo.devices; dev; dev = dev->next) {
1878 if (dev->deviceGrab.grab &&
1879 SameClient(dev->deviceGrab.grab, client)((((dev->deviceGrab.grab)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) == (client)->clientAsMask)
) {
1880 (*dev->deviceGrab.DeactivateGrab) (dev);
1881 done = FALSE0;
1882 }
1883 }
1884 } while (!done);
1885}
1886
1887/**************************************************************************
1888 * The following procedures deal with delivering events *
1889 **************************************************************************/
1890
1891/**
1892 * Deliver the given events to the given client.
1893 *
1894 * More than one event may be delivered at a time. This is the case with
1895 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1896 *
1897 * TryClientEvents() is the last station before actually writing the events to
1898 * the socket. Anything that is not filtered here, will get delivered to the
1899 * client.
1900 * An event is only delivered if
1901 * - mask and filter match up.
1902 * - no other client has a grab on the device that caused the event.
1903 *
1904 *
1905 * @param client The target client to deliver to.
1906 * @param dev The device the event came from. May be NULL.
1907 * @param pEvents The events to be delivered.
1908 * @param count Number of elements in pEvents.
1909 * @param mask Event mask as set by the window.
1910 * @param filter Mask based on event type.
1911 * @param grab Possible grab on the device that caused the event.
1912 *
1913 * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1914 * client.
1915 */
1916int
1917TryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
1918 int count, Mask mask, Mask filter, GrabPtr grab)
1919{
1920 int type;
1921
1922#ifdef DEBUG_EVENTS
1923 ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
1924 pEvents->u.u.type, pEvents->u.u.detail, mask,
1925 client ? client->index : -1,
1926 (client && client->clientGone) ? " (gone)" : "");
1927#endif
1928
1929 if (!client || client == serverClient || client->clientGone) {
1930#ifdef DEBUG_EVENTS
1931 ErrorF(" not delivered to fake/dead client\n");
1932#endif
1933 return 0;
1934 }
1935
1936 if (filter != CantBeFiltered0L && !(mask & filter)) {
1937#ifdef DEBUG_EVENTS
1938 ErrorF(" filtered\n");
1939#endif
1940 return 0;
1941 }
1942
1943 if (grab && !SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
) {
1944#ifdef DEBUG_EVENTS
1945 ErrorF(" not delivered due to grab\n");
1946#endif
1947 return -1; /* don't send, but notify caller */
1948 }
1949
1950 type = pEvents->u.u.type;
1951 if (type == MotionNotify6) {
1952 if (mask & PointerMotionHintMask(1L<<7)) {
1953 if (WID(dev->valuator->motionHintWindow)((dev->valuator->motionHintWindow) ? ((dev->valuator
->motionHintWindow)->drawable.id) : 0)
==
1954 pEvents->u.keyButtonPointer.event) {
1955#ifdef DEBUG_EVENTS
1956 ErrorF("[dix] \n");
1957 ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
1958#endif
1959 return 1; /* don't send, but pretend we did */
1960 }
1961 pEvents->u.u.detail = NotifyHint1;
1962 }
1963 else {
1964 pEvents->u.u.detail = NotifyNormal0;
1965 }
1966 }
1967 else if (type == DeviceMotionNotify) {
1968 if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents,
1969 mask) != 0)
1970 return 1;
1971 }
1972 else if (type == KeyPress2) {
1973 if (EventIsKeyRepeat(pEvents)) {
1974 if (!_XkbWantsDetectableAutoRepeat(client)((client)->xkbClientFlags&(1L << 0))) {
1975 xEvent release = *pEvents;
1976
1977 release.u.u.type = KeyRelease3;
1978 WriteEventsToClient(client, 1, &release);
1979#ifdef DEBUG_EVENTS
1980 ErrorF(" (plus fake core release for repeat)");
1981#endif
1982 }
1983 else {
1984#ifdef DEBUG_EVENTS
1985 ErrorF(" (detectable autorepeat for core)");
1986#endif
1987 }
1988 }
1989
1990 }
1991 else if (type == DeviceKeyPress) {
1992 if (EventIsKeyRepeat(pEvents)) {
1993 if (!_XkbWantsDetectableAutoRepeat(client)((client)->xkbClientFlags&(1L << 0))) {
1994 deviceKeyButtonPointer release =
1995 *(deviceKeyButtonPointer *) pEvents;
1996 release.type = DeviceKeyRelease;
1997#ifdef DEBUG_EVENTS
1998 ErrorF(" (plus fake xi1 release for repeat)");
1999#endif
2000 WriteEventsToClient(client, 1, (xEvent *) &release);
2001 }
2002 else {
2003#ifdef DEBUG_EVENTS
2004 ErrorF(" (detectable autorepeat for core)");
2005#endif
2006 }
2007 }
2008 }
2009
2010 if (BitIsOn(criticalEvents, type)(!!(((const BYTE *) (criticalEvents))[(type)>>3] & (
1 << ((type) & 7))))
) {
2011 if (client->smart_priority < SMART_MAX_PRIORITY(20))
2012 client->smart_priority++;
2013 SetCriticalOutputPending();
2014 }
2015
2016 WriteEventsToClient(client, count, pEvents);
2017#ifdef DEBUG_EVENTS
2018 ErrorF("[dix] delivered\n");
2019#endif
2020 return 1;
2021}
2022
2023static BOOL
2024ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
2025 xEvent *event, Mask deliveryMask)
2026{
2027 GrabPtr tempGrab;
2028 OtherInputMasks *inputMasks;
2029 CARD8 type = event->u.u.type;
2030 enum InputLevel grabtype;
2031
2032 if (type == ButtonPress4)
2033 grabtype = CORE;
2034 else if (type == DeviceButtonPress)
2035 grabtype = XI;
2036 else if ((type = xi2_get_type(event)) == XI_ButtonPress4)
2037 grabtype = XI2;
2038 else
2039 return FALSE0;
2040
2041 tempGrab = AllocGrab(NULL((void*)0));
2042 if (!tempGrab)
2043 return FALSE0;
2044 tempGrab->next = NULL((void*)0);
2045 tempGrab->device = dev;
2046 tempGrab->resource = client->clientAsMask;
2047 tempGrab->window = win;
2048 tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask(1L<<24)) ? TRUE1 : FALSE0;
2049 tempGrab->eventMask = deliveryMask;
2050 tempGrab->keyboardMode = GrabModeAsync1;
2051 tempGrab->pointerMode = GrabModeAsync1;
2052 tempGrab->confineTo = NullWindow((WindowPtr) 0);
2053 tempGrab->cursor = NullCursor((CursorPtr)((void*)0));
2054 tempGrab->type = type;
2055 tempGrab->grabtype = grabtype;
2056
2057 /* get the XI and XI2 device mask */
2058 inputMasks = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
;
2059 tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0;
2060
2061 if (inputMasks)
2062 xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
2063
2064 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab,
2065 currentTime, TRUE1 | ImplicitGrabMask(1 << 7));
2066 FreeGrab(tempGrab);
2067 return TRUE1;
2068}
2069
2070/**
2071 * Attempt event delivery to the client owning the window.
2072 */
2073static enum EventDeliveryState
2074DeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
2075 xEvent *events, int count, Mask filter, GrabPtr grab)
2076{
2077 /* if nobody ever wants to see this event, skip some work */
2078 if (filter != CantBeFiltered0L &&
2079 !((wOtherEventMasks(win)((win)->optional ? (win)->optional->otherEventMasks :
0)
| win->eventMask) & filter))
2080 return EVENT_SKIP;
2081
2082 if (IsInterferingGrab(wClient(win)(clients[((int)((((win)->drawable.id) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, dev, events))
2083 return EVENT_SKIP;
2084
2085 if (!XaceHook(XACE_RECEIVE_ACCESS6, wClient(win)(clients[((int)((((win)->drawable.id) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, win, events, count)) {
2086 int attempt = TryClientEvents(wClient(win)(clients[((int)((((win)->drawable.id) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, dev, events,
2087 count, win->eventMask,
2088 filter, grab);
2089
2090 if (attempt > 0)
2091 return EVENT_DELIVERED;
2092 if (attempt < 0)
2093 return EVENT_REJECTED;
2094 }
2095
2096 return EVENT_NOT_DELIVERED;
2097}
2098
2099/**
2100 * Get the list of clients that should be tried for event delivery on the
2101 * given window.
2102 *
2103 * @return 1 if the client list should be traversed, zero if the event
2104 * should be skipped.
2105 */
2106static Bool
2107GetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
2108 xEvent *events, Mask filter, InputClients ** iclients)
2109{
2110 int rc = 0;
2111
2112 if (core_get_type(events) != 0)
2113 *iclients = (InputClients *) wOtherClients(win)((win)->optional ? (win)->optional->otherClients : (
(void*)0))
;
2114 else if (xi2_get_type(events) != 0) {
2115 OtherInputMasks *inputMasks = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
;
2116
2117 /* Has any client selected for the event? */
2118 if (!WindowXI2MaskIsset(dev, win, events))
2119 goto out;
2120 *iclients = inputMasks->inputClients;
2121 }
2122 else {
2123 OtherInputMasks *inputMasks = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
;
2124
2125 /* Has any client selected for the event? */
2126 if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter))
2127 goto out;
2128
2129 *iclients = inputMasks->inputClients;
2130 }
2131
2132 rc = 1;
2133 out:
2134 return rc;
2135}
2136
2137/**
2138 * Try delivery on each client in inputclients, provided the event mask
2139 * accepts it and there is no interfering core grab..
2140 */
2141static enum EventDeliveryState
2142DeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
2143 WindowPtr win, xEvent *events,
2144 int count, Mask filter, GrabPtr grab,
2145 ClientPtr *client_return, Mask *mask_return)
2146{
2147 int attempt;
2148 enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
2149 Bool have_device_button_grab_class_client = FALSE0;
2150
2151 for (; inputclients; inputclients = inputclients->next) {
2152 Mask mask;
2153 ClientPtr client = rClient(inputclients)(clients[((int)((((inputclients)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
2154
2155 if (IsInterferingGrab(client, dev, events))
2156 continue;
2157
2158 if (IsWrongPointerBarrierClient(client, dev, events))
2159 continue;
2160
2161 mask = GetEventMask(dev, events, inputclients);
2162
2163 if (XaceHook(XACE_RECEIVE_ACCESS6, client, win, events, count))
2164 /* do nothing */ ;
2165 else if ((attempt = TryClientEvents(client, dev,
2166 events, count,
2167 mask, filter, grab))) {
2168 if (attempt > 0) {
2169 /*
2170 * The order of clients is arbitrary therefore if one
2171 * client belongs to DeviceButtonGrabClass make sure to
2172 * catch it.
2173 */
2174 if (!have_device_button_grab_class_client) {
2175 rc = EVENT_DELIVERED;
2176 *client_return = client;
2177 *mask_return = mask;
2178 /* Success overrides non-success, so if we've been
2179 * successful on one client, return that */
2180 if (mask & DeviceButtonGrabMask)
2181 have_device_button_grab_class_client = TRUE1;
2182 }
2183 } else if (rc == EVENT_NOT_DELIVERED)
2184 rc = EVENT_REJECTED;
2185 }
2186 }
2187
2188 return rc;
2189}
2190
2191/**
2192 * Deliver events to clients registered on the window.
2193 *
2194 * @param client_return On successful delivery, set to the recipient.
2195 * @param mask_return On successful delivery, set to the recipient's event
2196 * mask for this event.
2197 */
2198static enum EventDeliveryState
2199DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
2200 int count, Mask filter, GrabPtr grab,
2201 ClientPtr *client_return, Mask *mask_return)
2202{
2203 InputClients *iclients;
2204
2205 if (!GetClientsForDelivery(dev, win, events, filter, &iclients))
2206 return EVENT_SKIP;
2207
2208 return DeliverEventToInputClients(dev, iclients, win, events, count, filter,
2209 grab, client_return, mask_return);
2210
2211}
2212
2213/**
2214 * Deliver events to a window. At this point, we do not yet know if the event
2215 * actually needs to be delivered. May activate a grab if the event is a
2216 * button press.
2217 *
2218 * Core events are always delivered to the window owner. If the filter is
2219 * something other than CantBeFiltered, the event is also delivered to other
2220 * clients with the matching mask on the window.
2221 *
2222 * More than one event may be delivered at a time. This is the case with
2223 * DeviceMotionNotifies which may be followed by DeviceValuator events.
2224 *
2225 * @param pWin The window that would get the event.
2226 * @param pEvents The events to be delivered.
2227 * @param count Number of elements in pEvents.
2228 * @param filter Mask based on event type.
2229 * @param grab Possible grab on the device that caused the event.
2230 *
2231 * @return a positive number if at least one successful delivery has been
2232 * made, 0 if no events were delivered, or a negative number if the event
2233 * has not been delivered _and_ rejected by at least one client.
2234 */
2235int
2236DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
2237 *pEvents, int count, Mask filter, GrabPtr grab)
2238{
2239 int deliveries = 0, nondeliveries = 0;
2240 ClientPtr client = NullClient((ClientPtr) 0);
2241 Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
2242 this mask is the mask of the grab. */
2243 int type = pEvents->u.u.type;
2244
2245 UpdateCurrentTimeIf();
2246 /* Deliver to window owner */
2247 if ((filter == CantBeFiltered0L) || core_get_type(pEvents) != 0) {
2248 enum EventDeliveryState rc;
2249
2250 rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
2251
2252 switch (rc) {
2253 case EVENT_SKIP:
2254 return 0;
2255 case EVENT_REJECTED:
2256 nondeliveries--;
2257 break;
2258 case EVENT_DELIVERED:
2259 /* We delivered to the owner, with our event mask */
2260 deliveries++;
2261 client = wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
2262 deliveryMask = pWin->eventMask;
2263 break;
2264 case EVENT_NOT_DELIVERED:
2265 break;
2266 }
2267 }
2268
2269 /* CantBeFiltered means only window owner gets the event */
2270 if (filter != CantBeFiltered0L) {
2271 enum EventDeliveryState rc;
2272
2273 rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
2274 grab, &client, &deliveryMask);
2275
2276 switch (rc) {
2277 case EVENT_SKIP:
2278 return 0;
2279 case EVENT_REJECTED:
2280 nondeliveries--;
2281 break;
2282 case EVENT_DELIVERED:
2283 deliveries++;
2284 break;
2285 case EVENT_NOT_DELIVERED:
2286 break;
2287 }
2288 }
2289
2290 if (deliveries) {
2291 /*
2292 * Note that since core events are delivered first, an implicit grab may
2293 * be activated on a core grab, stopping the XI events.
2294 */
2295 if (!grab &&
2296 ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
2297 /* grab activated */ ;
2298 else if (type == MotionNotify6)
2299 pDev->valuator->motionHintWindow = pWin;
2300 else if (type == DeviceMotionNotify || type == DeviceButtonPress)
2301 CheckDeviceGrabAndHintWindow(pWin, type,
2302 (deviceKeyButtonPointer *) pEvents,
2303 grab, client, deliveryMask);
2304 return deliveries;
2305 }
2306 return nondeliveries;
2307}
2308
2309/**
2310 * Filter out raw events for XI 2.0 and XI 2.1 clients.
2311 *
2312 * If there is a grab on the device, 2.0 clients only get raw events if they
2313 * have the grab. 2.1+ clients get raw events in all cases.
2314 *
2315 * @return TRUE if the event should be discarded, FALSE otherwise.
2316 */
2317static BOOL
2318FilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root)
2319{
2320 XIClientPtr client_xi_version;
2321 int cmp;
2322
2323 /* device not grabbed -> don't filter */
2324 if (!grab)
2325 return FALSE0;
2326
2327 client_xi_version =
2328 dixLookupPrivate(&client->devPrivates, XIClientPrivateKey(&XIClientPrivateKeyRec));
2329
2330 cmp = version_compare(client_xi_version->major_version,
2331 client_xi_version->minor_version, 2, 0);
2332 /* XI 2.0: if device is grabbed, skip
2333 XI 2.1: if device is grabbed by us, skip, we've already delivered */
2334 if (cmp == 0)
2335 return TRUE1;
2336
2337 return (grab->window != root) ? FALSE0 : SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
;
2338}
2339
2340/**
2341 * Deliver a raw event to the grab owner (if any) and to all root windows.
2342 *
2343 * Raw event delivery differs between XI 2.0 and XI 2.1.
2344 * XI 2.0: events delivered to the grabbing client (if any) OR to all root
2345 * windows
2346 * XI 2.1: events delivered to all root windows, regardless of grabbing
2347 * state.
2348 */
2349void
2350DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
2351{
2352 GrabPtr grab = device->deviceGrab.grab;
2353 xEvent *xi;
2354 int i, rc;
2355 int filter;
2356
2357 rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi);
2358 if (rc != Success0) {
2359 ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
2360 __func__, device->name, rc);
2361 return;
2362 }
2363
2364 if (grab)
2365 DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE0);
2366
2367 filter = GetEventFilter(device, xi);
2368
2369 for (i = 0; i < screenInfo.numScreens; i++) {
2370 WindowPtr root;
2371 InputClients *inputclients;
2372
2373 root = screenInfo.screens[i]->root;
2374 if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
2375 continue;
2376
2377 for (; inputclients; inputclients = inputclients->next) {
2378 ClientPtr c; /* unused */
2379 Mask m; /* unused */
2380 InputClients ic = *inputclients;
2381
2382 /* Because we run through the list manually, copy the actual
2383 * list, shorten the copy to only have one client and then pass
2384 * that down to DeliverEventToInputClients. This way we avoid
2385 * double events on XI 2.1 clients that have a grab on the
2386 * device.
2387 */
2388 ic.next = NULL((void*)0);
2389
2390 if (!FilterRawEvents(rClient(&ic)(clients[((int)((((&ic)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
, grab, root))
2391 DeliverEventToInputClients(device, &ic, root, xi, 1,
2392 filter, NULL((void*)0), &c, &m);
2393 }
2394 }
2395
2396 free(xi);
2397}
2398
2399/* If the event goes to dontClient, don't send it and return 0. if
2400 send works, return 1 or if send didn't work, return 2.
2401 Only works for core events.
2402*/
2403
2404#ifdef PANORAMIX1
2405static int
2406XineramaTryClientEventsResult(ClientPtr client,
2407 GrabPtr grab, Mask mask, Mask filter)
2408{
2409 if ((client) && (client != serverClient) && (!client->clientGone) &&
2410 ((filter == CantBeFiltered0L) || (mask & filter))) {
2411 if (grab && !SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
2412 return -1;
2413 else
2414 return 1;
2415 }
2416 return 0;
2417}
2418#endif
2419
2420/**
2421 * Try to deliver events to the interested parties.
2422 *
2423 * @param pWin The window that would get the event.
2424 * @param pEvents The events to be delivered.
2425 * @param count Number of elements in pEvents.
2426 * @param filter Mask based on event type.
2427 * @param dontClient Don't deliver to the dontClient.
2428 */
2429int
2430MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
2431 int count, Mask filter, ClientPtr dontClient)
2432{
2433 OtherClients *other;
2434
2435 if (pWin->eventMask & filter) {
2436 if (wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
== dontClient)
2437 return 0;
2438#ifdef PANORAMIX1
2439 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2440 return XineramaTryClientEventsResult(wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
, NullGrab((GrabPtr)((void*)0)),
2441 pWin->eventMask, filter);
2442#endif
2443 if (XaceHook(XACE_RECEIVE_ACCESS6, wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
, pWin, pEvents, count))
2444 return 1; /* don't send, but pretend we did */
2445 return TryClientEvents(wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
, NULL((void*)0), pEvents, count,
2446 pWin->eventMask, filter, NullGrab((GrabPtr)((void*)0)));
2447 }
2448 for (other = wOtherClients(pWin)((pWin)->optional ? (pWin)->optional->otherClients :
((void*)0))
; other; other = other->next) {
2449 if (other->mask & filter) {
2450 if (SameClient(other, dontClient)((((other)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (dontClient
)->clientAsMask)
)
2451 return 0;
2452#ifdef PANORAMIX1
2453 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2454 return XineramaTryClientEventsResult(rClient(other)(clients[((int)((((other)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, NullGrab((GrabPtr)((void*)0)),
2455 other->mask, filter);
2456#endif
2457 if (XaceHook(XACE_RECEIVE_ACCESS6, rClient(other)(clients[((int)((((other)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, pWin, pEvents,
2458 count))
2459 return 1; /* don't send, but pretend we did */
2460 return TryClientEvents(rClient(other)(clients[((int)((((other)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, NULL((void*)0), pEvents, count,
2461 other->mask, filter, NullGrab((GrabPtr)((void*)0)));
2462 }
2463 }
2464 return 2;
2465}
2466
2467static Window
2468FindChildForEvent(SpritePtr pSprite, WindowPtr event)
2469{
2470 WindowPtr w = DeepestSpriteWin(pSprite);
2471 Window child = None0L;
2472
2473 /* If the search ends up past the root should the child field be
2474 set to none or should the value in the argument be passed
2475 through. It probably doesn't matter since everyone calls
2476 this function with child == None anyway. */
2477 while (w) {
2478 /* If the source window is same as event window, child should be
2479 none. Don't bother going all all the way back to the root. */
2480
2481 if (w == event) {
2482 child = None0L;
2483 break;
2484 }
2485
2486 if (w->parent == event) {
2487 child = w->drawable.id;
2488 break;
2489 }
2490 w = w->parent;
2491 }
2492 return child;
2493}
2494
2495/**
2496 * Adjust event fields to comply with the window properties.
2497 *
2498 * @param xE Event to be modified in place
2499 * @param pWin The window to get the information from.
2500 * @param child Child window setting for event (if applicable)
2501 * @param calcChild If True, calculate the child window.
2502 */
2503void
2504FixUpEventFromWindow(SpritePtr pSprite,
2505 xEvent *xE, WindowPtr pWin, Window child, Bool calcChild)
2506{
2507 int evtype;
2508
2509 if (calcChild)
2510 child = FindChildForEvent(pSprite, pWin);
2511
2512 if ((evtype = xi2_get_type(xE))) {
2513 xXIDeviceEvent *event = (xXIDeviceEvent *) xE;
2514
2515 switch (evtype) {
2516 case XI_RawKeyPress13:
2517 case XI_RawKeyRelease14:
2518 case XI_RawButtonPress15:
2519 case XI_RawButtonRelease16:
2520 case XI_RawMotion17:
2521 case XI_RawTouchBegin22:
2522 case XI_RawTouchUpdate23:
2523 case XI_RawTouchEnd24:
2524 case XI_DeviceChanged1:
2525 case XI_HierarchyChanged11:
2526 case XI_PropertyEvent12:
2527 case XI_BarrierHit25:
2528 case XI_BarrierLeave26:
2529 return;
2530 default:
2531 break;
2532 }
2533
2534 event->root = RootWindow(pSprite)pSprite->spriteTrace[0]->drawable.id;
2535 event->event = pWin->drawable.id;
2536
2537 if (evtype == XI_TouchOwnership21) {
2538 event->child = child;
2539 return;
2540 }
2541
2542 if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
2543 event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
2544 event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
2545 event->child = child;
2546 }
2547 else {
2548 event->event_x = 0;
2549 event->event_y = 0;
2550 event->child = None0L;
2551 }
2552
2553 if (event->evtype == XI_Enter7 || event->evtype == XI_Leave8 ||
2554 event->evtype == XI_FocusIn9 || event->evtype == XI_FocusOut10)
2555 ((xXIEnterEvent *) event)->same_screen =
2556 (pSprite->hot.pScreen == pWin->drawable.pScreen);
2557
2558 }
2559 else {
2560 XE_KBPTR(xE->u.keyButtonPointer).root = RootWindow(pSprite)pSprite->spriteTrace[0]->drawable.id;
2561 XE_KBPTR(xE->u.keyButtonPointer).event = pWin->drawable.id;
2562 if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
2563 XE_KBPTR(xE->u.keyButtonPointer).sameScreen = xTrue1;
2564 XE_KBPTR(xE->u.keyButtonPointer).child = child;
2565 XE_KBPTR(xE->u.keyButtonPointer).eventX = XE_KBPTR(xE->u.keyButtonPointer).rootX - pWin->drawable.x;
2566 XE_KBPTR(xE->u.keyButtonPointer).eventY = XE_KBPTR(xE->u.keyButtonPointer).rootY - pWin->drawable.y;
2567 }
2568 else {
2569 XE_KBPTR(xE->u.keyButtonPointer).sameScreen = xFalse0;
2570 XE_KBPTR(xE->u.keyButtonPointer).child = None0L;
2571 XE_KBPTR(xE->u.keyButtonPointer).eventX = 0;
2572 XE_KBPTR(xE->u.keyButtonPointer).eventY = 0;
2573 }
2574 }
2575}
2576
2577/**
2578 * Check if a given event is deliverable at all on a given window.
2579 *
2580 * This function only checks if any client wants it, not for a specific
2581 * client.
2582 *
2583 * @param[in] dev The device this event is being sent for.
2584 * @param[in] evtype The event type of the event that is to be sent.
2585 * @param[in] win The current event window.
2586 *
2587 * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
2588 * ::EVENT_DONT_PROPAGATE_MASK.
2589 */
2590int
2591EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
2592{
2593 int rc = 0;
2594 int filter = 0;
2595 int type;
2596 OtherInputMasks *inputMasks = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
;
2597
2598 if ((type = GetXI2Type(evtype)) != 0) {
2599 if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
2600 rc |= EVENT_XI2_MASK(1 << 3);
2601 }
2602
2603 if ((type = GetXIType(evtype)) != 0) {
2604 filter = event_get_filter_from_type(dev, type);
2605
2606 /* Check for XI mask */
2607 if (inputMasks &&
2608 (inputMasks->deliverableEvents[dev->id] & filter) &&
2609 (inputMasks->inputEvents[dev->id] & filter))
2610 rc |= EVENT_XI1_MASK(1 << 0);
2611
2612 /* Check for XI DontPropagate mask */
2613 if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
2614 rc |= EVENT_DONT_PROPAGATE_MASK(1 << 2);
2615
2616 }
2617
2618 if ((type = GetCoreType(evtype)) != 0) {
2619 filter = event_get_filter_from_type(dev, type);
2620
2621 /* Check for core mask */
2622 if ((win->deliverableEvents & filter) &&
2623 ((wOtherEventMasks(win)((win)->optional ? (win)->optional->otherEventMasks :
0)
| win->eventMask) & filter))
2624 rc |= EVENT_CORE_MASK(1 << 1);
2625
2626 /* Check for core DontPropagate mask */
2627 if (filter & wDontPropagateMask(win)((win)->optional ? (win)->optional->dontPropagateMask
: DontPropagateMasks[(win)->dontPropagate])
)
2628 rc |= EVENT_DONT_PROPAGATE_MASK(1 << 2);
2629 }
2630
2631 return rc;
2632}
2633
2634static int
2635DeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
2636 WindowPtr win, Window child, GrabPtr grab)
2637{
2638 SpritePtr pSprite = dev->spriteInfo->sprite;
2639 Mask filter;
2640 int deliveries = 0;
2641
2642 if (XaceHook(XACE_SEND_ACCESS5, NULL((void*)0), dev, win, xE, count) == Success0) {
2643 filter = GetEventFilter(dev, xE);
2644 FixUpEventFromWindow(pSprite, xE, win, child, FALSE0);
2645 deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab);
2646 }
2647
2648 return deliveries;
2649}
2650
2651static int
2652DeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
2653 WindowPtr win, Window child, GrabPtr grab)
2654{
2655 xEvent *xE = NULL((void*)0);
2656 int count = 0;
2657 int deliveries = 0;
2658 int rc;
2659
2660 switch (level) {
2661 case XI2:
2662 rc = EventToXI2(event, &xE);
2663 count = 1;
2664 break;
2665 case XI:
2666 rc = EventToXI(event, &xE, &count);
2667 break;
2668 case CORE:
2669 rc = EventToCore(event, &xE, &count);
2670 break;
2671 default:
2672 rc = BadImplementation17;
2673 break;
2674 }
2675
2676 if (rc == Success0) {
2677 deliveries = DeliverEvent(dev, xE, count, win, child, grab);
2678 free(xE);
2679 }
2680 else
2681 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", 2683
, __func__); if (1) ErrorFSigSafe("%s: conversion to level %d failed with rc %d\n"
, dev->name, level, rc); xorg_backtrace(); } } while(0)
2682 "%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", 2683
, __func__); if (1) ErrorFSigSafe("%s: conversion to level %d failed with rc %d\n"
, dev->name, level, rc); xorg_backtrace(); } } while(0)
2683 dev->name, level, rc)do { if (rc != 8) { ErrorFSigSafe("BUG: triggered 'if (" "rc != 8"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "events.c", 2683
, __func__); if (1) ErrorFSigSafe("%s: conversion to level %d failed with rc %d\n"
, dev->name, level, rc); xorg_backtrace(); } } while(0)
;
2684 return deliveries;
2685}
2686
2687/**
2688 * Deliver events caused by input devices.
2689 *
2690 * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
2691 * called directly from the processInputProc.
2692 * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
2693 * DeliverDeviceEvents.
2694 * For focused events, DeliverFocusedEvent is called first, and _may_ call
2695 * DeliverDeviceEvents.
2696 *
2697 * @param pWin Window to deliver event to.
2698 * @param event The events to deliver, not yet in wire format.
2699 * @param grab Possible grab on a device.
2700 * @param stopAt Don't recurse up to the root window.
2701 * @param dev The device that is responsible for the event.
2702 *
2703 * @see DeliverGrabbedEvent
2704 * @see DeliverFocusedEvent
2705 */
2706int
2707DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
2708 WindowPtr stopAt, DeviceIntPtr dev)
2709{
2710 Window child = None0L;
2711 int deliveries = 0;
2712 int mask;
2713
2714 verify_internal_event(event);
2715
2716 while (pWin) {
2717 if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) {
2718 /* XI2 events first */
2719 if (mask & EVENT_XI2_MASK(1 << 3)) {
2720 deliveries =
2721 DeliverOneEvent(event, dev, XI2, pWin, child, grab);
2722 if (deliveries > 0)
2723 break;
2724 }
2725
2726 /* XI events */
2727 if (mask & EVENT_XI1_MASK(1 << 0)) {
2728 deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
2729 if (deliveries > 0)
2730 break;
2731 }
2732
2733 /* Core event */
2734 if ((mask & EVENT_CORE_MASK(1 << 1)) && IsMaster(dev) && dev->coreEvents) {
2735 deliveries =
2736 DeliverOneEvent(event, dev, CORE, pWin, child, grab);
2737 if (deliveries > 0)
2738 break;
2739 }
2740
2741 }
2742
2743 if ((deliveries < 0) || (pWin == stopAt) ||
2744 (mask & EVENT_DONT_PROPAGATE_MASK(1 << 2))) {
2745 deliveries = 0;
2746 break;
2747 }
2748
2749 child = pWin->drawable.id;
2750 pWin = pWin->parent;
2751 }
2752
2753 return deliveries;
2754}
2755
2756/**
2757 * Deliver event to a window and it's immediate parent. Used for most window
2758 * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2759 * propagate up the tree or extension events
2760 *
2761 * In case of a ReparentNotify event, the event will be delivered to the
2762 * otherParent as well.
2763 *
2764 * @param pWin Window to deliver events to.
2765 * @param xE Events to deliver.
2766 * @param count number of events in xE.
2767 * @param otherParent Used for ReparentNotify events.
2768 */
2769int
2770DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
2771{
2772 DeviceIntRec dummy;
2773 int deliveries;
2774
2775#ifdef PANORAMIX1
2776 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2777 return count;
2778#endif
2779
2780 if (!count)
2781 return 0;
2782
2783 dummy.id = XIAllDevices0;
2784
2785 switch (xE->u.u.type) {
2786 case DestroyNotify17:
2787 case UnmapNotify18:
2788 case MapNotify19:
2789 case MapRequest20:
2790 case ReparentNotify21:
2791 case ConfigureNotify22:
2792 case ConfigureRequest23:
2793 case GravityNotify24:
2794 case CirculateNotify26:
2795 case CirculateRequest27:
2796 xE->u.destroyNotify.event = pWin->drawable.id;
2797 break;
2798 }
2799
2800 switch (xE->u.u.type) {
2801 case DestroyNotify17:
2802 case UnmapNotify18:
2803 case MapNotify19:
2804 case ReparentNotify21:
2805 case ConfigureNotify22:
2806 case GravityNotify24:
2807 case CirculateNotify26:
2808 break;
2809 default:
2810 {
2811 Mask filter;
2812
2813 filter = GetEventFilter(&dummy, xE);
2814 return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab((GrabPtr)((void*)0)));
2815 }
2816 }
2817
2818 deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
2819 StructureNotifyMask(1L<<17), NullGrab((GrabPtr)((void*)0)));
2820 if (pWin->parent) {
2821 xE->u.destroyNotify.event = pWin->parent->drawable.id;
2822 deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
2823 SubstructureNotifyMask(1L<<19), NullGrab((GrabPtr)((void*)0)));
2824 if (xE->u.u.type == ReparentNotify21) {
2825 xE->u.destroyNotify.event = otherParent->drawable.id;
2826 deliveries += DeliverEventsToWindow(&dummy,
2827 otherParent, xE, count,
2828 SubstructureNotifyMask(1L<<19),
2829 NullGrab((GrabPtr)((void*)0)));
2830 }
2831 }
2832 return deliveries;
2833}
2834
2835Bool
2836PointInBorderSize(WindowPtr pWin, int x, int y)
2837{
2838 BoxRec box;
2839
2840 if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
2841 return TRUE1;
2842
2843#ifdef PANORAMIX1
2844 if (!noPanoramiXExtension &&
2845 XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
2846 SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
2847 int i;
2848
2849 FOR_NSCREENS_FORWARD_SKIP(i)for(i = 1; i < PanoramiXNumScreens; i++) {
2850 if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
2851 x + screenInfo.screens[0]->x -
2852 screenInfo.screens[i]->x,
2853 y + screenInfo.screens[0]->y -
2854 screenInfo.screens[i]->y, &box))
2855 return TRUE1;
2856 }
2857 }
2858#endif
2859 return FALSE0;
2860}
2861
2862/**
2863 * Traversed from the root window to the window at the position x/y. While
2864 * traversing, it sets up the traversal history in the spriteTrace array.
2865 * After completing, the spriteTrace history is set in the following way:
2866 * spriteTrace[0] ... root window
2867 * spriteTrace[1] ... top level window that encloses x/y
2868 * ...
2869 * spriteTrace[spriteTraceGood - 1] ... window at x/y
2870 *
2871 * @returns the window at the given coordinates.
2872 */
2873WindowPtr
2874XYToWindow(SpritePtr pSprite, int x, int y)
2875{
2876 ScreenPtr pScreen = RootWindow(pSprite)pSprite->spriteTrace[0]->drawable.pScreen;
2877
2878 return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
2879}
2880
2881/**
2882 * Ungrab a currently FocusIn grabbed device and grab the device on the
2883 * given window. If the win given is the NoneWin, the device is ungrabbed if
2884 * applicable and FALSE is returned.
2885 *
2886 * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2887 */
2888BOOL
2889ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2890{
2891 BOOL rc = FALSE0;
2892 DeviceEvent event;
2893
2894 if (dev->deviceGrab.grab) {
2895 if (!dev->deviceGrab.fromPassiveGrab ||
2896 dev->deviceGrab.grab->type != XI_Enter7 ||
2897 dev->deviceGrab.grab->window == win ||
2898 IsParent(dev->deviceGrab.grab->window, win))
2899 return FALSE0;
2900 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab5);
2901 (*dev->deviceGrab.DeactivateGrab) (dev);
2902 }
2903
2904 if (win == NoneWin((WindowPtr)0L) || win == PointerRootWin((WindowPtr)1L))
2905 return FALSE0;
2906
2907 event = (DeviceEvent) {
2908 .header = ET_Internal,
2909 .type = ET_FocusIn,
2910 .length = sizeof(DeviceEvent),
2911 .time = GetTimeInMillis(),
2912 .deviceid = dev->id,
2913 .sourceid = dev->id,
2914 .detail.button = 0
2915 };
2916 rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE0,
2917 TRUE1) != NULL((void*)0));
2918 if (rc)
2919 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab5);
2920 return rc;
2921}
2922
2923/**
2924 * Ungrab a currently Enter grabbed device and grab the device for the given
2925 * window.
2926 *
2927 * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2928 */
2929static BOOL
2930ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2931{
2932 BOOL rc = FALSE0;
2933 DeviceEvent event;
2934
2935 if (dev->deviceGrab.grab) {
2936 if (!dev->deviceGrab.fromPassiveGrab ||
2937 dev->deviceGrab.grab->type != XI_Enter7 ||
2938 dev->deviceGrab.grab->window == win ||
2939 IsParent(dev->deviceGrab.grab->window, win))
2940 return FALSE0;
2941 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab5);
2942 (*dev->deviceGrab.DeactivateGrab) (dev);
2943 }
2944
2945 event = (DeviceEvent) {
2946 .header = ET_Internal,
2947 .type = ET_Enter,
2948 .length = sizeof(DeviceEvent),
2949 .time = GetTimeInMillis(),
2950 .deviceid = dev->id,
2951 .sourceid = dev->id,
2952 .detail.button = 0
2953 };
2954 rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE0,
2955 TRUE1) != NULL((void*)0));
2956 if (rc)
2957 DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab4);
2958 return rc;
2959}
2960
2961/**
2962 * Update the sprite coordinates based on the event. Update the cursor
2963 * position, then update the event with the new coordinates that may have been
2964 * changed. If the window underneath the sprite has changed, change to new
2965 * cursor and send enter/leave events.
2966 *
2967 * CheckMotion() will not do anything and return FALSE if the event is not a
2968 * pointer event.
2969 *
2970 * @return TRUE if the sprite has moved or FALSE otherwise.
2971 */
2972Bool
2973CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
2974{
2975 WindowPtr prevSpriteWin, newSpriteWin;
2976 SpritePtr pSprite = pDev->spriteInfo->sprite;
2977
2978 verify_internal_event((InternalEvent *) ev);
2979
2980 prevSpriteWin = pSprite->win;
2981
2982 if (ev && !syncEvents.playingEvents) {
2983 /* GetPointerEvents() guarantees that pointer events have the correct
2984 rootX/Y set already. */
2985 switch (ev->type) {
2986 case ET_ButtonPress:
2987 case ET_ButtonRelease:
2988 case ET_Motion:
2989 case ET_TouchBegin:
2990 case ET_TouchUpdate:
2991 case ET_TouchEnd:
2992 break;
2993 default:
2994 /* all other events return FALSE */
2995 return FALSE0;
2996 }
2997
2998#ifdef PANORAMIX1
2999 if (!noPanoramiXExtension) {
3000 /* Motion events entering DIX get translated to Screen 0
3001 coordinates. Replayed events have already been
3002 translated since they've entered DIX before */
3003 ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
3004 ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
3005 }
3006 else
3007#endif
3008 {
3009 if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) {
3010 pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
3011 RootWindow(pDev->spriteInfo->sprite)pDev->spriteInfo->sprite->spriteTrace[0] =
3012 pSprite->hot.pScreen->root;
3013 }
3014 }
3015
3016 pSprite->hot.x = ev->root_x;
3017 pSprite->hot.y = ev->root_y;
3018 if (pSprite->hot.x < pSprite->physLimits.x1)
3019 pSprite->hot.x = pSprite->physLimits.x1;
3020 else if (pSprite->hot.x >= pSprite->physLimits.x2)
3021 pSprite->hot.x = pSprite->physLimits.x2 - 1;
3022 if (pSprite->hot.y < pSprite->physLimits.y1)
3023 pSprite->hot.y = pSprite->physLimits.y1;
3024 else if (pSprite->hot.y >= pSprite->physLimits.y2)
3025 pSprite->hot.y = pSprite->physLimits.y2 - 1;
3026 if (pSprite->hotShape)
3027 ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x,
3028 &pSprite->hot.y);
3029 pSprite->hotPhys = pSprite->hot;
3030
3031 if ((pSprite->hotPhys.x != ev->root_x) ||
3032 (pSprite->hotPhys.y != ev->root_y)) {
3033#ifdef PANORAMIX1
3034 if (!noPanoramiXExtension) {
3035 XineramaSetCursorPosition(pDev, pSprite->hotPhys.x,
3036 pSprite->hotPhys.y, FALSE0);
3037 }
3038 else
3039#endif
3040 {
3041 (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev,
3042 pSprite->
3043 hotPhys.pScreen,
3044 pSprite->
3045 hotPhys.x,
3046 pSprite->
3047 hotPhys.y,
3048 FALSE0);
3049 }
3050 }
3051
3052 ev->root_x = pSprite->hot.x;
3053 ev->root_y = pSprite->hot.y;
3054 }
3055
3056 newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
3057
3058 if (newSpriteWin != prevSpriteWin) {
3059 int sourceid;
3060
3061 if (!ev) {
3062 UpdateCurrentTimeIf();
3063 sourceid = pDev->id; /* when from WindowsRestructured */
3064 }
3065 else
3066 sourceid = ev->sourceid;
3067
3068 if (prevSpriteWin != NullWindow((WindowPtr) 0)) {
3069 if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
3070 DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
3071 newSpriteWin, NotifyNormal0);
3072 }
3073 /* set pSprite->win after ActivateEnterGrab, otherwise
3074 sprite window == grab_window and no enter/leave events are
3075 sent. */
3076 pSprite->win = newSpriteWin;
3077 PostNewCursor(pDev);
3078 return FALSE0;
3079 }
3080 return TRUE1;
3081}
3082
3083/**
3084 * Windows have restructured, we need to update the sprite position and the
3085 * sprite's cursor.
3086 */
3087void
3088WindowsRestructured(void)
3089{
3090 DeviceIntPtr pDev = inputInfo.devices;
3091
3092 while (pDev) {
3093 if (IsMaster(pDev) || IsFloating(pDev))
3094 CheckMotion(NULL((void*)0), pDev);
3095 pDev = pDev->next;
3096 }
3097}
3098
3099#ifdef PANORAMIX1
3100/* This was added to support reconfiguration under Xdmx. The problem is
3101 * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
3102 * other than 0,0, the information in the private sprite structure must
3103 * be updated accordingly, or XYToWindow (and other routines) will not
3104 * compute correctly. */
3105void
3106ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
3107{
3108 GrabPtr grab;
3109 DeviceIntPtr pDev;
3110 SpritePtr pSprite;
3111
3112 if (noPanoramiXExtension)
3113 return;
3114
3115 pDev = inputInfo.devices;
3116 while (pDev) {
3117 if (DevHasCursor(pDev)) {
3118 pSprite = pDev->spriteInfo->sprite;
3119 pSprite->hot.x -= xoff;
3120 pSprite->hot.y -= yoff;
3121
3122 pSprite->hotPhys.x -= xoff;
3123 pSprite->hotPhys.y -= yoff;
3124
3125 pSprite->hotLimits.x1 -= xoff;
3126 pSprite->hotLimits.y1 -= yoff;
3127 pSprite->hotLimits.x2 -= xoff;
3128 pSprite->hotLimits.y2 -= yoff;
3129
3130 if (RegionNotEmpty(&pSprite->Reg1))
3131 RegionTranslate(&pSprite->Reg1, xoff, yoff);
3132 if (RegionNotEmpty(&pSprite->Reg2))
3133 RegionTranslate(&pSprite->Reg2, xoff, yoff);
3134
3135 /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
3136 if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
3137 if (grab->confineTo->drawable.pScreen
3138 != pSprite->hotPhys.pScreen)
3139 pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
3140 ConfineCursorToWindow(pDev, grab->confineTo, TRUE1, TRUE1);
3141 }
3142 else
3143 ConfineCursorToWindow(pDev,
3144 pSprite->hotPhys.pScreen->root,
3145 TRUE1, FALSE0);
3146
3147 }
3148 pDev = pDev->next;
3149 }
3150}
3151#endif
3152
3153/**
3154 * Initialize a sprite for the given device and set it to some sane values. If
3155 * the device already has a sprite alloc'd, don't realloc but just reset to
3156 * default values.
3157 * If a window is supplied, the sprite will be initialized with the window's
3158 * cursor and positioned in the center of the window's screen. The root window
3159 * is a good choice to pass in here.
3160 *
3161 * It's a good idea to call it only for pointer devices, unless you have a
3162 * really talented keyboard.
3163 *
3164 * @param pDev The device to initialize.
3165 * @param pWin The window where to generate the sprite in.
3166 *
3167 */
3168void
3169InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
3170{
3171 SpritePtr pSprite;
3172 ScreenPtr pScreen;
3173 CursorPtr pCursor;
3174
3175 if (!pDev->spriteInfo->sprite) {
3176 DeviceIntPtr it;
3177
3178 pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec));
3179 if (!pDev->spriteInfo->sprite)
3180 FatalError("InitializeSprite: failed to allocate sprite struct");
3181
3182 /* We may have paired another device with this device before our
3183 * device had a actual sprite. We need to check for this and reset the
3184 * sprite field for all paired devices.
3185 *
3186 * The VCK is always paired with the VCP before the VCP has a sprite.
3187 */
3188 for (it = inputInfo.devices; it; it = it->next) {
3189 if (it->spriteInfo->paired == pDev)
3190 it->spriteInfo->sprite = pDev->spriteInfo->sprite;
3191 }
3192 if (inputInfo.keyboard->spriteInfo->paired == pDev)
3193 inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
3194 }
3195
3196 pSprite = pDev->spriteInfo->sprite;
3197 pDev->spriteInfo->spriteOwner = TRUE1;
3198
3199 pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL((void*)0);
3200 pSprite->hot.pScreen = pScreen;
3201 pSprite->hotPhys.pScreen = pScreen;
3202 if (pScreen) {
3203 pSprite->hotPhys.x = pScreen->width / 2;
3204 pSprite->hotPhys.y = pScreen->height / 2;
3205 pSprite->hotLimits.x2 = pScreen->width;
3206 pSprite->hotLimits.y2 = pScreen->height;
3207 }
3208
3209 pSprite->hot = pSprite->hotPhys;
3210 pSprite->win = pWin;
3211
3212 if (pWin) {
3213 pCursor = wCursor(pWin)((pWin)->cursorIsNone ? 0L : ((pWin)->optional ? (pWin)
->optional->cursor : FindWindowWithOptional(pWin)->optional
->cursor))
;
3214 pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr));
3215 if (!pSprite->spriteTrace)
3216 FatalError("Failed to allocate spriteTrace");
3217 pSprite->spriteTraceSize = 32;
3218
3219 RootWindow(pDev->spriteInfo->sprite)pDev->spriteInfo->sprite->spriteTrace[0] = pWin;
3220 pSprite->spriteTraceGood = 1;
3221
3222 pSprite->pEnqueueScreen = pScreen;
3223 pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3224
3225 }
3226 else {
3227 pCursor = NullCursor((CursorPtr)((void*)0));
3228 pSprite->spriteTrace = NULL((void*)0);
3229 pSprite->spriteTraceSize = 0;
3230 pSprite->spriteTraceGood = 0;
3231 pSprite->pEnqueueScreen = screenInfo.screens[0];
3232 pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3233 }
3234 pCursor = RefCursor(pCursor);
3235 if (pSprite->current)
3236 FreeCursor(pSprite->current, None0L);
3237 pSprite->current = pCursor;
3238
3239 if (pScreen) {
3240 (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
3241 (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current,
3242 &pSprite->hotLimits, &pSprite->physLimits);
3243 pSprite->confined = FALSE0;
3244
3245 (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3246 (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
3247 pSprite->hot.y, FALSE0);
3248 (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3249 }
3250#ifdef PANORAMIX1
3251 if (!noPanoramiXExtension) {
3252 pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3253 pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3254 pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
3255 pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3256 pSprite->physLimits = pSprite->hotLimits;
3257 pSprite->confineWin = NullWindow((WindowPtr) 0);
3258 pSprite->hotShape = NullRegion((RegionPtr)0);
3259 pSprite->screen = pScreen;
3260 /* gotta UNINIT these someplace */
3261 RegionNull(&pSprite->Reg1);
3262 RegionNull(&pSprite->Reg2);
3263 }
3264#endif
3265}
3266
3267void FreeSprite(DeviceIntPtr dev)
3268{
3269 if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
3270 if (dev->spriteInfo->sprite->current)
3271 FreeCursor(dev->spriteInfo->sprite->current, None0L);
3272 free(dev->spriteInfo->sprite->spriteTrace);
3273 free(dev->spriteInfo->sprite);
3274 }
3275 dev->spriteInfo->sprite = NULL((void*)0);
3276}
3277
3278
3279/**
3280 * Update the mouse sprite info when the server switches from a pScreen to another.
3281 * Otherwise, the pScreen of the mouse sprite is never updated when we switch
3282 * from a pScreen to another. Never updating the pScreen of the mouse sprite
3283 * implies that windows that are in pScreen whose pScreen->myNum >0 will never
3284 * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen
3285 * always points to the first pScreen it has been set by
3286 * DefineInitialRootWindow().
3287 *
3288 * Calling this function is useful for use cases where the server
3289 * has more than one pScreen.
3290 * This function is similar to DefineInitialRootWindow() but it does not
3291 * reset the mouse pointer position.
3292 * @param win must be the new pScreen we are switching to.
3293 */
3294void
3295UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
3296{
3297 SpritePtr pSprite = NULL((void*)0);
3298 WindowPtr win = NULL((void*)0);
3299 CursorPtr pCursor;
3300
3301 if (!pScreen)
3302 return;
3303
3304 if (!pDev->spriteInfo->sprite)
3305 return;
3306
3307 pSprite = pDev->spriteInfo->sprite;
3308
3309 win = pScreen->root;
3310
3311 pSprite->hotPhys.pScreen = pScreen;
3312 pSprite->hot = pSprite->hotPhys;
3313 pSprite->hotLimits.x2 = pScreen->width;
3314 pSprite->hotLimits.y2 = pScreen->height;
3315 pSprite->win = win;
3316 pCursor = RefCursor(wCursor(win)((win)->cursorIsNone ? 0L : ((win)->optional ? (win)->
optional->cursor : FindWindowWithOptional(win)->optional
->cursor))
);
3317 if (pSprite->current)
3318 FreeCursor(pSprite->current, 0);
3319 pSprite->current = pCursor;
3320 pSprite->spriteTraceGood = 1;
3321 pSprite->spriteTrace[0] = win;
3322 (*pScreen->CursorLimits) (pDev,
3323 pScreen,
3324 pSprite->current,
3325 &pSprite->hotLimits, &pSprite->physLimits);
3326 pSprite->confined = FALSE0;
3327 (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3328 (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3329
3330#ifdef PANORAMIX1
3331 if (!noPanoramiXExtension) {
3332 pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3333 pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3334 pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
3335 pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3336 pSprite->physLimits = pSprite->hotLimits;
3337 pSprite->screen = pScreen;
3338 }
3339#endif
3340}
3341
3342/*
3343 * This does not take any shortcuts, and even ignores its argument, since
3344 * it does not happen very often, and one has to walk up the tree since
3345 * this might be a newly instantiated cursor for an intermediate window
3346 * between the one the pointer is in and the one that the last cursor was
3347 * instantiated from.
3348 */
3349void
3350WindowHasNewCursor(WindowPtr pWin)
3351{
3352 DeviceIntPtr pDev;
3353
3354 for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
3355 if (DevHasCursor(pDev))
3356 PostNewCursor(pDev);
3357}
3358
3359void
3360NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
3361{
3362 DeviceIntPtr ptr;
3363 SpritePtr pSprite;
3364
3365 ptr =
3366 IsFloating(pDev) ? pDev :
3367 GetXTestDevice(GetMaster(pDev, MASTER_POINTER1));
3368 pSprite = ptr->spriteInfo->sprite;
3369
3370 pSprite->hotPhys.x = x;
3371 pSprite->hotPhys.y = y;
3372#ifdef PANORAMIX1
3373 if (!noPanoramiXExtension) {
3374 pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
3375 pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
3376 if (newScreen != pSprite->screen) {
3377 pSprite->screen = newScreen;
3378 /* Make sure we tell the DDX to update its copy of the screen */
3379 if (pSprite->confineWin)
3380 XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE1);
3381 else
3382 XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root,
3383 TRUE1);
3384 /* if the pointer wasn't confined, the DDX won't get
3385 told of the pointer warp so we reposition it here */
3386 if (!syncEvents.playingEvents)
3387 (*pSprite->screen->SetCursorPosition) (ptr,
3388 pSprite->screen,
3389 pSprite->hotPhys.x +
3390 screenInfo.screens[0]->
3391 x - pSprite->screen->x,
3392 pSprite->hotPhys.y +
3393 screenInfo.screens[0]->
3394 y - pSprite->screen->y,
3395 FALSE0);
3396 }
3397 }
3398 else
3399#endif
3400 if (newScreen != pSprite->hotPhys.pScreen)
3401 ConfineCursorToWindow(ptr, newScreen->root, TRUE1, FALSE0);
3402}
3403
3404#ifdef PANORAMIX1
3405
3406static Bool
3407XineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y)
3408{
3409 BoxRec box;
3410 int i, xoff, yoff;
3411
3412 if (!pWin->realized)
3413 return FALSE0;
3414
3415 if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
3416 return TRUE1;
3417
3418 if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin))
3419 return FALSE0;
3420
3421 xoff = x + screenInfo.screens[0]->x;
3422 yoff = y + screenInfo.screens[0]->y;
3423
3424 FOR_NSCREENS_FORWARD_SKIP(i)for(i = 1; i < PanoramiXNumScreens; i++) {
3425 pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
3426
3427 x = xoff - screenInfo.screens[i]->x;
3428 y = yoff - screenInfo.screens[i]->y;
3429
3430 if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
3431 && (!wInputShape(pWin)((pWin)->optional ? (pWin)->optional->inputShape : (
(void*)0))
||
3432 RegionContainsPoint(wInputShape(pWin)((pWin)->optional ? (pWin)->optional->inputShape : (
(void*)0))
,
3433 x - pWin->drawable.x,
3434 y - pWin->drawable.y, &box)))
3435 return TRUE1;
3436
3437 }
3438
3439 return FALSE0;
3440}
3441
3442static int
3443XineramaWarpPointer(ClientPtr client)
3444{
3445 WindowPtr dest = NULL((void*)0);
3446 int x, y, rc;
3447 SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
3448
3449 REQUEST(xWarpPointerReq)xWarpPointerReq *stuff = (xWarpPointerReq *)client->requestBuffer;
3450
3451 if (stuff->dstWid != None0L) {
3452 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess(1<<0));
3453 if (rc != Success0)
3454 return rc;
3455 }
3456 x = pSprite->hotPhys.x;
3457 y = pSprite->hotPhys.y;
3458
3459 if (stuff->srcWid != None0L) {
3460 int winX, winY;
3461 XID winID = stuff->srcWid;
3462 WindowPtr source;
3463
3464 rc = dixLookupWindow(&source, winID, client, DixReadAccess(1<<0));
3465 if (rc != Success0)
3466 return rc;
3467
3468 winX = source->drawable.x;
3469 winY = source->drawable.y;
3470 if (source == screenInfo.screens[0]->root) {
3471 winX -= screenInfo.screens[0]->x;
3472 winY -= screenInfo.screens[0]->y;
3473 }
3474 if (x < winX + stuff->srcX ||
3475 y < winY + stuff->srcY ||
3476 (stuff->srcWidth != 0 &&
3477 winX + stuff->srcX + (int) stuff->srcWidth < x) ||
3478 (stuff->srcHeight != 0 &&
3479 winY + stuff->srcY + (int) stuff->srcHeight < y) ||
3480 !XineramaPointInWindowIsVisible(source, x, y))
3481 return Success0;
3482 }
3483 if (dest) {
3484 x = dest->drawable.x;
3485 y = dest->drawable.y;
3486 if (dest == screenInfo.screens[0]->root) {
3487 x -= screenInfo.screens[0]->x;
3488 y -= screenInfo.screens[0]->y;
3489 }
3490 }
3491
3492 x += stuff->dstX;
3493 y += stuff->dstY;
3494
3495 if (x < pSprite->physLimits.x1)
3496 x = pSprite->physLimits.x1;
3497 else if (x >= pSprite->physLimits.x2)
3498 x = pSprite->physLimits.x2 - 1;
3499 if (y < pSprite->physLimits.y1)
3500 y = pSprite->physLimits.y1;
3501 else if (y >= pSprite->physLimits.y2)
3502 y = pSprite->physLimits.y2 - 1;
3503 if (pSprite->hotShape)
3504 ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
3505
3506 XineramaSetCursorPosition(PickPointer(client), x, y, TRUE1);
3507
3508 return Success0;
3509}
3510
3511#endif
3512
3513/**
3514 * Server-side protocol handling for WarpPointer request.
3515 * Warps the cursor position to the coordinates given in the request.
3516 */
3517int
3518ProcWarpPointer(ClientPtr client)
3519{
3520 WindowPtr dest = NULL((void*)0);
3521 int x, y, rc;
3522 ScreenPtr newScreen;
3523 DeviceIntPtr dev, tmp;
3524 SpritePtr pSprite;
3525
3526 REQUEST(xWarpPointerReq)xWarpPointerReq *stuff = (xWarpPointerReq *)client->requestBuffer;
3527 REQUEST_SIZE_MATCH(xWarpPointerReq)if ((sizeof(xWarpPointerReq) >> 2) != client->req_len
) return(16)
;
3528
3529 dev = PickPointer(client);
3530
3531 for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
3532 if (GetMaster(tmp, MASTER_ATTACHED4) == dev) {
3533 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, DixWriteAccess(1<<1));
3534 if (rc != Success0)
3535 return rc;
3536 }
3537 }
3538
3539 if (dev->lastSlave)
3540 dev = dev->lastSlave;
3541 pSprite = dev->spriteInfo->sprite;
3542
3543#ifdef PANORAMIX1
3544 if (!noPanoramiXExtension)
3545 return XineramaWarpPointer(client);
3546#endif
3547
3548 if (stuff->dstWid != None0L) {
3549 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess(1<<4));
3550 if (rc != Success0)
3551 return rc;
3552 }
3553 x = pSprite->hotPhys.x;
3554 y = pSprite->hotPhys.y;
3555
3556 if (stuff->srcWid != None0L) {
3557 int winX, winY;
3558 XID winID = stuff->srcWid;
3559 WindowPtr source;
3560
3561 rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess(1<<4));
3562 if (rc != Success0)
3563 return rc;
3564
3565 winX = source->drawable.x;
3566 winY = source->drawable.y;
3567 if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
3568 x < winX + stuff->srcX ||
3569 y < winY + stuff->srcY ||
3570 (stuff->srcWidth != 0 &&
3571 winX + stuff->srcX + (int) stuff->srcWidth < x) ||
3572 (stuff->srcHeight != 0 &&
3573 winY + stuff->srcY + (int) stuff->srcHeight < y) ||
3574 !PointInWindowIsVisible(source, x, y))
3575 return Success0;
3576 }
3577 if (dest) {
3578 x = dest->drawable.x;
3579 y = dest->drawable.y;
3580 newScreen = dest->drawable.pScreen;
3581 }
3582 else
3583 newScreen = pSprite->hotPhys.pScreen;
3584
3585 x += stuff->dstX;
3586 y += stuff->dstY;
3587
3588 if (x < 0)
3589 x = 0;
3590 else if (x >= newScreen->width)
3591 x = newScreen->width - 1;
3592 if (y < 0)
3593 y = 0;
3594 else if (y >= newScreen->height)
3595 y = newScreen->height - 1;
3596
3597 if (newScreen == pSprite->hotPhys.pScreen) {
3598 if (x < pSprite->physLimits.x1)
3599 x = pSprite->physLimits.x1;
3600 else if (x >= pSprite->physLimits.x2)
3601 x = pSprite->physLimits.x2 - 1;
3602 if (y < pSprite->physLimits.y1)
3603 y = pSprite->physLimits.y1;
3604 else if (y >= pSprite->physLimits.y2)
3605 y = pSprite->physLimits.y2 - 1;
3606 if (pSprite->hotShape)
3607 ConfineToShape(dev, pSprite->hotShape, &x, &y);
3608 (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE1);
3609 }
3610 else if (!PointerConfinedToScreen(dev)) {
3611 NewCurrentScreen(dev, newScreen, x, y);
3612 }
3613 return Success0;
3614}
3615
3616static Bool
3617BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
3618{
3619 if (RegionNotEmpty(&pWin->borderSize))
3620 return TRUE1;
3621
3622#ifdef PANORAMIX1
3623 if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
3624 int i;
3625
3626 FOR_NSCREENS_FORWARD_SKIP(i)for(i = 1; i < PanoramiXNumScreens; i++) {
3627 if (RegionNotEmpty
3628 (&pDev->spriteInfo->sprite->windows[i]->borderSize))
3629 return TRUE1;
3630 }
3631 }
3632#endif
3633 return FALSE0;
3634}
3635
3636/**
3637 * Activate the given passive grab. If the grab is activated successfully, the
3638 * event has been delivered to the client.
3639 *
3640 * @param device The device of the event to check.
3641 * @param grab The grab to check.
3642 * @param event The current device event.
3643 * @param real_event The original event, in case of touch emulation. The
3644 * real event is the one stored in the sync queue.
3645 *
3646 * @return Whether the grab has been activated.
3647 */
3648Bool
3649ActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3650 InternalEvent *real_event)
3651{
3652 SpritePtr pSprite = device->spriteInfo->sprite;
3653 GrabInfoPtr grabinfo = &device->deviceGrab;
3654 xEvent *xE = NULL((void*)0);
3655 int count;
3656 int rc;
3657
3658 /* The only consumers of corestate are Xi 1.x and core events, which
3659 * are guaranteed to come from DeviceEvents. */
3660 if (grab->grabtype == XI || grab->grabtype == CORE) {
3661 DeviceIntPtr gdev;
3662
3663 event->device_event.corestate &= 0x1f00;
3664
3665 if (grab->grabtype == CORE)
3666 gdev = GetMaster(device, KEYBOARD_OR_FLOAT5);
3667 else
3668 gdev = grab->modifierDevice;
3669
3670 if (gdev && gdev->key && gdev->key->xkbInfo)
3671 event->device_event.corestate |=
3672 gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
3673 }
3674
3675 if (grab->grabtype == CORE) {
3676 rc = EventToCore(event, &xE, &count);
3677 if (rc != Success0) {
3678 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", 3679
, __func__); if (1) ErrorFSigSafe("[dix] %s: core conversion failed"
"(%d, %d).\n", device->name, event->any.type, rc); xorg_backtrace
(); } } while(0)
3679 "(%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", 3679
, __func__); if (1) ErrorFSigSafe("[dix] %s: core conversion failed"
"(%d, %d).\n", device->name, event->any.type, rc); xorg_backtrace
(); } } while(0)
;
3680 return FALSE0;
3681 }
3682 }
3683 else if (grab->grabtype == XI2) {
3684 rc = EventToXI2(event, &xE);
3685 if (rc != Success0) {
3686 if (rc != BadMatch8)
3687 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", 3688
, __func__); if (1) ErrorFSigSafe("[dix] %s: XI2 conversion failed"
"(%d, %d).\n", device->name, event->any.type, rc); xorg_backtrace
(); } } while(0)
3688 "(%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", 3688
, __func__); if (1) ErrorFSigSafe("[dix] %s: XI2 conversion failed"
"(%d, %d).\n", device->name, event->any.type, rc); xorg_backtrace
(); } } while(0)
;
3689 return FALSE0;
3690 }
3691 count = 1;
3692 }
3693 else {
3694 rc = EventToXI(event, &xE, &count);
3695 if (rc != Success0) {
3696 if (rc != BadMatch8)
3697 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", 3698
, __func__); if (1) ErrorFSigSafe("[dix] %s: XI conversion failed"
"(%d, %d).\n", device->name, event->any.type, rc); xorg_backtrace
(); } } while(0)
3698 "(%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", 3698
, __func__); if (1) ErrorFSigSafe("[dix] %s: XI conversion failed"
"(%d, %d).\n", device->name, event->any.type, rc); xorg_backtrace
(); } } while(0)
;
3699 return FALSE0;
3700 }
3701 }
3702
3703 (*grabinfo->ActivateGrab) (device, grab,
3704 ClientTimeToServerTime(event->any.time), TRUE1);
3705
3706 if (xE) {
3707 FixUpEventFromWindow(pSprite, xE, grab->window, None0L, TRUE1);
3708
3709 /* XXX: XACE? */
3710 TryClientEvents(rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, device, xE, count,
3711 GetEventFilter(device, xE),
3712 GetEventFilter(device, xE), grab);
3713 }
3714
3715 if (grabinfo->sync.state == FROZEN_NO_EVENT5)
3716 grabinfo->sync.state = FROZEN_WITH_EVENT6;
3717 *grabinfo->sync.event = real_event->device_event;
3718
3719 free(xE);
3720 return TRUE1;
3721}
3722
3723static BOOL
3724CoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
3725{
3726 DeviceIntPtr other;
3727 BOOL interfering = FALSE0;
3728
3729 for (other = inputInfo.devices; other; other = other->next) {
3730 GrabPtr othergrab = other->deviceGrab.grab;
3731
3732 if (othergrab && othergrab->grabtype == CORE &&
3733 SameClient(grab, rClient(othergrab))((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == ((clients[
((int)((((othergrab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))]))->clientAsMask)
&&
3734 ((IsPointerDevice(grab->device) &&
3735 IsPointerDevice(othergrab->device)) ||
3736 (IsKeyboardDevice(grab->device) &&
3737 IsKeyboardDevice(othergrab->device)))) {
3738 interfering = TRUE1;
3739 break;
3740 }
3741 }
3742
3743 return interfering;
3744}
3745
3746enum MatchFlags {
3747 NO_MATCH = 0x0,
3748 CORE_MATCH = 0x1,
3749 XI_MATCH = 0x2,
3750 XI2_MATCH = 0x4,
3751};
3752
3753/**
3754 * Match the grab against the temporary grab on the given input level.
3755 * Modifies the temporary grab pointer.
3756 *
3757 * @param grab The grab to match against
3758 * @param tmp The temporary grab to use for matching
3759 * @param level The input level we want to match on
3760 * @param event_type Wire protocol event type
3761 *
3762 * @return The respective matched flag or 0 for no match
3763 */
3764static enum MatchFlags
3765MatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level,
3766 int event_type)
3767{
3768 enum MatchFlags match;
3769 BOOL ignore_device = FALSE0;
3770 int grabtype;
3771 int evtype;
3772
3773 switch (level) {
3774 case XI2:
3775 grabtype = XI2;
3776 evtype = GetXI2Type(event_type);
3777 BUG_WARN(!evtype)do { if (!evtype) { ErrorFSigSafe("BUG: triggered 'if (" "!evtype"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "events.c", 3777
, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0)
;
3778 match = XI2_MATCH;
3779 break;
3780 case XI:
3781 grabtype = XI;
3782 evtype = GetXIType(event_type);
3783 match = XI_MATCH;
3784 break;
3785 case CORE:
3786 grabtype = CORE;
3787 evtype = GetCoreType(event_type);
3788 match = CORE_MATCH;
3789 ignore_device = TRUE1;
3790 break;
3791 default:
3792 return NO_MATCH;
3793 }
3794
3795 tmp->grabtype = grabtype;
3796 tmp->type = evtype;
3797
3798 if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
3799 return match;
3800
3801 return NO_MATCH;
3802}
3803
3804/**
3805 * Check an individual grab against an event to determine if a passive grab
3806 * should be activated.
3807 *
3808 * @param device The device of the event to check.
3809 * @param grab The grab to check.
3810 * @param event The current device event.
3811 * @param checkCore Check for core grabs too.
3812 * @param tempGrab A pre-allocated temporary grab record for matching. This
3813 * must have the window and device values filled in.
3814 *
3815 * @return Whether the grab matches the event.
3816 */
3817static Bool
3818CheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3819 Bool checkCore, GrabPtr tempGrab)
3820{
3821 DeviceIntPtr gdev;
3822 XkbSrvInfoPtr xkbi = NULL((void*)0);
3823 enum MatchFlags match = 0;
3824 int emulated_type = 0;
3825
3826 gdev = grab->modifierDevice;
3827 if (grab->grabtype == CORE) {
3828 gdev = GetMaster(device, KEYBOARD_OR_FLOAT5);
3829 }
3830 else if (grab->grabtype == XI2) {
3831 /* if the device is an attached slave device, gdev must be the
3832 * attached master keyboard. Since the slave may have been
3833 * reattached after the grab, the modifier device may not be the
3834 * same. */
3835 if (!IsMaster(grab->device) && !IsFloating(device))
3836 gdev = GetMaster(device, MASTER_KEYBOARD2);
3837 }
3838
3839 if (gdev && gdev->key)
3840 xkbi = gdev->key->xkbInfo;
3841 tempGrab->modifierDevice = grab->modifierDevice;
3842 tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
3843
3844 /* Check for XI2 and XI grabs first */
3845 match = MatchForType(grab, tempGrab, XI2, event->any.type);
3846
3847 if (!match && IsTouchEvent(event) &&
3848 (event->device_event.flags & TOUCH_POINTER_EMULATED(1 << 5))) {
3849 emulated_type = TouchGetPointerEventType(event);
3850 match = MatchForType(grab, tempGrab, XI2, emulated_type);
3851 }
3852
3853 if (!match)
3854 match = MatchForType(grab, tempGrab, XI, event->any.type);
3855
3856 if (!match && emulated_type)
3857 match = MatchForType(grab, tempGrab, XI, emulated_type);
3858
3859 if (!match && checkCore) {
3860 match = MatchForType(grab, tempGrab, CORE, event->any.type);
3861 if (!match && emulated_type)
3862 match = MatchForType(grab, tempGrab, CORE, emulated_type);
3863 }
3864
3865 if (!match || (grab->confineTo &&
3866 (!grab->confineTo->realized ||
3867 !BorderSizeNotEmpty(device, grab->confineTo))))
3868 return FALSE0;
3869
3870 /* In some cases a passive core grab may exist, but the client
3871 * already has a core grab on some other device. In this case we
3872 * must not get the grab, otherwise we may never ungrab the
3873 * device.
3874 */
3875
3876 if (grab->grabtype == CORE) {
3877 /* A passive grab may have been created for a different device
3878 than it is assigned to at this point in time.
3879 Update the grab's device and modifier device to reflect the
3880 current state.
3881 Since XGrabDeviceButton requires to specify the
3882 modifierDevice explicitly, we don't override this choice.
3883 */
3884 if (grab->type < GenericEvent35) {
3885 grab->device = device;
3886 grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD2);
3887 }
3888
3889 if (CoreGrabInterferes(device, grab))
3890 return FALSE0;
3891 }
3892
3893 return TRUE1;
3894}
3895
3896/**
3897 * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
3898 * passive grab set on the window to be activated.
3899 * If activate is true and a passive grab is found, it will be activated,
3900 * and the event will be delivered to the client.
3901 *
3902 * @param pWin The window that may be subject to a passive grab.
3903 * @param device Device that caused the event.
3904 * @param event The current device event.
3905 * @param checkCore Check for core grabs too.
3906 * @param activate If a grab is found, activate it and deliver the event.
3907 */
3908
3909GrabPtr
3910CheckPassiveGrabsOnWindow(WindowPtr pWin,
3911 DeviceIntPtr device,
3912 InternalEvent *event, BOOL checkCore, BOOL activate)
3913{
3914 GrabPtr grab = wPassiveGrabs(pWin)((pWin)->optional ? (pWin)->optional->passiveGrabs :
((void*)0))
;
3915 GrabPtr tempGrab;
3916
3917 if (!grab)
3918 return NULL((void*)0);
3919
3920 tempGrab = AllocGrab(NULL((void*)0));
3921 if (tempGrab == NULL((void*)0))
3922 return NULL((void*)0);
3923
3924 /* Fill out the grab details, but leave the type for later before
3925 * comparing */
3926 switch (event->any.type) {
3927 case ET_KeyPress:
3928 case ET_KeyRelease:
3929 tempGrab->detail.exact = event->device_event.detail.key;
3930 break;
3931 case ET_ButtonPress:
3932 case ET_ButtonRelease:
3933 case ET_TouchBegin:
3934 case ET_TouchEnd:
3935 tempGrab->detail.exact = event->device_event.detail.button;
3936 break;
3937 default:
3938 tempGrab->detail.exact = 0;
3939 break;
3940 }
3941 tempGrab->window = pWin;
3942 tempGrab->device = device;
3943 tempGrab->detail.pMask = NULL((void*)0);
3944 tempGrab->modifiersDetail.pMask = NULL((void*)0);
3945 tempGrab->next = NULL((void*)0);
3946
3947 for (; grab; grab = grab->next) {
3948 if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
3949 continue;
3950
3951 if (activate && !ActivatePassiveGrab(device, grab, event, event))
3952 continue;
3953
3954 break;
3955 }
3956
3957 FreeGrab(tempGrab);
3958 return grab;
3959}
3960
3961/**
3962 * CheckDeviceGrabs handles both keyboard and pointer events that may cause
3963 * a passive grab to be activated.
3964 *
3965 * If the event is a keyboard event, the ancestors of the focus window are
3966 * traced down and tried to see if they have any passive grabs to be
3967 * activated. If the focus window itself is reached and it's descendants
3968 * contain the pointer, the ancestors of the window that the pointer is in
3969 * are then traced down starting at the focus window, otherwise no grabs are
3970 * activated.
3971 * If the event is a pointer event, the ancestors of the window that the
3972 * pointer is in are traced down starting at the root until CheckPassiveGrabs
3973 * causes a passive grab to activate or all the windows are
3974 * tried. PRH
3975 *
3976 * If a grab is activated, the event has been sent to the client already!
3977 *
3978 * The event we pass in must always be an XI event. From this, we then emulate
3979 * the core event and then check for grabs.
3980 *
3981 * @param device The device that caused the event.
3982 * @param xE The event to handle (Device{Button|Key}Press).
3983 * @param count Number of events in list.
3984 * @return TRUE if a grab has been activated or false otherwise.
3985*/
3986
3987Bool
3988CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
3989{
3990 int i;
3991 WindowPtr pWin = NULL((void*)0);
3992 FocusClassPtr focus =
3993 IsPointerEvent((InternalEvent *) event) ? NULL((void*)0) : device->focus;
3994 BOOL sendCore = (IsMaster(device) && device->coreEvents);
3995 Bool ret = FALSE0;
3996
3997 if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
3998 return FALSE0;
3999
4000 if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1))
4001 return FALSE0;
4002
4003 if (device->deviceGrab.grab)
4004 return FALSE0;
4005
4006 i = 0;
4007 if (ancestor) {
4008 while (i < device->spriteInfo->sprite->spriteTraceGood)
4009 if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
4010 break;
4011 if (i == device->spriteInfo->sprite->spriteTraceGood)
4012 goto out;
4013 }
4014
4015 if (focus) {
4016 for (; i < focus->traceGood; i++) {
4017 pWin = focus->trace[i];
4018 if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4019 sendCore, TRUE1)) {
4020 ret = TRUE1;
4021 goto out;
4022 }
4023 }
4024
4025 if ((focus->win == NoneWin((WindowPtr)0L)) ||
4026 (i >= device->spriteInfo->sprite->spriteTraceGood) ||
4027 (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1]))
4028 goto out;
4029 }
4030
4031 for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
4032 pWin = device->spriteInfo->sprite->spriteTrace[i];
4033 if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4034 sendCore, TRUE1)) {
4035 ret = TRUE1;
4036 goto out;
4037 }
4038 }
4039
4040 out:
4041 if (ret == TRUE1 && event->type == ET_KeyPress)
4042 device->deviceGrab.activatingKey = event->detail.key;
4043 return ret;
4044}
4045
4046/**
4047 * Called for keyboard events to deliver event to whatever client owns the
4048 * focus.
4049 *
4050 * The event is delivered to the keyboard's focus window, the root window or
4051 * to the window owning the input focus.
4052 *
4053 * @param keybd The keyboard originating the event.
4054 * @param event The event, not yet in wire format.
4055 * @param window Window underneath the sprite.
4056 */
4057void
4058DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
4059{
4060 DeviceIntPtr ptr;
4061 WindowPtr focus = keybd->focus->win;
4062 BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
4063 xEvent *core = NULL((void*)0), *xE = NULL((void*)0), *xi2 = NULL((void*)0);
4064 int count, rc;
4065 int deliveries = 0;
4066
4067 if (focus == FollowKeyboardWin((WindowPtr) 3))
4068 focus = inputInfo.keyboard->focus->win;
4069 if (!focus)
4070 return;
4071 if (focus == PointerRootWin((WindowPtr)1L)) {
4072 DeliverDeviceEvents(window, event, NullGrab((GrabPtr)((void*)0)), NullWindow((WindowPtr) 0), keybd);
4073 return;
4074 }
4075 if ((focus == window) || IsParent(focus, window)) {
4076 if (DeliverDeviceEvents(window, event, NullGrab((GrabPtr)((void*)0)), focus, keybd))
4077 return;
4078 }
4079
4080 /* just deliver it to the focus window */
4081 ptr = GetMaster(keybd, POINTER_OR_FLOAT6);
4082
4083 rc = EventToXI2(event, &xi2);
4084 if (rc == Success0) {
4085 /* XXX: XACE */
4086 int filter = GetEventFilter(keybd, xi2);
4087
4088 FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None0L, FALSE0);
4089 deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
4090 filter, NullGrab((GrabPtr)((void*)0)));
4091 if (deliveries > 0)
4092 goto unwind;
4093 }
4094 else if (rc != BadMatch8)
4095 ErrorF
4096 ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
4097 keybd->name, event->any.type, rc);
4098
4099 rc = EventToXI(event, &xE, &count);
4100 if (rc == Success0 &&
4101 XaceHook(XACE_SEND_ACCESS5, NULL((void*)0), keybd, focus, xE, count) == Success0) {
4102 FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None0L, FALSE0);
4103 deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
4104 GetEventFilter(keybd, xE), NullGrab((GrabPtr)((void*)0)));
4105
4106 if (deliveries > 0)
4107 goto unwind;
4108 }
4109 else if (rc != BadMatch8)
4110 ErrorF
4111 ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
4112 keybd->name, event->any.type, rc);
4113
4114 if (sendCore) {
4115 rc = EventToCore(event, &core, &count);
4116 if (rc == Success0) {
4117 if (XaceHook(XACE_SEND_ACCESS5, NULL((void*)0), keybd, focus, core, count) ==
4118 Success0) {
4119 FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
4120 None0L, FALSE0);
4121 deliveries =
Value stored to 'deliveries' is never read
4122 DeliverEventsToWindow(keybd, focus, core, count,
4123 GetEventFilter(keybd, core),
4124 NullGrab((GrabPtr)((void*)0)));
4125 }
4126 }
4127 else if (rc != BadMatch8)
4128 ErrorF
4129 ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
4130 keybd->name, event->any.type, rc);
4131 }
4132
4133 unwind:
4134 free(core);
4135 free(xE);
4136 free(xi2);
4137 return;
4138}
4139
4140int
4141DeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev,
4142 enum InputLevel level)
4143{
4144 SpritePtr pSprite = dev->spriteInfo->sprite;
4145 int rc;
4146 xEvent *xE = NULL((void*)0);
4147 int count = 0;
4148 int deliveries = 0;
4149 Mask mask;
4150 GrabInfoPtr grabinfo = &dev->deviceGrab;
4151 GrabPtr grab = grabinfo->grab;
4152 Mask filter;
4153
4154 if (grab->grabtype != level)
4155 return 0;
4156
4157 switch (level) {
4158 case XI2:
4159 rc = EventToXI2(event, &xE);
4160 count = 1;
4161 if (rc == Success0) {
4162 int evtype = xi2_get_type(xE);
4163
4164 mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
4165 filter = GetEventFilter(dev, xE);
4166 }
4167 break;
4168 case XI:
4169 if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
4170 mask = grab->deviceMask;
4171 else
4172 mask = grab->eventMask;
4173 rc = EventToXI(event, &xE, &count);
4174 if (rc == Success0)
4175 filter = GetEventFilter(dev, xE);
4176 break;
4177 case CORE:
4178 rc = EventToCore(event, &xE, &count);
4179 mask = grab->eventMask;
4180 if (rc == Success0)
4181 filter = GetEventFilter(dev, xE);
4182 break;
4183 default:
4184 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", 4184, __func__
); if (1) ErrorFSigSafe("Invalid input level %d\n", level); xorg_backtrace
(); } } while(0)
;
4185 return 0;
4186 }
4187
4188 if (rc == Success0) {
4189 FixUpEventFromWindow(pSprite, xE, grab->window, None0L, TRUE1);
4190 if (XaceHook(XACE_SEND_ACCESS5, 0, dev,
4191 grab->window, xE, count) ||
4192 XaceHook(XACE_RECEIVE_ACCESS6, rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
,
4193 grab->window, xE, count))
4194 deliveries = 1; /* don't send, but pretend we did */
4195 else if (level != CORE || !IsInterferingGrab(rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, dev, xE)) {
4196 deliveries = TryClientEvents(rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, dev,
4197 xE, count, mask, filter, grab);
4198 }
4199 }
4200 else
4201 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", 4203
, __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 "%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", 4203
, __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)
4203 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", 4203
, __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)
;
4204
4205 free(xE);
4206 return deliveries;
4207}
4208
4209/**
4210 * Deliver an event from a device that is currently grabbed. Uses
4211 * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
4212 * grab. If not, TryClientEvents() is used.
4213 *
4214 * @param deactivateGrab True if the device's grab should be deactivated.
4215 *
4216 * @return The number of events delivered.
4217 */
4218int
4219DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
4220 Bool deactivateGrab)
4221{
4222 GrabPtr grab;
4223 GrabInfoPtr grabinfo;
4224 int deliveries = 0;
4225 DeviceIntPtr dev;
4226 SpritePtr pSprite = thisDev->spriteInfo->sprite;
4227 BOOL sendCore = FALSE0;
4228
4229 grabinfo = &thisDev->deviceGrab;
4230 grab = grabinfo->grab;
4231
4232 if (grab->ownerEvents) {
4233 WindowPtr focus;
4234
4235 /* Hack: Some pointer device have a focus class. So we need to check
4236 * for the type of event, to see if we really want to deliver it to
4237 * the focus window. For pointer events, the answer is no.
4238 */
4239 if (IsPointerEvent(event))
4240 focus = PointerRootWin((WindowPtr)1L);
4241 else if (thisDev->focus) {
4242 focus = thisDev->focus->win;
4243 if (focus == FollowKeyboardWin((WindowPtr) 3))
4244 focus = inputInfo.keyboard->focus->win;
4245 }
4246 else
4247 focus = PointerRootWin((WindowPtr)1L);
4248 if (focus == PointerRootWin((WindowPtr)1L))
4249 deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
4250 NullWindow((WindowPtr) 0), thisDev);
4251 else if (focus && (focus == pSprite->win ||
4252 IsParent(focus, pSprite->win)))
4253 deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
4254 thisDev);
4255 else if (focus)
4256 deliveries = DeliverDeviceEvents(focus, event, grab, focus,
4257 thisDev);
4258 }
4259 if (!deliveries) {
4260 sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
4261 /* try core event */
4262 if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
4263 deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype);
4264
4265 if (deliveries && (event->any.type == ET_Motion))
4266 thisDev->valuator->motionHintWindow = grab->window;
4267 }
4268 if (deliveries && !deactivateGrab &&
4269 (event->any.type == ET_KeyPress ||
4270 event->any.type == ET_KeyRelease ||
4271 event->any.type == ET_ButtonPress ||
4272 event->any.type == ET_ButtonRelease)) {
4273 switch (grabinfo->sync.state) {
4274 case FREEZE_BOTH_NEXT_EVENT4:
4275 dev = GetPairedDevice(thisDev);
4276 if (dev) {
4277 FreezeThaw(dev, TRUE1);
4278 if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT4) &&
4279 (CLIENT_BITS(grab->resource)((grab->resource) & (((1 << ResourceClientBits()
) - 1) << (29 - ResourceClientBits())))
==
4280 CLIENT_BITS(dev->deviceGrab.grab->resource)((dev->deviceGrab.grab->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits())))
))
4281 dev->deviceGrab.sync.state = FROZEN_NO_EVENT5;
4282 else
4283 dev->deviceGrab.sync.other = grab;
4284 }
4285 /* fall through */
4286 case FREEZE_NEXT_EVENT3:
4287 grabinfo->sync.state = FROZEN_WITH_EVENT6;
4288 FreezeThaw(thisDev, TRUE1);
4289 *grabinfo->sync.event = event->device_event;
4290 break;
4291 }
4292 }
4293
4294 return deliveries;
4295}
4296
4297/* This function is used to set the key pressed or key released state -
4298 this is only used when the pressing of keys does not cause
4299 the device's processInputProc to be called, as in for example Mouse Keys.
4300*/
4301void
4302FixKeyState(DeviceEvent *event, DeviceIntPtr keybd)
4303{
4304 int key = event->detail.key;
4305
4306 if (event->type == ET_KeyPress) {
4307 DebugF("FixKeyState: Key %d %s\n", key,
4308 ((event->type == ET_KeyPress) ? "down" : "up"));
4309 }
4310
4311 if (event->type == ET_KeyPress)
4312 set_key_down(keybd, key, KEY_PROCESSED1);
4313 else if (event->type == ET_KeyRelease)
4314 set_key_up(keybd, key, KEY_PROCESSED1);
4315 else
4316 FatalError("Impossible keyboard event");
4317}
4318
4319#define AtMostOneClient((1L<<20) | (1L<<18) | (1L<<2)) \
4320 (SubstructureRedirectMask(1L<<20) | ResizeRedirectMask(1L<<18) | ButtonPressMask(1L<<2))
4321#define ManagerMask((1L<<20) | (1L<<18)) \
4322 (SubstructureRedirectMask(1L<<20) | ResizeRedirectMask(1L<<18))
4323
4324/**
4325 * Recalculate which events may be deliverable for the given window.
4326 * Recalculated mask is used for quicker determination which events may be
4327 * delivered to a window.
4328 *
4329 * The otherEventMasks on a WindowOptional is the combination of all event
4330 * masks set by all clients on the window.
4331 * deliverableEventMask is the combination of the eventMask and the
4332 * otherEventMask plus the events that may be propagated to the parent.
4333 *
4334 * Traverses to siblings and parents of the window.
4335 */
4336void
4337RecalculateDeliverableEvents(WindowPtr pWin)
4338{
4339 OtherClients *others;
4340 WindowPtr pChild;
4341
4342 pChild = pWin;
4343 while (1) {
4344 if (pChild->optional) {
4345 pChild->optional->otherEventMasks = 0;
4346 for (others = wOtherClients(pChild)((pChild)->optional ? (pChild)->optional->otherClients
: ((void*)0))
; others; others = others->next) {
4347 pChild->optional->otherEventMasks |= others->mask;
4348 }
4349 }
4350 pChild->deliverableEvents = pChild->eventMask |
4351 wOtherEventMasks(pChild)((pChild)->optional ? (pChild)->optional->otherEventMasks
: 0)
;
4352 if (pChild->parent)
4353 pChild->deliverableEvents |=
4354 (pChild->parent->deliverableEvents &
4355 ~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) ) )
);
4356 if (pChild->firstChild) {
4357 pChild = pChild->firstChild;
4358 continue;
4359 }
4360 while (!pChild->nextSib && (pChild != pWin))
4361 pChild = pChild->parent;
4362 if (pChild == pWin)
4363 break;
4364 pChild = pChild->nextSib;
4365 }
4366}
4367
4368/**
4369 *
4370 * \param value must conform to DeleteType
4371 */
4372int
4373OtherClientGone(void *value, XID id)
4374{
4375 OtherClientsPtr other, prev;
4376 WindowPtr pWin = (WindowPtr) value;
4377
4378 prev = 0;
4379 for (other = wOtherClients(pWin)((pWin)->optional ? (pWin)->optional->otherClients :
((void*)0))
; other; other = other->next) {
4380 if (other->resource == id) {
4381 if (prev)
4382 prev->next = other->next;
4383 else {
4384 if (!(pWin->optional->otherClients = other->next))
4385 CheckWindowOptionalNeed(pWin);
4386 }
4387 free(other);
4388 RecalculateDeliverableEvents(pWin);
4389 return Success0;
4390 }
4391 prev = other;
4392 }
4393 FatalError("client not on event list");
4394}
4395
4396int
4397EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
4398{
4399 Mask check;
4400 OtherClients *others;
4401 DeviceIntPtr dev;
4402 int rc;
4403
4404 if (mask & ~AllEventMasks((1L<<24)|((1L<<24)-1))) {
4405 client->errorValue = mask;
4406 return BadValue2;
4407 }
4408 check = (mask & ManagerMask((1L<<20) | (1L<<18)));
4409 if (check) {
4410 rc = XaceHook(XACE_RESOURCE_ACCESS2, client, pWin->drawable.id,
4411 RT_WINDOW((RESTYPE)1|((RESTYPE)1<<30)), pWin, RT_NONE((RESTYPE)0), NULL((void*)0), DixManageAccess(1<<25));
4412 if (rc != Success0)
4413 return rc;
4414 }
4415 check = (mask & AtMostOneClient((1L<<20) | (1L<<18) | (1L<<2)));
4416 if (check & (pWin->eventMask | wOtherEventMasks(pWin)((pWin)->optional ? (pWin)->optional->otherEventMasks
: 0)
)) {
4417 /* It is illegal for two different clients to select on any of the
4418 events for AtMostOneClient. However, it is OK, for some client to
4419 continue selecting on one of those events. */
4420 if ((wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
!= client) && (check & pWin->eventMask))
4421 return BadAccess10;
4422 for (others = wOtherClients(pWin)((pWin)->optional ? (pWin)->optional->otherClients :
((void*)0))
; others; others = others->next) {
4423 if (!SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
&& (check & others->mask))
4424 return BadAccess10;
4425 }
4426 }
4427 if (wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
== client) {
4428 check = pWin->eventMask;
4429 pWin->eventMask = mask;
4430 }
4431 else {
4432 for (others = wOtherClients(pWin)((pWin)->optional ? (pWin)->optional->otherClients :
((void*)0))
; others; others = others->next) {
4433 if (SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
) {
4434 check = others->mask;
4435 if (mask == 0) {
4436 FreeResource(others->resource, RT_NONE((RESTYPE)0));
4437 return Success0;
4438 }
4439 else
4440 others->mask = mask;
4441 goto maskSet;
4442 }
4443 }
4444 check = 0;
4445 if (!pWin->optional && !MakeWindowOptional(pWin))
4446 return BadAlloc11;
4447 others = malloc(sizeof(OtherClients));
4448 if (!others)
4449 return BadAlloc11;
4450 others->mask = mask;
4451 others->resource = FakeClientID(client->index);
4452 others->next = pWin->optional->otherClients;
4453 pWin->optional->otherClients = others;
4454 if (!AddResourceDarwin_X_AddResource(others->resource, RT_OTHERCLIENT((RESTYPE)8|((RESTYPE)1<<29)), (void *) pWin))
4455 return BadAlloc11;
4456 }
4457 maskSet:
4458 if ((mask & PointerMotionHintMask(1L<<7)) && !(check & PointerMotionHintMask(1L<<7))) {
4459 for (dev = inputInfo.devices; dev; dev = dev->next) {
4460 if (dev->valuator && dev->valuator->motionHintWindow == pWin)
4461 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
4462 }
4463 }
4464 RecalculateDeliverableEvents(pWin);
4465 return Success0;
4466}
4467
4468int
4469EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
4470 Mask mask, Bool *checkOptional)
4471{
4472 int i, freed;
4473
4474 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) ) )
) {
4475 client->errorValue = mask;
4476 return BadValue2;
4477 }
4478 if (pWin->dontPropagate)
4479 DontPropagateRefCnts[pWin->dontPropagate]--;
4480 if (!mask)
4481 i = 0;
4482 else {
4483 for (i = DNPMCOUNT8, freed = 0; --i > 0;) {
4484 if (!DontPropagateRefCnts[i])
4485 freed = i;
4486 else if (mask == DontPropagateMasks[i])
4487 break;
4488 }
4489 if (!i && freed) {
4490 i = freed;
4491 DontPropagateMasks[i] = mask;
4492 }
4493 }
4494 if (i || !mask) {
4495 pWin->dontPropagate = i;
4496 if (i)
4497 DontPropagateRefCnts[i]++;
4498 if (pWin->optional) {
4499 pWin->optional->dontPropagateMask = mask;
4500 *checkOptional = TRUE1;
4501 }
4502 }
4503 else {
4504 if (!pWin->optional && !MakeWindowOptional(pWin)) {
4505 if (pWin->dontPropagate)
4506 DontPropagateRefCnts[pWin->dontPropagate]++;
4507 return BadAlloc11;
4508 }
4509 pWin->dontPropagate = 0;
4510 pWin->optional->dontPropagateMask = mask;
4511 }
4512 RecalculateDeliverableEvents(pWin);
4513 return Success0;
4514}
4515
4516/**
4517 * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
4518 * Uses the paired keyboard to get some additional information.
4519 */
4520void
4521CoreEnterLeaveEvent(DeviceIntPtr mouse,
4522 int type,
4523 int mode, int detail, WindowPtr pWin, Window child)
4524{
4525 xEvent event = {
4526 .u.u.type = type,
4527 .u.u.detail = detail
4528 };
4529 WindowPtr focus;
4530 DeviceIntPtr keybd;
4531 GrabPtr grab = mouse->deviceGrab.grab;
4532 Mask mask;
4533
4534 keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT5);
4535
4536 if ((pWin == mouse->valuator->motionHintWindow) &&
4537 (detail != NotifyInferior2))
4538 mouse->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
4539 if (grab) {
4540 mask = (pWin == grab->window) ? grab->eventMask : 0;
4541 if (grab->ownerEvents)
4542 mask |= EventMaskForClient(pWin, rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
);
4543 }
4544 else {
4545 mask = pWin->eventMask | wOtherEventMasks(pWin)((pWin)->optional ? (pWin)->optional->otherEventMasks
: 0)
;
4546 }
4547
4548 event.u.enterLeave.time = currentTime.milliseconds;
4549 event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
4550 event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
4551 /* Counts on the same initial structure of crossing & button events! */
4552 FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None0L, FALSE0);
4553 /* Enter/Leave events always set child */
4554 event.u.enterLeave.child = child;
4555 event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
4556 ELFlagSameScreen(1<<1) : 0;
4557 event.u.enterLeave.state =
4558 mouse->button ? (mouse->button->state & 0x1f00) : 0;
4559 if (keybd)
4560 event.u.enterLeave.state |=
4561 XkbGrabStateFromRec(&keybd->key->xkbInfo->state)(((((&keybd->key->xkbInfo->state)->group)&
0x3)<<13)|(((&keybd->key->xkbInfo->state)->
grab_mods)&0xff))
;
4562 event.u.enterLeave.mode = mode;
4563 focus = (keybd) ? keybd->focus->win : None0L;
4564 if ((focus != NoneWin((WindowPtr)0L)) &&
4565 ((pWin == focus) || (focus == PointerRootWin((WindowPtr)1L)) || IsParent(focus, pWin)))
4566 event.u.enterLeave.flags |= ELFlagFocus(1<<0);
4567
4568 if ((mask & GetEventFilter(mouse, &event))) {
4569 if (grab)
4570 TryClientEvents(rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, mouse, &event, 1, mask,
4571 GetEventFilter(mouse, &event), grab);
4572 else
4573 DeliverEventsToWindow(mouse, pWin, &event, 1,
4574 GetEventFilter(mouse, &event), NullGrab((GrabPtr)((void*)0)));
4575 }
4576
4577 if ((type == EnterNotify7) && (mask & KeymapStateMask(1L<<14))) {
4578 xKeymapEvent ke = {
4579 .type = KeymapNotify11
4580 };
4581 ClientPtr client = grab ? rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
: wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
4582 int rc;
4583
4584 rc = XaceHook(XACE_DEVICE_ACCESS3, client, keybd, DixReadAccess(1<<0));
4585 if (rc == Success0)
4586 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))
;
4587
4588 if (grab)
4589 TryClientEvents(rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, keybd, (xEvent *) &ke, 1,
4590 mask, KeymapStateMask(1L<<14), grab);
4591 else
4592 DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1,
4593 KeymapStateMask(1L<<14), NullGrab((GrabPtr)((void*)0)));
4594 }
4595}
4596
4597void
4598DeviceEnterLeaveEvent(DeviceIntPtr mouse,
4599 int sourceid,
4600 int type,
4601 int mode, int detail, WindowPtr pWin, Window child)
4602{
4603 GrabPtr grab = mouse->deviceGrab.grab;
4604 xXIEnterEvent *event;
4605 WindowPtr focus;
4606 int filter;
4607 int btlen, len, i;
4608 DeviceIntPtr kbd;
4609
4610 if ((mode == XINotifyPassiveGrab4 && type == XI_Leave8) ||
4611 (mode == XINotifyPassiveUngrab5 && type == XI_Enter7))
4612 return;
4613
4614 btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
4615 btlen = bytes_to_int32(btlen);
4616 len = sizeof(xXIEnterEvent) + btlen * 4;
4617
4618 event = calloc(1, len);
4619 event->type = GenericEvent35;
4620 event->extension = IReqCode;
4621 event->evtype = type;
4622 event->length = (len - sizeof(xEvent)) / 4;
4623 event->buttons_len = btlen;
4624 event->detail = detail;
4625 event->time = currentTime.milliseconds;
4626 event->deviceid = mouse->id;
4627 event->sourceid = sourceid;
4628 event->mode = mode;
4629 event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x);
4630 event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y);
4631
4632 for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
4633 if (BitIsOn(mouse->button->down, i)(!!(((const BYTE *) (mouse->button->down))[(i)>>3
] & (1 << ((i) & 7))))
)
4634 SetBit(&event[1], i)(((BYTE *) (&event[1]))[(i)>>3] |= (1 << ((i)
& 7)))
;
4635
4636 kbd = GetMaster(mouse, MASTER_KEYBOARD2);
4637 if (kbd && kbd->key) {
4638 event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
4639 event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
4640 event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
4641
4642 event->group.base_group = kbd->key->xkbInfo->state.base_group;
4643 event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
4644 event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
4645 }
4646
4647 focus = (kbd) ? kbd->focus->win : None0L;
4648 if ((focus != NoneWin((WindowPtr)0L)) &&
4649 ((pWin == focus) || (focus == PointerRootWin((WindowPtr)1L)) || IsParent(focus, pWin)))
4650 event->focus = TRUE1;
4651
4652 FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
4653 None0L, FALSE0);
4654
4655 filter = GetEventFilter(mouse, (xEvent *) event);
4656
4657 if (grab && grab->grabtype == XI2) {
4658 Mask mask;
4659
4660 mask = xi2mask_isset(grab->xi2mask, mouse, type);
4661 TryClientEvents(rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
, mouse, (xEvent *) event, 1, mask, 1,
4662 grab);
4663 }
4664 else {
4665 if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event))
4666 goto out;
4667 DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter,
4668 NullGrab((GrabPtr)((void*)0)));
4669 }
4670
4671 out:
4672 free(event);
4673}
4674
4675void
4676CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
4677{
4678 xEvent event = {
4679 .u.u.type = type,
4680 .u.u.detail = detail
4681 };
4682 event.u.focus.mode = mode;
4683 event.u.focus.window = pWin->drawable.id;
4684
4685 DeliverEventsToWindow(dev, pWin, &event, 1,
4686 GetEventFilter(dev, &event), NullGrab((GrabPtr)((void*)0)));
4687 if ((type == FocusIn9) &&
4688 ((pWin->eventMask | wOtherEventMasks(pWin)((pWin)->optional ? (pWin)->optional->otherEventMasks
: 0)
) & KeymapStateMask(1L<<14))) {
4689 xKeymapEvent ke = {
4690 .type = KeymapNotify11
4691 };
4692 ClientPtr client = wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
4693 int rc;
4694
4695 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, DixReadAccess(1<<0));
4696 if (rc == Success0)
4697 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))
;
4698
4699 DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1,
4700 KeymapStateMask(1L<<14), NullGrab((GrabPtr)((void*)0)));
4701 }
4702}
4703
4704/**
4705 * Set the input focus to the given window. Subsequent keyboard events will be
4706 * delivered to the given window.
4707 *
4708 * Usually called from ProcSetInputFocus as result of a client request. If so,
4709 * the device is the inputInfo.keyboard.
4710 * If called from ProcXSetInputFocus as result of a client xinput request, the
4711 * device is set to the device specified by the client.
4712 *
4713 * @param client Client that requested input focus change.
4714 * @param dev Focus device.
4715 * @param focusID The window to obtain the focus. Can be PointerRoot or None.
4716 * @param revertTo Specifies where the focus reverts to when window becomes
4717 * unviewable.
4718 * @param ctime Specifies the time.
4719 * @param followOK True if pointer is allowed to follow the keyboard.
4720 */
4721int
4722SetInputFocus(ClientPtr client,
4723 DeviceIntPtr dev,
4724 Window focusID, CARD8 revertTo, Time ctime, Bool followOK)
4725{
4726 FocusClassPtr focus;
4727 WindowPtr focusWin;
4728 int mode, rc;
4729 TimeStamp time;
4730 DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
4731
4732 UpdateCurrentTime();
4733 if ((revertTo != RevertToParent2) &&
4734 (revertTo != RevertToPointerRoot(int)1L) &&
4735 (revertTo != RevertToNone(int)0L) &&
4736 ((revertTo != RevertToFollowKeyboard3) || !followOK)) {
4737 client->errorValue = revertTo;
4738 return BadValue2;
4739 }
4740 time = ClientTimeToServerTime(ctime);
4741
4742 keybd = GetMaster(dev, KEYBOARD_OR_FLOAT5);
4743
4744 if ((focusID == None0L) || (focusID == PointerRoot1L))
4745 focusWin = (WindowPtr) (long) focusID;
4746 else if ((focusID == FollowKeyboard3) && followOK) {
4747 focusWin = keybd->focus->win;
4748 }
4749 else {
4750 rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess(1<<5));
4751 if (rc != Success0)
4752 return rc;
4753 /* It is a match error to try to set the input focus to an
4754 unviewable window. */
4755 if (!focusWin->realized)
4756 return BadMatch8;
4757 }
4758 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, DixSetFocusAccess(1<<10));
4759 if (rc != Success0)
4760 return Success0;
4761
4762 focus = dev->focus;
4763 if ((CompareTimeStamps(time, currentTime) == LATER1) ||
4764 (CompareTimeStamps(time, focus->time) == EARLIER-1))
4765 return Success0;
4766 mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed3 : NotifyNormal0;
4767 if (focus->win == FollowKeyboardWin((WindowPtr) 3)) {
4768 if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
4769 DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
4770 }
4771 else {
4772 if (!ActivateFocusInGrab(dev, focus->win, focusWin))
4773 DoFocusEvents(dev, focus->win, focusWin, mode);
4774 }
4775 focus->time = time;
4776 focus->revert = revertTo;
4777 if (focusID == FollowKeyboard3)
4778 focus->win = FollowKeyboardWin((WindowPtr) 3);
4779 else
4780 focus->win = focusWin;
4781 if ((focusWin == NoneWin((WindowPtr)0L)) || (focusWin == PointerRootWin((WindowPtr)1L)))
4782 focus->traceGood = 0;
4783 else {
4784 int depth = 0;
4785 WindowPtr pWin;
4786
4787 for (pWin = focusWin; pWin; pWin = pWin->parent)
4788 depth++;
4789 if (depth > focus->traceSize) {
4790 focus->traceSize = depth + 1;
4791 focus->trace = reallocarrayxreallocarray(focus->trace, focus->traceSize,
4792 sizeof(WindowPtr));
4793 }
4794 focus->traceGood = depth;
4795 for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
4796 focus->trace[depth] = pWin;
4797 }
4798 return Success0;
4799}
4800
4801/**
4802 * Server-side protocol handling for SetInputFocus request.
4803 *
4804 * Sets the input focus for the virtual core keyboard.
4805 */
4806int
4807ProcSetInputFocus(ClientPtr client)
4808{
4809 DeviceIntPtr kbd = PickKeyboard(client);
4810
4811 REQUEST(xSetInputFocusReq)xSetInputFocusReq *stuff = (xSetInputFocusReq *)client->requestBuffer;
4812
4813 REQUEST_SIZE_MATCH(xSetInputFocusReq)if ((sizeof(xSetInputFocusReq) >> 2) != client->req_len
) return(16)
;
4814
4815 return SetInputFocus(client, kbd, stuff->focus,
4816 stuff->revertTo, stuff->time, FALSE0);
4817}
4818
4819/**
4820 * Server-side protocol handling for GetInputFocus request.
4821 *
4822 * Sends the current input focus for the client's keyboard back to the
4823 * client.
4824 */
4825int
4826ProcGetInputFocus(ClientPtr client)
4827{
4828 DeviceIntPtr kbd = PickKeyboard(client);
4829 xGetInputFocusReply rep;
4830 FocusClassPtr focus = kbd->focus;
4831 int rc;
4832
4833 /* REQUEST(xReq); */
4834 REQUEST_SIZE_MATCH(xReq)if ((sizeof(xReq) >> 2) != client->req_len) return(16
)
;
4835
4836 rc = XaceHook(XACE_DEVICE_ACCESS3, client, kbd, DixGetFocusAccess(1<<9));
4837 if (rc != Success0)
4838 return rc;
4839
4840 rep = (xGetInputFocusReply) {
4841 .type = X_Reply1,
4842 .length = 0,
4843 .sequenceNumber = client->sequence,
4844 .revertTo = focus->revert
4845 };
4846
4847 if (focus->win == NoneWin((WindowPtr)0L))
4848 rep.focus = None0L;
4849 else if (focus->win == PointerRootWin((WindowPtr)1L))
4850 rep.focus = PointerRoot1L;
4851 else
4852 rep.focus = focus->win->drawable.id;
4853
4854 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)); }
;
4855 return Success0;
4856}
4857
4858/**
4859 * Server-side protocol handling for GrabPointer request.
4860 *
4861 * Sets an active grab on the client's ClientPointer and returns success
4862 * status to client.
4863 */
4864int
4865ProcGrabPointer(ClientPtr client)
4866{
4867 xGrabPointerReply rep;
4868 DeviceIntPtr device = PickPointer(client);
4869 GrabPtr grab;
4870 GrabMask mask;
4871 WindowPtr confineTo;
4872 BYTE status;
4873
4874 REQUEST(xGrabPointerReq)xGrabPointerReq *stuff = (xGrabPointerReq *)client->requestBuffer;
4875 int rc;
4876
4877 REQUEST_SIZE_MATCH(xGrabPointerReq)if ((sizeof(xGrabPointerReq) >> 2) != client->req_len
) return(16)
;
4878 UpdateCurrentTime();
4879
4880 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) ) )
) {
4881 client->errorValue = stuff->eventMask;
4882 return BadValue2;
4883 }
4884
4885 if (stuff->confineTo == None0L)
4886 confineTo = NullWindow((WindowPtr) 0);
4887 else {
4888 rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4889 DixSetAttrAccess(1<<5));
4890 if (rc != Success0)
4891 return rc;
4892 }
4893
4894 grab = device->deviceGrab.grab;
4895
4896 if (grab && grab->confineTo && !confineTo)
4897 ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE0, FALSE0);
4898
4899 mask.core = stuff->eventMask;
4900
4901 rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
4902 stuff->grabWindow, stuff->ownerEvents, stuff->time,
4903 &mask, CORE, stuff->cursor, stuff->confineTo, &status);
4904 if (rc != Success0)
4905 return rc;
4906
4907 rep = (xGrabPointerReply) {
4908 .type = X_Reply1,
4909 .status = status,
4910 .sequenceNumber = client->sequence,
4911 .length = 0
4912 };
4913 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)); }
;
4914 return Success0;
4915}
4916
4917/**
4918 * Server-side protocol handling for ChangeActivePointerGrab request.
4919 *
4920 * Changes properties of the grab hold by the client. If the client does not
4921 * hold an active grab on the device, nothing happens.
4922 */
4923int
4924ProcChangeActivePointerGrab(ClientPtr client)
4925{
4926 DeviceIntPtr device;
4927 GrabPtr grab;
4928 CursorPtr newCursor, oldCursor;
4929
4930 REQUEST(xChangeActivePointerGrabReq)xChangeActivePointerGrabReq *stuff = (xChangeActivePointerGrabReq
*)client->requestBuffer
;
4931 TimeStamp time;
4932
4933 REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq)if ((sizeof(xChangeActivePointerGrabReq) >> 2) != client
->req_len) return(16)
;
4934 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) ) )
) {
4935 client->errorValue = stuff->eventMask;
4936 return BadValue2;
4937 }
4938 if (stuff->cursor == None0L)
4939 newCursor = NullCursor((CursorPtr)((void*)0));
4940 else {
4941 int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor,
4942 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
4943
4944 if (rc != Success0) {
4945 client->errorValue = stuff->cursor;
4946 return rc;
4947 }
4948 }
4949
4950 device = PickPointer(client);
4951 grab = device->deviceGrab.grab;
4952
4953 if (!grab)
4954 return Success0;
4955 if (!SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
4956 return Success0;
4957 UpdateCurrentTime();
4958 time = ClientTimeToServerTime(stuff->time);
4959 if ((CompareTimeStamps(time, currentTime) == LATER1) ||
4960 (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER-1))
4961 return Success0;
4962 oldCursor = grab->cursor;
4963 grab->cursor = RefCursor(newCursor);
4964 PostNewCursor(device);
4965 if (oldCursor)
4966 FreeCursor(oldCursor, (Cursor) 0);
4967 grab->eventMask = stuff->eventMask;
4968 return Success0;
4969}
4970
4971/**
4972 * Server-side protocol handling for UngrabPointer request.
4973 *
4974 * Deletes a pointer grab on a device the client has grabbed.
4975 */
4976int
4977ProcUngrabPointer(ClientPtr client)
4978{
4979 DeviceIntPtr device = PickPointer(client);
4980 GrabPtr grab;
4981 TimeStamp time;
4982
4983 REQUEST(xResourceReq)xResourceReq *stuff = (xResourceReq *)client->requestBuffer;
4984
4985 REQUEST_SIZE_MATCH(xResourceReq)if ((sizeof(xResourceReq) >> 2) != client->req_len) return
(16)
;
4986 UpdateCurrentTime();
4987 grab = device->deviceGrab.grab;
4988
4989 time = ClientTimeToServerTime(stuff->id);
4990 if ((CompareTimeStamps(time, currentTime) != LATER1) &&
4991 (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER-1) &&
4992 (grab) && SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
4993 (*device->deviceGrab.DeactivateGrab) (device);
4994 return Success0;
4995}
4996
4997/**
4998 * Sets a grab on the given device.
4999 *
5000 * Called from ProcGrabKeyboard to work on the client's keyboard.
5001 * Called from ProcXGrabDevice to work on the device specified by the client.
5002 *
5003 * The parameters this_mode and other_mode represent the keyboard_mode and
5004 * pointer_mode parameters of XGrabKeyboard().
5005 * See man page for details on all the parameters
5006 *
5007 * @param client Client that owns the grab.
5008 * @param dev The device to grab.
5009 * @param this_mode GrabModeSync or GrabModeAsync
5010 * @param other_mode GrabModeSync or GrabModeAsync
5011 * @param status Return code to be returned to the caller.
5012 *
5013 * @returns Success or BadValue or BadAlloc.
5014 */
5015int
5016GrabDevice(ClientPtr client, DeviceIntPtr dev,
5017 unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
5018 unsigned ownerEvents, Time ctime, GrabMask *mask,
5019 int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
5020{
5021 WindowPtr pWin, confineTo;
5022 GrabPtr grab;
5023 TimeStamp time;
5024 Mask access_mode = DixGrabAccess(1<<17);
5025 int rc;
5026 GrabInfoPtr grabInfo = &dev->deviceGrab;
5027 CursorPtr cursor;
5028
5029 UpdateCurrentTime();
5030 if ((keyboard_mode != GrabModeSync0) && (keyboard_mode != GrabModeAsync1)) {
5031 client->errorValue = keyboard_mode;
5032 return BadValue2;
5033 }
5034 if ((pointer_mode != GrabModeSync0) && (pointer_mode != GrabModeAsync1)) {
5035 client->errorValue = pointer_mode;
5036 return BadValue2;
5037 }
5038 if ((ownerEvents != xFalse0) && (ownerEvents != xTrue1)) {
5039 client->errorValue = ownerEvents;
5040 return BadValue2;
5041 }
5042
5043 rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess(1<<5));
5044 if (rc != Success0)
5045 return rc;
5046
5047 if (confineToWin == None0L)
5048 confineTo = NullWindow((WindowPtr) 0);
5049 else {
5050 rc = dixLookupWindow(&confineTo, confineToWin, client,
5051 DixSetAttrAccess(1<<5));
5052 if (rc != Success0)
5053 return rc;
5054 }
5055
5056 if (curs == None0L)
5057 cursor = NullCursor((CursorPtr)((void*)0));
5058 else {
5059 rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR((RESTYPE)5),
5060 client, DixUseAccess(1<<24));
5061 if (rc != Success0) {
5062 client->errorValue = curs;
5063 return rc;
5064 }
5065 access_mode |= DixForceAccess(1<<19);
5066 }
5067
5068 if (keyboard_mode == GrabModeSync0 || pointer_mode == GrabModeSync0)
5069 access_mode |= DixFreezeAccess(1<<18);
5070 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
5071 if (rc != Success0)
5072 return rc;
5073
5074 time = ClientTimeToServerTime(ctime);
5075 grab = grabInfo->grab;
5076 if (grab && grab->grabtype != grabtype)
5077 *status = AlreadyGrabbed1;
5078 else if (grab && !SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
5079 *status = AlreadyGrabbed1;
5080 else if ((!pWin->realized) ||
5081 (confineTo &&
5082 !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo))))
5083 *status = GrabNotViewable3;
5084 else if ((CompareTimeStamps(time, currentTime) == LATER1) ||
5085 (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER-1))
5086 *status = GrabInvalidTime2;
5087 else if (grabInfo->sync.frozen &&
5088 grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)((((grabInfo->sync.other)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) == (client)->clientAsMask)
)
5089 *status = GrabFrozen4;
5090 else {
5091 GrabPtr tempGrab;
5092
5093 tempGrab = AllocGrab(NULL((void*)0));
5094 if (tempGrab == NULL((void*)0))
5095 return BadAlloc11;
5096
5097 tempGrab->next = NULL((void*)0);
5098 tempGrab->window = pWin;
5099 tempGrab->resource = client->clientAsMask;
5100 tempGrab->ownerEvents = ownerEvents;
5101 tempGrab->keyboardMode = keyboard_mode;
5102 tempGrab->pointerMode = pointer_mode;
5103 if (grabtype == CORE)
5104 tempGrab->eventMask = mask->core;
5105 else if (grabtype == XI)
5106 tempGrab->eventMask = mask->xi;
5107 else
5108 xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
5109 tempGrab->device = dev;
5110 tempGrab->cursor = RefCursor(cursor);
5111 tempGrab->confineTo = confineTo;
5112 tempGrab->grabtype = grabtype;
5113 (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE0);
5114 *status = GrabSuccess0;
5115
5116 FreeGrab(tempGrab);
5117 }
5118 return Success0;
5119}
5120
5121/**
5122 * Server-side protocol handling for GrabKeyboard request.
5123 *
5124 * Grabs the client's keyboard and returns success status to client.
5125 */
5126int
5127ProcGrabKeyboard(ClientPtr client)
5128{
5129 xGrabKeyboardReply rep;
5130 BYTE status;
5131
5132 REQUEST(xGrabKeyboardReq)xGrabKeyboardReq *stuff = (xGrabKeyboardReq *)client->requestBuffer;
5133 int result;
5134 DeviceIntPtr keyboard = PickKeyboard(client);
5135 GrabMask mask;
5136
5137 REQUEST_SIZE_MATCH(xGrabKeyboardReq)if ((sizeof(xGrabKeyboardReq) >> 2) != client->req_len
) return(16)
;
5138 UpdateCurrentTime();
5139
5140 mask.core = KeyPressMask(1L<<0) | KeyReleaseMask(1L<<1);
5141
5142 result = GrabDevice(client, keyboard, stuff->pointerMode,
5143 stuff->keyboardMode, stuff->grabWindow,
5144 stuff->ownerEvents, stuff->time, &mask, CORE, None0L,
5145 None0L, &status);
5146
5147 if (result != Success0)
5148 return result;
5149
5150 rep = (xGrabKeyboardReply) {
5151 .type = X_Reply1,
5152 .status = status,
5153 .sequenceNumber = client->sequence,
5154 .length = 0
5155 };
5156 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)); }
;
5157 return Success0;
5158}
5159
5160/**
5161 * Server-side protocol handling for UngrabKeyboard request.
5162 *
5163 * Deletes a possible grab on the client's keyboard.
5164 */
5165int
5166ProcUngrabKeyboard(ClientPtr client)
5167{
5168 DeviceIntPtr device = PickKeyboard(client);
5169 GrabPtr grab;
5170 TimeStamp time;
5171
5172 REQUEST(xResourceReq)xResourceReq *stuff = (xResourceReq *)client->requestBuffer;
5173
5174 REQUEST_SIZE_MATCH(xResourceReq)if ((sizeof(xResourceReq) >> 2) != client->req_len) return
(16)
;
5175 UpdateCurrentTime();
5176
5177 grab = device->deviceGrab.grab;
5178
5179 time = ClientTimeToServerTime(stuff->id);
5180 if ((CompareTimeStamps(time, currentTime) != LATER1) &&
5181 (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER-1) &&
5182 (grab) && SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
&& grab->grabtype == CORE)
5183 (*device->deviceGrab.DeactivateGrab) (device);
5184 return Success0;
5185}
5186
5187/**
5188 * Server-side protocol handling for QueryPointer request.
5189 *
5190 * Returns the current state and position of the client's ClientPointer to the
5191 * client.
5192 */
5193int
5194ProcQueryPointer(ClientPtr client)
5195{
5196 xQueryPointerReply rep;
5197 WindowPtr pWin, t;
5198 DeviceIntPtr mouse = PickPointer(client);
5199 DeviceIntPtr keyboard;
5200 SpritePtr pSprite;
5201 int rc;
5202
5203 REQUEST(xResourceReq)xResourceReq *stuff = (xResourceReq *)client->requestBuffer;
5204 REQUEST_SIZE_MATCH(xResourceReq)if ((sizeof(xResourceReq) >> 2) != client->req_len) return
(16)
;
5205
5206 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess(1<<4));
5207 if (rc != Success0)
5208 return rc;
5209 rc = XaceHook(XACE_DEVICE_ACCESS3, client, mouse, DixReadAccess(1<<0));
5210 if (rc != Success0 && rc != BadAccess10)
5211 return rc;
5212
5213 keyboard = GetMaster(mouse, MASTER_KEYBOARD2);
5214
5215 pSprite = mouse->spriteInfo->sprite;
5216 if (mouse->valuator->motionHintWindow)
5217 MaybeStopHint(mouse, client);
5218 rep = (xQueryPointerReply) {
5219 .type = X_Reply1,
5220 .sequenceNumber = client->sequence,
5221 .length = 0,
5222 .mask = event_get_corestate(mouse, keyboard),
5223 .root = (GetCurrentRootWindow(mouse))->drawable.id,
5224 .rootX = pSprite->hot.x,
5225 .rootY = pSprite->hot.y,
5226 .child = None0L
5227 };
5228 if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
5229 rep.sameScreen = xTrue1;
5230 rep.winX = pSprite->hot.x - pWin->drawable.x;
5231 rep.winY = pSprite->hot.y - pWin->drawable.y;
5232 for (t = pSprite->win; t; t = t->parent)
5233 if (t->parent == pWin) {
5234 rep.child = t->drawable.id;
5235 break;
5236 }
5237 }
5238 else {
5239 rep.sameScreen = xFalse0;
5240 rep.winX = 0;
5241 rep.winY = 0;
5242 }
5243
5244#ifdef PANORAMIX1
5245 if (!noPanoramiXExtension) {
5246 rep.rootX += screenInfo.screens[0]->x;
5247 rep.rootY += screenInfo.screens[0]->y;
5248 if (stuff->id == rep.root) {
5249 rep.winX += screenInfo.screens[0]->x;
5250 rep.winY += screenInfo.screens[0]->y;
5251 }
5252 }
5253#endif
5254
5255 if (rc == BadAccess10) {
5256 rep.mask = 0;
5257 rep.child = None0L;
5258 rep.rootX = 0;
5259 rep.rootY = 0;
5260 rep.winX = 0;
5261 rep.winY = 0;
5262 }
5263
5264 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)); }
;
5265
5266 return Success0;
5267}
5268
5269/**
5270 * Initializes the device list and the DIX sprite to sane values. Allocates
5271 * trace memory used for quick window traversal.
5272 */
5273void
5274InitEvents(void)
5275{
5276 int i;
5277 QdEventPtr qe, tmp;
5278
5279 inputInfo.numDevices = 0;
5280 inputInfo.devices = (DeviceIntPtr) NULL((void*)0);
5281 inputInfo.off_devices = (DeviceIntPtr) NULL((void*)0);
5282 inputInfo.keyboard = (DeviceIntPtr) NULL((void*)0);
5283 inputInfo.pointer = (DeviceIntPtr) NULL((void*)0);
5284
5285 for (i = 0; i < MAXDEVICES40; i++) {
5286 DeviceIntRec dummy;
5287 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))
;
5288
5289 dummy.id = i;
5290 NoticeTime(&dummy, currentTime);
5291 LastEventTimeToggleResetFlag(i, FALSE0);
5292 }
5293
5294 syncEvents.replayDev = (DeviceIntPtr) NULL((void*)0);
5295 syncEvents.replayWin = NullWindow((WindowPtr) 0);
5296 if (syncEvents.pending.next)
5297 xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)for (qe = ((void*)0), 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)))
5298 free(qe);
5299 xorg_list_init(&syncEvents.pending);
5300 syncEvents.playingEvents = FALSE0;
5301 syncEvents.time.months = 0;
5302 syncEvents.time.milliseconds = 0; /* hardly matters */
5303 currentTime.months = 0;
5304 currentTime.milliseconds = GetTimeInMillis();
5305 for (i = 0; i < DNPMCOUNT8; i++) {
5306 DontPropagateMasks[i] = 0;
5307 DontPropagateRefCnts[i] = 0;
5308 }
5309
5310 InputEventList = InitEventList(GetMaximumEventsNum());
5311 if (!InputEventList)
5312 FatalError("[dix] Failed to allocate input event list.\n");
5313}
5314
5315void
5316CloseDownEvents(void)
5317{
5318 FreeEventList(InputEventList, GetMaximumEventsNum());
5319 InputEventList = NULL((void*)0);
5320}
5321
5322#define SEND_EVENT_BIT0x80 0x80
5323
5324/**
5325 * Server-side protocol handling for SendEvent request.
5326 *
5327 * Locates the window to send the event to and forwards the event.
5328 */
5329int
5330ProcSendEvent(ClientPtr client)
5331{
5332 WindowPtr pWin;
5333 WindowPtr effectiveFocus = NullWindow((WindowPtr) 0); /* only set if dest==InputFocus */
5334 DeviceIntPtr dev = PickPointer(client);
5335 DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD2);
5336 SpritePtr pSprite = dev->spriteInfo->sprite;
5337
5338 REQUEST(xSendEventReq)xSendEventReq *stuff = (xSendEventReq *)client->requestBuffer;
5339
5340 REQUEST_SIZE_MATCH(xSendEventReq)if ((sizeof(xSendEventReq) >> 2) != client->req_len)
return(16)
;
5341
5342 /* libXext and other extension libraries may set the bit indicating
5343 * that this event came from a SendEvent request so remove it
5344 * since otherwise the event type may fail the range checks
5345 * and cause an invalid BadValue error to be returned.
5346 *
5347 * This is safe to do since we later add the SendEvent bit (0x80)
5348 * back in once we send the event to the client */
5349
5350 stuff->event.u.u.type &= ~(SEND_EVENT_BIT0x80);
5351
5352 /* The client's event type must be a core event type or one defined by an
5353 extension. */
5354
5355 if (!((stuff->event.u.u.type > X_Reply1 &&
5356 stuff->event.u.u.type < LASTEvent36) ||
5357 (stuff->event.u.u.type >= EXTENSION_EVENT_BASE64 &&
5358 stuff->event.u.u.type < (unsigned) lastEvent))) {
5359 client->errorValue = stuff->event.u.u.type;
5360 return BadValue2;
5361 }
5362 if (stuff->event.u.u.type == ClientMessage33 &&
5363 stuff->event.u.u.detail != 8 &&
5364 stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) {
5365 client->errorValue = stuff->event.u.u.detail;
5366 return BadValue2;
5367 }
5368 if (stuff->eventMask & ~AllEventMasks((1L<<24)|((1L<<24)-1))) {
5369 client->errorValue = stuff->eventMask;
5370 return BadValue2;
5371 }
5372
5373 if (stuff->destination == PointerWindow0L)
5374 pWin = pSprite->win;
5375 else if (stuff->destination == InputFocus1L) {
5376 WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin((WindowPtr)0L);
5377
5378 if (inputFocus == NoneWin((WindowPtr)0L))
5379 return Success0;
5380
5381 /* If the input focus is PointerRootWin, send the event to where
5382 the pointer is if possible, then perhaps propogate up to root. */
5383 if (inputFocus == PointerRootWin((WindowPtr)1L))
5384 inputFocus = GetCurrentRootWindow(dev);
5385
5386 if (IsParent(inputFocus, pSprite->win)) {
5387 effectiveFocus = inputFocus;
5388 pWin = pSprite->win;
5389 }
5390 else
5391 effectiveFocus = pWin = inputFocus;
5392 }
5393 else
5394 dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess(1<<22));
5395
5396 if (!pWin)
5397 return BadWindow3;
5398 if ((stuff->propagate != xFalse0) && (stuff->propagate != xTrue1)) {
5399 client->errorValue = stuff->propagate;
5400 return BadValue2;
5401 }
5402 stuff->event.u.u.type |= SEND_EVENT_BIT0x80;
5403 if (stuff->propagate) {
5404 for (; pWin; pWin = pWin->parent) {
5405 if (XaceHook(XACE_SEND_ACCESS5, client, NULL((void*)0), pWin,
5406 &stuff->event, 1))
5407 return Success0;
5408 if (DeliverEventsToWindow(dev, pWin,
5409 &stuff->event, 1, stuff->eventMask,
5410 NullGrab((GrabPtr)((void*)0))))
5411 return Success0;
5412 if (pWin == effectiveFocus)
5413 return Success0;
5414 stuff->eventMask &= ~wDontPropagateMask(pWin)((pWin)->optional ? (pWin)->optional->dontPropagateMask
: DontPropagateMasks[(pWin)->dontPropagate])
;
5415 if (!stuff->eventMask)
5416 break;
5417 }
5418 }
5419 else if (!XaceHook(XACE_SEND_ACCESS5, client, NULL((void*)0), pWin, &stuff->event, 1))
5420 DeliverEventsToWindow(dev, pWin, &stuff->event,
5421 1, stuff->eventMask, NullGrab((GrabPtr)((void*)0)));
5422 return Success0;
5423}
5424
5425/**
5426 * Server-side protocol handling for UngrabKey request.
5427 *
5428 * Deletes a passive grab for the given key. Works on the
5429 * client's keyboard.
5430 */
5431int
5432ProcUngrabKey(ClientPtr client)
5433{
5434 REQUEST(xUngrabKeyReq)xUngrabKeyReq *stuff = (xUngrabKeyReq *)client->requestBuffer;
5435 WindowPtr pWin;
5436 GrabPtr tempGrab;
5437 DeviceIntPtr keybd = PickKeyboard(client);
5438 int rc;
5439
5440 REQUEST_SIZE_MATCH(xUngrabKeyReq)if ((sizeof(xUngrabKeyReq) >> 2) != client->req_len)
return(16)
;
5441 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess(1<<4));
5442 if (rc != Success0)
5443 return rc;
5444
5445 if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5446 (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5447 && (stuff->key != AnyKey0L)) {
5448 client->errorValue = stuff->key;
5449 return BadValue2;
5450 }
5451 if ((stuff->modifiers != AnyModifier(1<<15)) &&
5452 (stuff->modifiers & ~AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
)) {
5453 client->errorValue = stuff->modifiers;
5454 return BadValue2;
5455 }
5456 tempGrab = AllocGrab(NULL((void*)0));
5457 if (!tempGrab)
5458 return BadAlloc11;
5459 tempGrab->resource = client->clientAsMask;
5460 tempGrab->device = keybd;
5461 tempGrab->window = pWin;
5462 tempGrab->modifiersDetail.exact = stuff->modifiers;
5463 tempGrab->modifiersDetail.pMask = NULL((void*)0);
5464 tempGrab->modifierDevice = keybd;
5465 tempGrab->type = KeyPress2;
5466 tempGrab->grabtype = CORE;
5467 tempGrab->detail.exact = stuff->key;
5468 tempGrab->detail.pMask = NULL((void*)0);
5469 tempGrab->next = NULL((void*)0);
5470
5471 if (!DeletePassiveGrabFromList(tempGrab))
5472 rc = BadAlloc11;
5473
5474 FreeGrab(tempGrab);
5475
5476 return rc;
5477}
5478
5479/**
5480 * Server-side protocol handling for GrabKey request.
5481 *
5482 * Creates a grab for the client's keyboard and adds it to the list of passive
5483 * grabs.
5484 */
5485int
5486ProcGrabKey(ClientPtr client)
5487{
5488 WindowPtr pWin;
5489
5490 REQUEST(xGrabKeyReq)xGrabKeyReq *stuff = (xGrabKeyReq *)client->requestBuffer;
5491 GrabPtr grab;
5492 DeviceIntPtr keybd = PickKeyboard(client);
5493 int rc;
5494 GrabParameters param;
5495 GrabMask mask;
5496
5497 REQUEST_SIZE_MATCH(xGrabKeyReq)if ((sizeof(xGrabKeyReq) >> 2) != client->req_len) return
(16)
;
5498
5499 param = (GrabParameters) {
5500 .grabtype = CORE,
5501 .ownerEvents = stuff->ownerEvents,
5502 .this_device_mode = stuff->keyboardMode,
5503 .other_devices_mode = stuff->pointerMode,
5504 .modifiers = stuff->modifiers
5505 };
5506
5507 rc = CheckGrabValues(client, &param);
5508 if (rc != Success0)
5509 return rc;
5510
5511 if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5512 (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5513 && (stuff->key != AnyKey0L)) {
5514 client->errorValue = stuff->key;
5515 return BadValue2;
5516 }
5517 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess(1<<5));
5518 if (rc != Success0)
5519 return rc;
5520
5521 mask.core = (KeyPressMask(1L<<0) | KeyReleaseMask(1L<<1));
5522
5523 grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
5524 &param, KeyPress2, stuff->key, NullWindow((WindowPtr) 0), NullCursor((CursorPtr)((void*)0)));
5525 if (!grab)
5526 return BadAlloc11;
5527 return AddPassiveGrabToList(client, grab);
5528}
5529
5530/**
5531 * Server-side protocol handling for GrabButton request.
5532 *
5533 * Creates a grab for the client's ClientPointer and adds it as a passive grab
5534 * to the list.
5535 */
5536int
5537ProcGrabButton(ClientPtr client)
5538{
5539 WindowPtr pWin, confineTo;
5540
5541 REQUEST(xGrabButtonReq)xGrabButtonReq *stuff = (xGrabButtonReq *)client->requestBuffer;
5542 CursorPtr cursor;
5543 GrabPtr grab;
5544 DeviceIntPtr ptr, modifierDevice;
5545 Mask access_mode = DixGrabAccess(1<<17);
5546 GrabMask mask;
5547 GrabParameters param;
5548 int rc;
5549
5550 REQUEST_SIZE_MATCH(xGrabButtonReq)if ((sizeof(xGrabButtonReq) >> 2) != client->req_len
) return(16)
;
5551 UpdateCurrentTime();
5552 if ((stuff->pointerMode != GrabModeSync0) &&
5553 (stuff->pointerMode != GrabModeAsync1)) {
5554 client->errorValue = stuff->pointerMode;
5555 return BadValue2;
5556 }
5557 if ((stuff->keyboardMode != GrabModeSync0) &&
5558 (stuff->keyboardMode != GrabModeAsync1)) {
5559 client->errorValue = stuff->keyboardMode;
5560 return BadValue2;
5561 }
5562 if ((stuff->modifiers != AnyModifier(1<<15)) &&
5563 (stuff->modifiers & ~AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
)) {
5564 client->errorValue = stuff->modifiers;
5565 return BadValue2;
5566 }
5567 if ((stuff->ownerEvents != xFalse0) && (stuff->ownerEvents != xTrue1)) {
5568 client->errorValue = stuff->ownerEvents;
5569 return BadValue2;
5570 }
5571 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) ) )
) {
5572 client->errorValue = stuff->eventMask;
5573 return BadValue2;
5574 }
5575 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess(1<<5));
5576 if (rc != Success0)
5577 return rc;
5578 if (stuff->confineTo == None0L)
5579 confineTo = NullWindow((WindowPtr) 0);
5580 else {
5581 rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
5582 DixSetAttrAccess(1<<5));
5583 if (rc != Success0)
5584 return rc;
5585 }
5586 if (stuff->cursor == None0L)
5587 cursor = NullCursor((CursorPtr)((void*)0));
5588 else {
5589 rc = dixLookupResourceByType((void **) &cursor, stuff->cursor,
5590 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
5591 if (rc != Success0) {
5592 client->errorValue = stuff->cursor;
5593 return rc;
5594 }
5595 access_mode |= DixForceAccess(1<<19);
5596 }
5597
5598 ptr = PickPointer(client);
5599 modifierDevice = GetMaster(ptr, MASTER_KEYBOARD2);
5600 if (stuff->pointerMode == GrabModeSync0 ||
5601 stuff->keyboardMode == GrabModeSync0)
5602 access_mode |= DixFreezeAccess(1<<18);
5603 rc = XaceHook(XACE_DEVICE_ACCESS3, client, ptr, access_mode);
5604 if (rc != Success0)
5605 return rc;
5606
5607 param = (GrabParameters) {
5608 .grabtype = CORE,
5609 .ownerEvents = stuff->ownerEvents,
5610 .this_device_mode = stuff->keyboardMode,
5611 .other_devices_mode = stuff->pointerMode,
5612 .modifiers = stuff->modifiers
5613 };
5614
5615 mask.core = stuff->eventMask;
5616
5617 grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
5618 CORE, &mask, &param, ButtonPress4,
5619 stuff->button, confineTo, cursor);
5620 if (!grab)
5621 return BadAlloc11;
5622 return AddPassiveGrabToList(client, grab);
5623}
5624
5625/**
5626 * Server-side protocol handling for UngrabButton request.
5627 *
5628 * Deletes a passive grab on the client's ClientPointer from the list.
5629 */
5630int
5631ProcUngrabButton(ClientPtr client)
5632{
5633 REQUEST(xUngrabButtonReq)xUngrabButtonReq *stuff = (xUngrabButtonReq *)client->requestBuffer;
5634 WindowPtr pWin;
5635 GrabPtr tempGrab;
5636 int rc;
5637 DeviceIntPtr ptr;
5638
5639 REQUEST_SIZE_MATCH(xUngrabButtonReq)if ((sizeof(xUngrabButtonReq) >> 2) != client->req_len
) return(16)
;
5640 UpdateCurrentTime();
5641 if ((stuff->modifiers != AnyModifier(1<<15)) &&
5642 (stuff->modifiers & ~AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
)) {
5643 client->errorValue = stuff->modifiers;
5644 return BadValue2;
5645 }
5646 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess(1<<0));
5647 if (rc != Success0)
5648 return rc;
5649
5650 ptr = PickPointer(client);
5651
5652 tempGrab = AllocGrab(NULL((void*)0));
5653 if (!tempGrab)
5654 return BadAlloc11;
5655 tempGrab->resource = client->clientAsMask;
5656 tempGrab->device = ptr;
5657 tempGrab->window = pWin;
5658 tempGrab->modifiersDetail.exact = stuff->modifiers;
5659 tempGrab->modifiersDetail.pMask = NULL((void*)0);
5660 tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD2);
5661 tempGrab->type = ButtonPress4;
5662 tempGrab->detail.exact = stuff->button;
5663 tempGrab->grabtype = CORE;
5664 tempGrab->detail.pMask = NULL((void*)0);
5665 tempGrab->next = NULL((void*)0);
5666
5667 if (!DeletePassiveGrabFromList(tempGrab))
5668 rc = BadAlloc11;
5669
5670 FreeGrab(tempGrab);
5671 return rc;
5672}
5673
5674/**
5675 * Deactivate any grab that may be on the window, remove the focus.
5676 * Delete any XInput extension events from the window too. Does not change the
5677 * window mask. Use just before the window is deleted.
5678 *
5679 * If freeResources is set, passive grabs on the window are deleted.
5680 *
5681 * @param pWin The window to delete events from.
5682 * @param freeResources True if resources associated with the window should be
5683 * deleted.
5684 */
5685void
5686DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
5687{
5688 WindowPtr parent;
5689 DeviceIntPtr mouse = inputInfo.pointer;
5690 DeviceIntPtr keybd = inputInfo.keyboard;
5691 FocusClassPtr focus;
5692 OtherClientsPtr oc;
5693 GrabPtr passive;
5694 GrabPtr grab;
5695
5696 /* Deactivate any grabs performed on this window, before making any
5697 input focus changes. */
5698 grab = mouse->deviceGrab.grab;
5699 if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5700 (*mouse->deviceGrab.DeactivateGrab) (mouse);
5701
5702 /* Deactivating a keyboard grab should cause focus events. */
5703 grab = keybd->deviceGrab.grab;
5704 if (grab && (grab->window == pWin))
5705 (*keybd->deviceGrab.DeactivateGrab) (keybd);
5706
5707 /* And now the real devices */
5708 for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
5709 grab = mouse->deviceGrab.grab;
5710 if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5711 (*mouse->deviceGrab.DeactivateGrab) (mouse);
5712 }
5713
5714 for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
5715 if (IsKeyboardDevice(keybd)) {
5716 focus = keybd->focus;
5717
5718 /* If the focus window is a root window (ie. has no parent)
5719 then don't delete the focus from it. */
5720
5721 if ((pWin == focus->win) && (pWin->parent != NullWindow((WindowPtr) 0))) {
5722 int focusEventMode = NotifyNormal0;
5723
5724 /* If a grab is in progress, then alter the mode of focus events. */
5725
5726 if (keybd->deviceGrab.grab)
5727 focusEventMode = NotifyWhileGrabbed3;
5728
5729 switch (focus->revert) {
5730 case RevertToNone(int)0L:
5731 DoFocusEvents(keybd, pWin, NoneWin((WindowPtr)0L), focusEventMode);
5732 focus->win = NoneWin((WindowPtr)0L);
5733 focus->traceGood = 0;
5734 break;
5735 case RevertToParent2:
5736 parent = pWin;
5737 do {
5738 parent = parent->parent;
5739 focus->traceGood--;
5740 } while (!parent->realized
5741 /* This would be a good protocol change -- windows being
5742 reparented during SaveSet processing would cause the
5743 focus to revert to the nearest enclosing window which
5744 will survive the death of the exiting client, instead
5745 of ending up reverting to a dying window and thence
5746 to None */
5747#ifdef NOTDEF
5748 || wClient(parent)(clients[((int)((((parent)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
->clientGone
5749#endif
5750 );
5751 if (!ActivateFocusInGrab(keybd, pWin, parent))
5752 DoFocusEvents(keybd, pWin, parent, focusEventMode);
5753 focus->win = parent;
5754 focus->revert = RevertToNone(int)0L;
5755 break;
5756 case RevertToPointerRoot(int)1L:
5757 if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin((WindowPtr)1L)))
5758 DoFocusEvents(keybd, pWin, PointerRootWin((WindowPtr)1L),
5759 focusEventMode);
5760 focus->win = PointerRootWin((WindowPtr)1L);
5761 focus->traceGood = 0;
5762 break;
5763 }
5764 }
5765 }
5766
5767 if (IsPointerDevice(keybd)) {
5768 if (keybd->valuator->motionHintWindow == pWin)
5769 keybd->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
5770 }
5771 }
5772
5773 if (freeResources) {
5774 if (pWin->dontPropagate)
5775 DontPropagateRefCnts[pWin->dontPropagate]--;
5776 while ((oc = wOtherClients(pWin)((pWin)->optional ? (pWin)->optional->otherClients :
((void*)0))
))
5777 FreeResource(oc->resource, RT_NONE((RESTYPE)0));
5778 while ((passive = wPassiveGrabs(pWin)((pWin)->optional ? (pWin)->optional->passiveGrabs :
((void*)0))
))
5779 FreeResource(passive->resource, RT_NONE((RESTYPE)0));
5780 }
5781
5782 DeleteWindowFromAnyExtEvents(pWin, freeResources);
5783}
5784
5785/**
5786 * Call this whenever some window at or below pWin has changed geometry. If
5787 * there is a grab on the window, the cursor will be re-confined into the
5788 * window.
5789 */
5790void
5791CheckCursorConfinement(WindowPtr pWin)
5792{
5793 GrabPtr grab;
5794 WindowPtr confineTo;
5795 DeviceIntPtr pDev;
5796
5797#ifdef PANORAMIX1
5798 if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
5799 return;
5800#endif
5801
5802 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
5803 if (DevHasCursor(pDev)) {
5804 grab = pDev->deviceGrab.grab;
5805 if (grab && (confineTo = grab->confineTo)) {
5806 if (!BorderSizeNotEmpty(pDev, confineTo))
5807 (*pDev->deviceGrab.DeactivateGrab) (pDev);
5808 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
5809 ConfineCursorToWindow(pDev, confineTo, TRUE1, TRUE1);
5810 }
5811 }
5812 }
5813}
5814
5815Mask
5816EventMaskForClient(WindowPtr pWin, ClientPtr client)
5817{
5818 OtherClientsPtr other;
5819
5820 if (wClient(pWin)(clients[((int)((((pWin)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
== client)
5821 return pWin->eventMask;
5822 for (other = wOtherClients(pWin)((pWin)->optional ? (pWin)->optional->otherClients :
((void*)0))
; other; other = other->next) {
5823 if (SameClient(other, client)((((other)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
5824 return other->mask;
5825 }
5826 return 0;
5827}
5828
5829/**
5830 * Server-side protocol handling for RecolorCursor request.
5831 */
5832int
5833ProcRecolorCursor(ClientPtr client)
5834{
5835 CursorPtr pCursor;
5836 int rc, nscr;
5837 ScreenPtr pscr;
5838 Bool displayed;
5839 SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
5840
5841 REQUEST(xRecolorCursorReq)xRecolorCursorReq *stuff = (xRecolorCursorReq *)client->requestBuffer;
5842
5843 REQUEST_SIZE_MATCH(xRecolorCursorReq)if ((sizeof(xRecolorCursorReq) >> 2) != client->req_len
) return(16)
;
5844 rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR((RESTYPE)5),
5845 client, DixWriteAccess(1<<1));
5846 if (rc != Success0) {
5847 client->errorValue = stuff->cursor;
5848 return rc;
5849 }
5850
5851 pCursor->foreRed = stuff->foreRed;
5852 pCursor->foreGreen = stuff->foreGreen;
5853 pCursor->foreBlue = stuff->foreBlue;
5854
5855 pCursor->backRed = stuff->backRed;
5856 pCursor->backGreen = stuff->backGreen;
5857 pCursor->backBlue = stuff->backBlue;
5858
5859 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
5860 pscr = screenInfo.screens[nscr];
5861#ifdef PANORAMIX1
5862 if (!noPanoramiXExtension)
5863 displayed = (pscr == pSprite->screen);
5864 else
5865#endif
5866 displayed = (pscr == pSprite->hotPhys.pScreen);
5867 (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor,
5868 (pCursor == pSprite->current) && displayed);
5869 }
5870 return Success0;
5871}
5872
5873/**
5874 * Write the given events to a client, swapping the byte order if necessary.
5875 * To swap the byte ordering, a callback is called that has to be set up for
5876 * the given event type.
5877 *
5878 * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
5879 * can be more than one. Usually it's just one event.
5880 *
5881 * Do not modify the event structure passed in. See comment below.
5882 *
5883 * @param pClient Client to send events to.
5884 * @param count Number of events.
5885 * @param events The event list.
5886 */
5887void
5888WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
5889{
5890#ifdef PANORAMIX1
5891 xEvent eventCopy;
5892#endif
5893 xEvent *eventTo, *eventFrom;
5894 int i, eventlength = sizeof(xEvent);
5895
5896 if (!pClient || pClient == serverClient || pClient->clientGone)
5897 return;
5898
5899 for (i = 0; i < count; i++)
5900 if ((events[i].u.u.type & 0x7f) != KeymapNotify11)
5901 events[i].u.u.sequenceNumber = pClient->sequence;
5902
5903 /* Let XKB rewrite the state, as it depends on client preferences. */
5904 XkbFilterEvents(pClient, count, events);
5905
5906#ifdef PANORAMIX1
5907 if (!noPanoramiXExtension &&
5908 (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) {
5909 switch (events->u.u.type) {
5910 case MotionNotify6:
5911 case ButtonPress4:
5912 case ButtonRelease5:
5913 case KeyPress2:
5914 case KeyRelease3:
5915 case EnterNotify7:
5916 case LeaveNotify8:
5917 /*
5918 When multiple clients want the same event DeliverEventsToWindow
5919 passes the same event structure multiple times so we can't
5920 modify the one passed to us
5921 */
5922 count = 1; /* should always be 1 */
5923 memcpy(&eventCopy, events, sizeof(xEvent))__builtin___memcpy_chk (&eventCopy, events, sizeof(xEvent
), __builtin_object_size (&eventCopy, 0))
;
5924 eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
5925 eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
5926 if (eventCopy.u.keyButtonPointer.event ==
5927 eventCopy.u.keyButtonPointer.root) {
5928 eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
5929 eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
5930 }
5931 events = &eventCopy;
5932 break;
5933 default:
5934 break;
5935 }
5936 }
5937#endif
5938
5939 if (EventCallback) {
5940 EventInfoRec eventinfo;
5941
5942 eventinfo.client = pClient;
5943 eventinfo.events = events;
5944 eventinfo.count = count;
5945 CallCallbacks(&EventCallback, (void *) &eventinfo);
5946 }
5947#ifdef XSERVER_DTRACE1
5948 if (XSERVER_SEND_EVENT_ENABLED()({ int _r = __dtrace_isenabled$Xserver$send__event$v1(); __asm__
volatile(""); _r; })
) {
5949 for (i = 0; i < count; i++) {
5950 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)
;
5951 }
5952 }
5953#endif
5954 /* Just a safety check to make sure we only have one GenericEvent, it just
5955 * makes things easier for me right now. (whot) */
5956 for (i = 1; i < count; i++) {
5957 if (events[i].u.u.type == GenericEvent35) {
5958 ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
5959 return;
5960 }
5961 }
5962
5963 if (events->u.u.type == GenericEvent35) {
5964 eventlength += ((xGenericEvent *) events)->length * 4;
5965 }
5966
5967 if (pClient->swapped) {
5968 if (eventlength > swapEventLen) {
5969 swapEventLen = eventlength;
5970 swapEvent = realloc(swapEvent, swapEventLen);
5971 if (!swapEvent) {
5972 FatalError("WriteEventsToClient: Out of memory.\n");
5973 return;
5974 }
5975 }
5976
5977 for (i = 0; i < count; i++) {
5978 eventFrom = &events[i];
5979 eventTo = swapEvent;
5980
5981 /* Remember to strip off the leading bit of type in case
5982 this event was sent with "SendEvent." */
5983 (*EventSwapVector[eventFrom->u.u.type & 0177])
5984 (eventFrom, eventTo);
5985
5986 WriteToClient(pClient, eventlength, eventTo);
5987 }
5988 }
5989 else {
5990 /* only one GenericEvent, remember? that means either count is 1 and
5991 * eventlength is arbitrary or eventlength is 32 and count doesn't
5992 * matter. And we're all set. Woohoo. */
5993 WriteToClient(pClient, count * eventlength, events);
5994 }
5995}
5996
5997/*
5998 * Set the client pointer for the given client.
5999 *
6000 * A client can have exactly one ClientPointer. Each time a
6001 * request/reply/event is processed and the choice of devices is ambiguous
6002 * (e.g. QueryPointer request), the server will pick the ClientPointer (see
6003 * PickPointer()).
6004 * If a keyboard is needed, the first keyboard paired with the CP is used.
6005 */
6006int
6007SetClientPointer(ClientPtr client, DeviceIntPtr device)
6008{
6009 int rc = XaceHook(XACE_DEVICE_ACCESS3, client, device, DixUseAccess(1<<24));
6010
6011 if (rc != Success0)
6012 return rc;
6013
6014 if (!IsMaster(device)) {
6015 ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
6016 return BadDevice;
6017 }
6018 else if (!device->spriteInfo->spriteOwner) {
6019 ErrorF("[dix] Device %d does not have a sprite. "
6020 "Cannot be ClientPointer\n", device->id);
6021 return BadDevice;
6022 }
6023 client->clientPtr = device;
6024 return Success0;
6025}
6026
6027/* PickPointer will pick an appropriate pointer for the given client.
6028 *
6029 * An "appropriate device" is (in order of priority):
6030 * 1) A device the given client has a core grab on.
6031 * 2) A device set as ClientPointer for the given client.
6032 * 3) The first master device.
6033 */
6034DeviceIntPtr
6035PickPointer(ClientPtr client)
6036{
6037 DeviceIntPtr it = inputInfo.devices;
6038
6039 /* First, check if the client currently has a grab on a device. Even
6040 * keyboards count. */
6041 for (it = inputInfo.devices; it; it = it->next) {
6042 GrabPtr grab = it->deviceGrab.grab;
6043
6044 if (grab && grab->grabtype == CORE && SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
) {
6045 it = GetMaster(it, MASTER_POINTER1);
6046 return it; /* Always return a core grabbed device */
6047 }
6048 }
6049
6050 if (!client->clientPtr) {
6051 it = inputInfo.devices;
6052 while (it) {
6053 if (IsMaster(it) && it->spriteInfo->spriteOwner) {
6054 client->clientPtr = it;
6055 break;
6056 }
6057 it = it->next;
6058 }
6059 }
6060 return client->clientPtr;
6061}
6062
6063/* PickKeyboard will pick an appropriate keyboard for the given client by
6064 * searching the list of devices for the keyboard device that is paired with
6065 * the client's pointer.
6066 */
6067DeviceIntPtr
6068PickKeyboard(ClientPtr client)
6069{
6070 DeviceIntPtr ptr = PickPointer(client);
6071 DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD2);
6072
6073 if (!kbd) {
6074 ErrorF("[dix] ClientPointer not paired with a keyboard. This "
6075 "is a bug.\n");
6076 }
6077
6078 return kbd;
6079}
6080
6081/* A client that has one or more core grabs does not get core events from
6082 * devices it does not have a grab on. Legacy applications behave bad
6083 * otherwise because they are not used to it and the events interfere.
6084 * Only applies for core events.
6085 *
6086 * Return true if a core event from the device would interfere and should not
6087 * be delivered.
6088 */
6089Bool
6090IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
6091{
6092 DeviceIntPtr it = inputInfo.devices;
6093
6094 switch (event->u.u.type) {
6095 case KeyPress2:
6096 case KeyRelease3:
6097 case ButtonPress4:
6098 case ButtonRelease5:
6099 case MotionNotify6:
6100 case EnterNotify7:
6101 case LeaveNotify8:
6102 break;
6103 default:
6104 return FALSE0;
6105 }
6106
6107 if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)((((dev->deviceGrab.grab)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) == (client)->clientAsMask)
)
6108 return FALSE0;
6109
6110 while (it) {
6111 if (it != dev) {
6112 if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)((((it->deviceGrab.grab)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) == (client)->clientAsMask)
6113 && !it->deviceGrab.fromPassiveGrab) {
6114 if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
6115 (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
6116 return TRUE1;
6117 }
6118 }
6119 it = it->next;
6120 }
6121
6122 return FALSE0;
6123}
6124
6125/* PointerBarrier events are only delivered to the client that created that
6126 * barrier */
6127static Bool
6128IsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
6129{
6130 xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
6131
6132 if (ev->type != GenericEvent35 || ev->extension != IReqCode)
6133 return FALSE0;
6134
6135 if (ev->evtype != XI_BarrierHit25 && ev->evtype != XI_BarrierLeave26)
6136 return FALSE0;
6137
6138 return client->index != CLIENT_ID(ev->barrier)((int)(((ev->barrier) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))
;
6139}