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