1 /************************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
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
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 /*****************************************************************
79 Copyright 2003-2005 Sun Microsystems, Inc.
83 Permission is hereby granted, free of charge, to any person obtaining a
84 copy of this software and associated documentation files (the
85 "Software"), to deal in the Software without restriction, including
86 without limitation the rights to use, copy, modify, merge, publish,
87 distribute, and/or sell copies of the Software, and to permit persons
88 to whom the Software is furnished to do so, provided that the above
89 copyright notice(s) and this permission notice appear in all copies of
90 the Software and that both the above copyright notice(s) and this
91 permission notice appear in supporting documentation.
93 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
94 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
95 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
96 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
97 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
98 INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
99 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
100 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
101 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
103 Except as contained in this notice, the name of a copyright holder
104 shall not be used in advertising or otherwise to promote the sale, use
105 or other dealings in this Software without prior written authorization
106 of the copyright holder.
108 ******************************************************************/
111 * This file handles event delivery and a big part of the server-side protocol
112 * handling (the parts for input devices).
115 #ifdef HAVE_DIX_CONFIG_H
116 #include <dix-config.h>
120 #include <X11/keysym.h>
122 #include "resource.h"
125 #include <X11/Xproto.h>
126 #include "windowstr.h"
127 #include "inputstr.h"
128 #include "scrnintstr.h"
129 #include "cursorstr.h"
131 #include "dixstruct.h"
133 #include "panoramiX.h"
134 #include "panoramiXsrv.h"
139 #include <X11/extensions/XKBproto.h>
141 extern Bool
XkbFilterEvents(ClientPtr
, int, xEvent
*);
146 #ifdef XSERVER_DTRACE
147 #include <sys/types.h>
148 typedef const char *string
;
149 #include "Xserver-dtrace.h"
153 extern WindowPtr
*WindowTable
;
154 extern int xevieFlag
;
155 extern int xevieClientIndex
;
156 extern DeviceIntPtr xeviemouse
;
157 extern DeviceIntPtr xeviekb
;
158 extern Mask xevieMask
;
159 extern Mask xevieFilters
[128];
160 extern int xevieEventSent
;
161 extern int xevieKBEventSent
;
162 int xeviegrabState
= 0;
165 #include <X11/extensions/XIproto.h>
166 #include "exglobals.h"
167 #include "exevents.h"
168 #include "exglobals.h"
169 #include "extnsionst.h"
171 #include "dixevents.h"
172 #include "dixgrabs.h"
173 #include "dispatch.h"
175 * Extension events type numbering starts at EXTENSION_EVENT_BASE.
177 #define EXTENSION_EVENT_BASE 64
179 #define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
180 #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
181 #define AllButtonsMask ( \
182 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
183 #define MotionMask ( \
184 PointerMotionMask | Button1MotionMask | \
185 Button2MotionMask | Button3MotionMask | Button4MotionMask | \
186 Button5MotionMask | ButtonMotionMask )
187 #define PropagateMask ( \
188 KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
190 #define PointerGrabMask ( \
191 ButtonPressMask | ButtonReleaseMask | \
192 EnterWindowMask | LeaveWindowMask | \
193 PointerMotionHintMask | KeymapStateMask | \
195 #define AllModifiersMask ( \
196 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
197 Mod3Mask | Mod4Mask | Mod5Mask )
198 #define AllEventMasks (lastEventMask|(lastEventMask-1))
200 * The following relies on the fact that the Button<n>MotionMasks are equal
201 * to the corresponding Button<n>Masks from the current modifier/button state.
203 #define Motion_Filter(class) (PointerMotionMask | \
204 (class)->state | (class)->motionMask)
207 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
209 #define XE_KBPTR (xE->u.keyButtonPointer)
212 #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
214 _X_EXPORT CallbackListPtr EventCallback
;
215 _X_EXPORT CallbackListPtr DeviceEventCallback
;
219 Mask DontPropagateMasks
[DNPMCOUNT
];
220 static int DontPropagateRefCnts
[DNPMCOUNT
];
223 * Main input device struct.
225 * is the core pointer. Referred to as "virtual core pointer", "VCP",
226 * "core pointer" or inputInfo.pointer. There is exactly one core pointer,
227 * but multiple devices may send core events. If a device generates core
228 * events, those events will appear to originate from the core pointer.
231 * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
232 * See inputInfo.pointer.
235 * linked list containing all devices including VCK and VCP. The VCK will
236 * always be the first entry, the VCP the second entry in the device list.
238 * inputInfo.off_devices
239 * Devices that have not been initialized and are thus turned off.
241 * inputInfo.numDevices
242 * Total number of devices.
244 _X_EXPORT InputInfo inputInfo
;
247 QdEventPtr pending
, *pendtail
;
248 DeviceIntPtr replayDev
; /* kludgy rock to put flag for */
249 WindowPtr replayWin
; /* ComputeFreezes */
255 * The window trace information is used to avoid having to compute all the
256 * windows between the root and the current pointer window each time a button
257 * or key goes down. The grabs on each of those windows must be checked.
259 * @see XYToWindow() for a documentation on how the array is set up.
261 static WindowPtr
*spriteTrace
= (WindowPtr
*)NULL
;
262 #define ROOT spriteTrace[0]
263 static int spriteTraceSize
= 0;
264 static int spriteTraceGood
;
267 * DIX sprite information. This is the sprite as seen from the DIX. It does
268 * not represent the actual sprite rendered to the screen.
273 BoxRec hotLimits
; /* logical constraints of hot spot */
274 Bool confined
; /* confined to screen */
275 #if defined(SHAPE) || defined(PANORAMIX)
276 RegionPtr hotShape
; /* additional logical shape constraint */
278 BoxRec physLimits
; /* physical constraints of hot spot */
279 WindowPtr win
; /* window of logical position */
280 HotSpot hot
; /* logical pointer position */
281 HotSpot hotPhys
; /* physical pointer position */
283 ScreenPtr screen
; /* all others are in Screen 0 coordinates */
284 RegionRec Reg1
; /* Region 1 for confining motion */
285 RegionRec Reg2
; /* Region 2 for confining virtual motion */
286 WindowPtr windows
[MAXSCREENS
];
287 WindowPtr confineWin
; /* confine window */
289 } sprite
; /* info about the cursor sprite */
292 _X_EXPORT WindowPtr xeviewin
;
293 _X_EXPORT HotSpot xeviehot
;
296 static void DoEnterLeaveEvents(
302 static WindowPtr
XYToWindow(
310 extern int lastEvent
;
312 static Mask lastEventMask
;
315 extern int DeviceMotionNotify
;
318 #define CantBeFiltered NoEventMask
319 static Mask filters
[128] =
323 KeyPressMask
, /* KeyPress */
324 KeyReleaseMask
, /* KeyRelease */
325 ButtonPressMask
, /* ButtonPress */
326 ButtonReleaseMask
, /* ButtonRelease */
327 PointerMotionMask
, /* MotionNotify (initial state) */
328 EnterWindowMask
, /* EnterNotify */
329 LeaveWindowMask
, /* LeaveNotify */
330 FocusChangeMask
, /* FocusIn */
331 FocusChangeMask
, /* FocusOut */
332 KeymapStateMask
, /* KeymapNotify */
333 ExposureMask
, /* Expose */
334 CantBeFiltered
, /* GraphicsExpose */
335 CantBeFiltered
, /* NoExpose */
336 VisibilityChangeMask
, /* VisibilityNotify */
337 SubstructureNotifyMask
, /* CreateNotify */
338 StructureAndSubMask
, /* DestroyNotify */
339 StructureAndSubMask
, /* UnmapNotify */
340 StructureAndSubMask
, /* MapNotify */
341 SubstructureRedirectMask
, /* MapRequest */
342 StructureAndSubMask
, /* ReparentNotify */
343 StructureAndSubMask
, /* ConfigureNotify */
344 SubstructureRedirectMask
, /* ConfigureRequest */
345 StructureAndSubMask
, /* GravityNotify */
346 ResizeRedirectMask
, /* ResizeRequest */
347 StructureAndSubMask
, /* CirculateNotify */
348 SubstructureRedirectMask
, /* CirculateRequest */
349 PropertyChangeMask
, /* PropertyNotify */
350 CantBeFiltered
, /* SelectionClear */
351 CantBeFiltered
, /* SelectionRequest */
352 CantBeFiltered
, /* SelectionNotify */
353 ColormapChangeMask
, /* ColormapNotify */
354 CantBeFiltered
, /* ClientMessage */
355 CantBeFiltered
/* MappingNotify */
358 static CARD8 criticalEvents
[32] =
360 0x7c /* key and button events */
364 static void ConfineToShape(RegionPtr shape
, int *px
, int *py
);
365 static void PostNewCursor(void);
367 #define SyntheticMotion(x, y) \
368 PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \
369 sprite.screen->myNum, \
370 syncEvents.playingEvents ? \
371 syncEvents.time.milliseconds : \
372 currentTime.milliseconds);
375 XineramaSetCursorPosition(
384 /* x,y are in Screen 0 coordinates. We need to decide what Screen
385 to send the message too and what the coordinates relative to
388 pScreen
= sprite
.screen
;
389 x
+= panoramiXdataPtr
[0].x
;
390 y
+= panoramiXdataPtr
[0].y
;
392 if(!POINT_IN_REGION(pScreen
, &XineramaScreenRegions
[pScreen
->myNum
],
397 if(i
== pScreen
->myNum
)
399 if(POINT_IN_REGION(pScreen
, &XineramaScreenRegions
[i
], x
, y
, &box
))
401 pScreen
= screenInfo
.screens
[i
];
407 sprite
.screen
= pScreen
;
408 sprite
.hotPhys
.x
= x
- panoramiXdataPtr
[0].x
;
409 sprite
.hotPhys
.y
= y
- panoramiXdataPtr
[0].y
;
410 x
-= panoramiXdataPtr
[pScreen
->myNum
].x
;
411 y
-= panoramiXdataPtr
[pScreen
->myNum
].y
;
413 return (*pScreen
->SetCursorPosition
)(pScreen
, x
, y
, generateEvent
);
418 XineramaConstrainCursor(void)
420 ScreenPtr pScreen
= sprite
.screen
;
421 BoxRec newBox
= sprite
.physLimits
;
423 /* Translate the constraining box to the screen
424 the sprite is actually on */
425 newBox
.x1
+= panoramiXdataPtr
[0].x
- panoramiXdataPtr
[pScreen
->myNum
].x
;
426 newBox
.x2
+= panoramiXdataPtr
[0].x
- panoramiXdataPtr
[pScreen
->myNum
].x
;
427 newBox
.y1
+= panoramiXdataPtr
[0].y
- panoramiXdataPtr
[pScreen
->myNum
].y
;
428 newBox
.y2
+= panoramiXdataPtr
[0].y
- panoramiXdataPtr
[pScreen
->myNum
].y
;
430 (* pScreen
->ConstrainCursor
)(pScreen
, &newBox
);
434 XineramaCheckPhysLimits(
443 new = sprite
.hotPhys
;
445 /* I don't care what the DDX has to say about it */
446 sprite
.physLimits
= sprite
.hotLimits
;
448 /* constrain the pointer to those limits */
449 if (new.x
< sprite
.physLimits
.x1
)
450 new.x
= sprite
.physLimits
.x1
;
452 if (new.x
>= sprite
.physLimits
.x2
)
453 new.x
= sprite
.physLimits
.x2
- 1;
454 if (new.y
< sprite
.physLimits
.y1
)
455 new.y
= sprite
.physLimits
.y1
;
457 if (new.y
>= sprite
.physLimits
.y2
)
458 new.y
= sprite
.physLimits
.y2
- 1;
460 if (sprite
.hotShape
) /* more work if the shape is a mess */
461 ConfineToShape(sprite
.hotShape
, &new.x
, &new.y
);
463 if((new.x
!= sprite
.hotPhys
.x
) || (new.y
!= sprite
.hotPhys
.y
))
465 XineramaSetCursorPosition (new.x
, new.y
, generateEvents
);
467 SyntheticMotion(new.x
, new.y
);
470 /* Tell DDX what the limits are */
471 XineramaConstrainCursor();
476 XineramaSetWindowPntrs(WindowPtr pWin
)
478 if(pWin
== WindowTable
[0]) {
479 memcpy(sprite
.windows
, WindowTable
,
480 PanoramiXNumScreens
*sizeof(WindowPtr
));
485 win
= (PanoramiXRes
*)LookupIDByType(pWin
->drawable
.id
, XRT_WINDOW
);
490 for(i
= 0; i
< PanoramiXNumScreens
; i
++) {
491 sprite
.windows
[i
] = LookupIDByType(win
->info
[i
].id
, RT_WINDOW
);
492 if(!sprite
.windows
[i
]) /* window is being unmapped */
500 XineramaCheckVirtualMotion(
507 sprite
.hot
.pScreen
= qe
->pScreen
; /* should always be Screen 0 */
508 sprite
.hot
.x
= qe
->event
->u
.keyButtonPointer
.rootX
;
509 sprite
.hot
.y
= qe
->event
->u
.keyButtonPointer
.rootY
;
510 pWin
= inputInfo
.pointer
->grab
? inputInfo
.pointer
->grab
->confineTo
:
515 int x
, y
, off_x
, off_y
, i
;
518 if(!XineramaSetWindowPntrs(pWin
))
521 i
= PanoramiXNumScreens
- 1;
523 REGION_COPY(sprite
.screen
, &sprite
.Reg2
,
524 &sprite
.windows
[i
]->borderSize
);
525 off_x
= panoramiXdataPtr
[i
].x
;
526 off_y
= panoramiXdataPtr
[i
].y
;
529 x
= off_x
- panoramiXdataPtr
[i
].x
;
530 y
= off_y
- panoramiXdataPtr
[i
].y
;
533 REGION_TRANSLATE(sprite
.screen
, &sprite
.Reg2
, x
, y
);
535 REGION_UNION(sprite
.screen
, &sprite
.Reg2
, &sprite
.Reg2
,
536 &sprite
.windows
[i
]->borderSize
);
538 off_x
= panoramiXdataPtr
[i
].x
;
539 off_y
= panoramiXdataPtr
[i
].y
;
542 lims
= *REGION_EXTENTS(sprite
.screen
, &sprite
.Reg2
);
544 if (sprite
.hot
.x
< lims
.x1
)
545 sprite
.hot
.x
= lims
.x1
;
546 else if (sprite
.hot
.x
>= lims
.x2
)
547 sprite
.hot
.x
= lims
.x2
- 1;
548 if (sprite
.hot
.y
< lims
.y1
)
549 sprite
.hot
.y
= lims
.y1
;
550 else if (sprite
.hot
.y
>= lims
.y2
)
551 sprite
.hot
.y
= lims
.y2
- 1;
553 if (REGION_NUM_RECTS(&sprite
.Reg2
) > 1)
554 ConfineToShape(&sprite
.Reg2
, &sprite
.hot
.x
, &sprite
.hot
.y
);
558 qe
->pScreen
= sprite
.hot
.pScreen
;
559 qe
->event
->u
.keyButtonPointer
.rootX
= sprite
.hot
.x
;
560 qe
->event
->u
.keyButtonPointer
.rootY
= sprite
.hot
.y
;
564 xeviehot
.x
= sprite
.hot
.x
;
565 xeviehot
.y
= sprite
.hot
.y
;
571 XineramaCheckMotion(xEvent
*xE
)
573 WindowPtr prevSpriteWin
= sprite
.win
;
575 if (xE
&& !syncEvents
.playingEvents
)
577 /* Motion events entering DIX get translated to Screen 0
578 coordinates. Replayed events have already been
579 translated since they've entered DIX before */
580 XE_KBPTR
.rootX
+= panoramiXdataPtr
[sprite
.screen
->myNum
].x
-
581 panoramiXdataPtr
[0].x
;
582 XE_KBPTR
.rootY
+= panoramiXdataPtr
[sprite
.screen
->myNum
].y
-
583 panoramiXdataPtr
[0].y
;
584 sprite
.hot
.x
= XE_KBPTR
.rootX
;
585 sprite
.hot
.y
= XE_KBPTR
.rootY
;
586 if (sprite
.hot
.x
< sprite
.physLimits
.x1
)
587 sprite
.hot
.x
= sprite
.physLimits
.x1
;
588 else if (sprite
.hot
.x
>= sprite
.physLimits
.x2
)
589 sprite
.hot
.x
= sprite
.physLimits
.x2
- 1;
590 if (sprite
.hot
.y
< sprite
.physLimits
.y1
)
591 sprite
.hot
.y
= sprite
.physLimits
.y1
;
592 else if (sprite
.hot
.y
>= sprite
.physLimits
.y2
)
593 sprite
.hot
.y
= sprite
.physLimits
.y2
- 1;
596 ConfineToShape(sprite
.hotShape
, &sprite
.hot
.x
, &sprite
.hot
.y
);
598 sprite
.hotPhys
= sprite
.hot
;
599 if ((sprite
.hotPhys
.x
!= XE_KBPTR
.rootX
) ||
600 (sprite
.hotPhys
.y
!= XE_KBPTR
.rootY
))
602 XineramaSetCursorPosition(
603 sprite
.hotPhys
.x
, sprite
.hotPhys
.y
, FALSE
);
605 XE_KBPTR
.rootX
= sprite
.hot
.x
;
606 XE_KBPTR
.rootY
= sprite
.hot
.y
;
610 xeviehot
.x
= sprite
.hot
.x
;
611 xeviehot
.y
= sprite
.hot
.y
;
614 sprite
.win
= XYToWindow(sprite
.hot
.x
, sprite
.hot
.y
);
616 if (sprite
.win
!= prevSpriteWin
)
618 if (prevSpriteWin
!= NullWindow
) {
620 UpdateCurrentTimeIf();
621 DoEnterLeaveEvents(prevSpriteWin
, sprite
.win
, NotifyNormal
);
631 XineramaConfineCursorToWindow(WindowPtr pWin
, Bool generateEvents
)
634 if (syncEvents
.playingEvents
)
636 XineramaCheckVirtualMotion((QdEventPtr
)NULL
, pWin
);
637 SyntheticMotion(sprite
.hot
.x
, sprite
.hot
.y
);
641 int x
, y
, off_x
, off_y
, i
;
643 if(!XineramaSetWindowPntrs(pWin
))
646 i
= PanoramiXNumScreens
- 1;
648 REGION_COPY(sprite
.screen
, &sprite
.Reg1
,
649 &sprite
.windows
[i
]->borderSize
);
650 off_x
= panoramiXdataPtr
[i
].x
;
651 off_y
= panoramiXdataPtr
[i
].y
;
654 x
= off_x
- panoramiXdataPtr
[i
].x
;
655 y
= off_y
- panoramiXdataPtr
[i
].y
;
658 REGION_TRANSLATE(sprite
.screen
, &sprite
.Reg1
, x
, y
);
660 REGION_UNION(sprite
.screen
, &sprite
.Reg1
, &sprite
.Reg1
,
661 &sprite
.windows
[i
]->borderSize
);
663 off_x
= panoramiXdataPtr
[i
].x
;
664 off_y
= panoramiXdataPtr
[i
].y
;
667 sprite
.hotLimits
= *REGION_EXTENTS(sprite
.screen
, &sprite
.Reg1
);
669 if(REGION_NUM_RECTS(&sprite
.Reg1
) > 1)
670 sprite
.hotShape
= &sprite
.Reg1
;
672 sprite
.hotShape
= NullRegion
;
674 sprite
.confined
= FALSE
;
675 sprite
.confineWin
= (pWin
== WindowTable
[0]) ? NullWindow
: pWin
;
677 XineramaCheckPhysLimits(sprite
.current
, generateEvents
);
683 XineramaChangeToCursor(CursorPtr cursor
)
685 if (cursor
!= sprite
.current
)
687 if ((sprite
.current
->bits
->xhot
!= cursor
->bits
->xhot
) ||
688 (sprite
.current
->bits
->yhot
!= cursor
->bits
->yhot
))
689 XineramaCheckPhysLimits(cursor
, FALSE
);
690 (*sprite
.screen
->DisplayCursor
)(sprite
.screen
, cursor
);
691 FreeCursor(sprite
.current
, (Cursor
)0);
692 sprite
.current
= cursor
;
693 sprite
.current
->refcnt
++;
698 #define SyntheticMotion(x, y) \
699 PostSyntheticMotion(x, y, \
701 syncEvents.playingEvents ? \
702 syncEvents.time.milliseconds : \
703 currentTime.milliseconds);
705 #endif /* PANORAMIX */
708 SetMaskForEvent(Mask mask
, int event
)
710 if ((event
< LASTEvent
) || (event
>= 128))
711 FatalError("SetMaskForEvent: bogus event number");
712 filters
[event
] = mask
;
716 SetCriticalEvent(int event
)
719 FatalError("SetCriticalEvent: bogus event number");
720 criticalEvents
[event
>> 3] |= 1 << (event
& 7);
725 ConfineToShape(RegionPtr shape
, int *px
, int *py
)
728 int x
= *px
, y
= *py
;
729 int incx
= 1, incy
= 1;
731 if (POINT_IN_REGION(sprite
.hot
.pScreen
, shape
, x
, y
, &box
))
733 box
= *REGION_EXTENTS(sprite
.hot
.pScreen
, shape
);
734 /* this is rather crude */
753 return; /* should never get here! */
755 } while (!POINT_IN_REGION(sprite
.hot
.pScreen
, shape
, x
, y
, &box
));
765 Bool confineToScreen
,
772 new = sprite
.hotPhys
;
774 new.pScreen
= pScreen
;
776 pScreen
= new.pScreen
;
777 (*pScreen
->CursorLimits
) (pScreen
, cursor
, &sprite
.hotLimits
,
779 sprite
.confined
= confineToScreen
;
780 (* pScreen
->ConstrainCursor
)(pScreen
, &sprite
.physLimits
);
781 if (new.x
< sprite
.physLimits
.x1
)
782 new.x
= sprite
.physLimits
.x1
;
784 if (new.x
>= sprite
.physLimits
.x2
)
785 new.x
= sprite
.physLimits
.x2
- 1;
786 if (new.y
< sprite
.physLimits
.y1
)
787 new.y
= sprite
.physLimits
.y1
;
789 if (new.y
>= sprite
.physLimits
.y2
)
790 new.y
= sprite
.physLimits
.y2
- 1;
793 ConfineToShape(sprite
.hotShape
, &new.x
, &new.y
);
795 if ((pScreen
!= sprite
.hotPhys
.pScreen
) ||
796 (new.x
!= sprite
.hotPhys
.x
) || (new.y
!= sprite
.hotPhys
.y
))
798 if (pScreen
!= sprite
.hotPhys
.pScreen
)
799 sprite
.hotPhys
= new;
800 (*pScreen
->SetCursorPosition
) (pScreen
, new.x
, new.y
, generateEvents
);
802 SyntheticMotion(new.x
, new.y
);
812 if(!noPanoramiXExtension
) {
813 XineramaCheckVirtualMotion(qe
, pWin
);
819 sprite
.hot
.pScreen
= qe
->pScreen
;
820 sprite
.hot
.x
= qe
->event
->u
.keyButtonPointer
.rootX
;
821 sprite
.hot
.y
= qe
->event
->u
.keyButtonPointer
.rootY
;
822 pWin
= inputInfo
.pointer
->grab
? inputInfo
.pointer
->grab
->confineTo
:
829 if (sprite
.hot
.pScreen
!= pWin
->drawable
.pScreen
)
831 sprite
.hot
.pScreen
= pWin
->drawable
.pScreen
;
832 sprite
.hot
.x
= sprite
.hot
.y
= 0;
834 lims
= *REGION_EXTENTS(pWin
->drawable
.pScreen
, &pWin
->borderSize
);
835 if (sprite
.hot
.x
< lims
.x1
)
836 sprite
.hot
.x
= lims
.x1
;
837 else if (sprite
.hot
.x
>= lims
.x2
)
838 sprite
.hot
.x
= lims
.x2
- 1;
839 if (sprite
.hot
.y
< lims
.y1
)
840 sprite
.hot
.y
= lims
.y1
;
841 else if (sprite
.hot
.y
>= lims
.y2
)
842 sprite
.hot
.y
= lims
.y2
- 1;
844 if (wBoundingShape(pWin
))
845 ConfineToShape(&pWin
->borderSize
, &sprite
.hot
.x
, &sprite
.hot
.y
);
849 qe
->pScreen
= sprite
.hot
.pScreen
;
850 qe
->event
->u
.keyButtonPointer
.rootX
= sprite
.hot
.x
;
851 qe
->event
->u
.keyButtonPointer
.rootY
= sprite
.hot
.y
;
855 xeviehot
.x
= sprite
.hot
.x
;
856 xeviehot
.y
= sprite
.hot
.y
;
858 ROOT
= WindowTable
[sprite
.hot
.pScreen
->myNum
];
862 ConfineCursorToWindow(WindowPtr pWin
, Bool generateEvents
, Bool confineToScreen
)
864 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
867 if(!noPanoramiXExtension
) {
868 XineramaConfineCursorToWindow(pWin
, generateEvents
);
873 if (syncEvents
.playingEvents
)
875 CheckVirtualMotion((QdEventPtr
)NULL
, pWin
);
876 SyntheticMotion(sprite
.hot
.x
, sprite
.hot
.y
);
880 sprite
.hotLimits
= *REGION_EXTENTS( pScreen
, &pWin
->borderSize
);
882 sprite
.hotShape
= wBoundingShape(pWin
) ? &pWin
->borderSize
885 CheckPhysLimits(sprite
.current
, generateEvents
, confineToScreen
,
891 PointerConfinedToScreen(void)
893 return sprite
.confined
;
897 * Update the sprite cursor to the given cursor.
899 * ChangeToCursor() will display the new cursor and free the old cursor (if
900 * applicable). If the provided cursor is already the updated cursor, nothing
904 ChangeToCursor(CursorPtr cursor
)
907 if(!noPanoramiXExtension
) {
908 XineramaChangeToCursor(cursor
);
913 if (cursor
!= sprite
.current
)
915 if ((sprite
.current
->bits
->xhot
!= cursor
->bits
->xhot
) ||
916 (sprite
.current
->bits
->yhot
!= cursor
->bits
->yhot
))
917 CheckPhysLimits(cursor
, FALSE
, sprite
.confined
,
919 (*sprite
.hotPhys
.pScreen
->DisplayCursor
) (sprite
.hotPhys
.pScreen
,
921 FreeCursor(sprite
.current
, (Cursor
)0);
922 sprite
.current
= cursor
;
923 sprite
.current
->refcnt
++;
928 * @returns true if b is a descendent of a
931 IsParent(WindowPtr a
, WindowPtr b
)
933 for (b
= b
->parent
; b
; b
= b
->parent
)
934 if (b
== a
) return TRUE
;
939 * Update the cursor displayed on the screen.
941 * Called whenever a cursor may have changed shape or position.
947 GrabPtr grab
= inputInfo
.pointer
->grab
;
949 if (syncEvents
.playingEvents
)
955 ChangeToCursor(grab
->cursor
);
958 if (IsParent(grab
->window
, sprite
.win
))
965 for (; win
; win
= win
->parent
)
966 if (win
->optional
&& win
->optional
->cursor
!= NullCursor
)
968 ChangeToCursor(win
->optional
->cursor
);
974 * @return root window of current active screen.
977 GetCurrentRootWindow(void)
983 * @return window underneath the cursor sprite.
986 GetSpriteWindow(void)
992 * @return current sprite cursor.
995 GetSpriteCursor(void)
997 return sprite
.current
;
1001 * Set x/y current sprite position in screen coordinates.
1004 GetSpritePosition(int *px
, int *py
)
1006 *px
= sprite
.hotPhys
.x
;
1007 *py
= sprite
.hotPhys
.y
;
1012 XineramaGetCursorScreen(void)
1014 if(!noPanoramiXExtension
) {
1015 return sprite
.screen
->myNum
;
1020 #endif /* PANORAMIX */
1022 #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
1025 MonthChangedOrBadTime(xEvent
*xE
)
1027 /* If the ddx/OS is careless about not processing timestamped events from
1028 * different sources in sorted order, then it's possible for time to go
1029 * backwards when it should not. Here we ensure a decent time.
1031 if ((currentTime
.milliseconds
- XE_KBPTR
.time
) > TIMESLOP
)
1032 currentTime
.months
++;
1034 XE_KBPTR
.time
= currentTime
.milliseconds
;
1037 #define NoticeTime(xE) { \
1038 if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
1039 MonthChangedOrBadTime(xE); \
1040 currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
1041 lastDeviceEventTime = currentTime; }
1044 NoticeEventTime(xEvent
*xE
)
1046 if (!syncEvents
.playingEvents
)
1050 /**************************************************************************
1051 * The following procedures deal with synchronous events *
1052 **************************************************************************/
1055 EnqueueEvent(xEvent
*xE
, DeviceIntPtr device
, int count
)
1057 QdEventPtr tail
= *syncEvents
.pendtail
;
1064 /* Fix for key repeating bug. */
1065 if (device
->key
!= NULL
&& device
->key
->xkbInfo
!= NULL
&&
1066 xE
->u
.u
.type
== KeyRelease
)
1067 AccessXCancelRepeatKey(device
->key
->xkbInfo
, xE
->u
.u
.detail
);
1070 if (DeviceEventCallback
)
1072 DeviceEventInfoRec eventinfo
;
1073 /* The RECORD spec says that the root window field of motion events
1074 * must be valid. At this point, it hasn't been filled in yet, so
1075 * we do it here. The long expression below is necessary to get
1076 * the current root window; the apparently reasonable alternative
1077 * GetCurrentRootWindow()->drawable.id doesn't give you the right
1078 * answer on the first motion event after a screen change because
1079 * the data that GetCurrentRootWindow relies on hasn't been
1082 if (xE
->u
.u
.type
== MotionNotify
)
1084 WindowTable
[sprite
.hotPhys
.pScreen
->myNum
]->drawable
.id
;
1085 eventinfo
.events
= xE
;
1086 eventinfo
.count
= count
;
1087 CallCallbacks(&DeviceEventCallback
, (pointer
)&eventinfo
);
1089 if (xE
->u
.u
.type
== MotionNotify
)
1092 if(!noPanoramiXExtension
) {
1093 XE_KBPTR
.rootX
+= panoramiXdataPtr
[sprite
.screen
->myNum
].x
-
1094 panoramiXdataPtr
[0].x
;
1095 XE_KBPTR
.rootY
+= panoramiXdataPtr
[sprite
.screen
->myNum
].y
-
1096 panoramiXdataPtr
[0].y
;
1099 sprite
.hotPhys
.x
= XE_KBPTR
.rootX
;
1100 sprite
.hotPhys
.y
= XE_KBPTR
.rootY
;
1101 /* do motion compression */
1103 (tail
->event
->u
.u
.type
== MotionNotify
) &&
1104 (tail
->pScreen
== sprite
.hotPhys
.pScreen
))
1106 tail
->event
->u
.keyButtonPointer
.rootX
= sprite
.hotPhys
.x
;
1107 tail
->event
->u
.keyButtonPointer
.rootY
= sprite
.hotPhys
.y
;
1108 tail
->event
->u
.keyButtonPointer
.time
= XE_KBPTR
.time
;
1109 tail
->months
= currentTime
.months
;
1113 qe
= (QdEventPtr
)xalloc(sizeof(QdEventRec
) + (count
* sizeof(xEvent
)));
1116 qe
->next
= (QdEventPtr
)NULL
;
1117 qe
->device
= device
;
1118 qe
->pScreen
= sprite
.hotPhys
.pScreen
;
1119 qe
->months
= currentTime
.months
;
1120 qe
->event
= (xEvent
*)(qe
+ 1);
1121 qe
->evcount
= count
;
1122 for (qxE
= qe
->event
; --count
>= 0; qxE
++, xE
++)
1125 syncEvents
.pendtail
= &tail
->next
;
1126 *syncEvents
.pendtail
= qe
;
1130 PlayReleasedEvents(void)
1132 QdEventPtr
*prev
, qe
;
1135 prev
= &syncEvents
.pending
;
1136 while ( (qe
= *prev
) )
1138 if (!qe
->device
->sync
.frozen
)
1141 if (*syncEvents
.pendtail
== *prev
)
1142 syncEvents
.pendtail
= prev
;
1143 if (qe
->event
->u
.u
.type
== MotionNotify
)
1144 CheckVirtualMotion(qe
, NullWindow
);
1145 syncEvents
.time
.months
= qe
->months
;
1146 syncEvents
.time
.milliseconds
= qe
->event
->u
.keyButtonPointer
.time
;
1148 /* Translate back to the sprite screen since processInputProc
1149 will translate from sprite screen to screen 0 upon reentry
1151 if(!noPanoramiXExtension
) {
1152 qe
->event
->u
.keyButtonPointer
.rootX
+=
1153 panoramiXdataPtr
[0].x
-
1154 panoramiXdataPtr
[sprite
.screen
->myNum
].x
;
1155 qe
->event
->u
.keyButtonPointer
.rootY
+=
1156 panoramiXdataPtr
[0].y
-
1157 panoramiXdataPtr
[sprite
.screen
->myNum
].y
;
1160 (*qe
->device
->public.processInputProc
)(qe
->event
, qe
->device
,
1163 for (dev
= inputInfo
.devices
; dev
&& dev
->sync
.frozen
; dev
= dev
->next
)
1167 /* Playing the event may have unfrozen another device. */
1168 /* So to play it safe, restart at the head of the queue */
1169 prev
= &syncEvents
.pending
;
1177 FreezeThaw(DeviceIntPtr dev
, Bool frozen
)
1179 dev
->sync
.frozen
= frozen
;
1181 dev
->public.processInputProc
= dev
->public.enqueueInputProc
;
1183 dev
->public.processInputProc
= dev
->public.realInputProc
;
1187 ComputeFreezes(void)
1189 DeviceIntPtr replayDev
= syncEvents
.replayDev
;
1197 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1198 FreezeThaw(dev
, dev
->sync
.other
|| (dev
->sync
.state
>= FROZEN
));
1199 if (syncEvents
.playingEvents
|| (!replayDev
&& !syncEvents
.pending
))
1201 syncEvents
.playingEvents
= TRUE
;
1204 xE
= replayDev
->sync
.event
;
1205 count
= replayDev
->sync
.evcount
;
1206 syncEvents
.replayDev
= (DeviceIntPtr
)NULL
;
1208 w
= XYToWindow( XE_KBPTR
.rootX
, XE_KBPTR
.rootY
);
1209 for (i
= 0; i
< spriteTraceGood
; i
++)
1211 if (syncEvents
.replayWin
== spriteTrace
[i
])
1213 if (!CheckDeviceGrabs(replayDev
, xE
, i
+1, count
)) {
1214 if (replayDev
->focus
)
1215 DeliverFocusedEvent(replayDev
, xE
, w
, count
);
1217 DeliverDeviceEvents(w
, xE
, NullGrab
, NullWindow
,
1223 /* must not still be in the same stack */
1224 if (replayDev
->focus
)
1225 DeliverFocusedEvent(replayDev
, xE
, w
, count
);
1227 DeliverDeviceEvents(w
, xE
, NullGrab
, NullWindow
, replayDev
, count
);
1230 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1232 if (!dev
->sync
.frozen
)
1234 PlayReleasedEvents();
1238 syncEvents
.playingEvents
= FALSE
;
1239 /* the following may have been skipped during replay, so do it now */
1240 if ((grab
= inputInfo
.pointer
->grab
) && grab
->confineTo
)
1242 if (grab
->confineTo
->drawable
.pScreen
!= sprite
.hotPhys
.pScreen
)
1243 sprite
.hotPhys
.x
= sprite
.hotPhys
.y
= 0;
1244 ConfineCursorToWindow(grab
->confineTo
, TRUE
, TRUE
);
1247 ConfineCursorToWindow(WindowTable
[sprite
.hotPhys
.pScreen
->myNum
],
1254 ScreenRestructured (ScreenPtr pScreen
)
1258 if ((grab
= inputInfo
.pointer
->grab
) && grab
->confineTo
)
1260 if (grab
->confineTo
->drawable
.pScreen
!= sprite
.hotPhys
.pScreen
)
1261 sprite
.hotPhys
.x
= sprite
.hotPhys
.y
= 0;
1262 ConfineCursorToWindow(grab
->confineTo
, TRUE
, TRUE
);
1265 ConfineCursorToWindow(WindowTable
[sprite
.hotPhys
.pScreen
->myNum
],
1271 CheckGrabForSyncs(DeviceIntPtr thisDev
, Bool thisMode
, Bool otherMode
)
1273 GrabPtr grab
= thisDev
->grab
;
1276 if (thisMode
== GrabModeSync
)
1277 thisDev
->sync
.state
= FROZEN_NO_EVENT
;
1279 { /* free both if same client owns both */
1280 thisDev
->sync
.state
= THAWED
;
1281 if (thisDev
->sync
.other
&&
1282 (CLIENT_BITS(thisDev
->sync
.other
->resource
) ==
1283 CLIENT_BITS(grab
->resource
)))
1284 thisDev
->sync
.other
= NullGrab
;
1286 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1290 if (otherMode
== GrabModeSync
)
1291 dev
->sync
.other
= grab
;
1293 { /* free both if same client owns both */
1294 if (dev
->sync
.other
&&
1295 (CLIENT_BITS(dev
->sync
.other
->resource
) ==
1296 CLIENT_BITS(grab
->resource
)))
1297 dev
->sync
.other
= NullGrab
;
1305 * Activate a pointer grab on the given device. A pointer grab will cause all
1306 * core pointer events to be delivered to the grabbing client only. Can cause
1307 * the cursor to change if a grab cursor is set.
1309 * As a pointer grab can only be issued on the core devices, mouse is always
1310 * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
1312 * @param mouse The device to grab.
1313 * @param grab The grab structure, needs to be setup.
1314 * @param autoGrab True if the grab was caused by a button down event and not
1315 * explicitely by a client.
1318 ActivatePointerGrab(DeviceIntPtr mouse
, GrabPtr grab
,
1319 TimeStamp time
, Bool autoGrab
)
1321 WindowPtr oldWin
= (mouse
->grab
) ? mouse
->grab
->window
1324 if (grab
->confineTo
)
1326 if (grab
->confineTo
->drawable
.pScreen
!= sprite
.hotPhys
.pScreen
)
1327 sprite
.hotPhys
.x
= sprite
.hotPhys
.y
= 0;
1328 ConfineCursorToWindow(grab
->confineTo
, FALSE
, TRUE
);
1330 DoEnterLeaveEvents(oldWin
, grab
->window
, NotifyGrab
);
1331 mouse
->valuator
->motionHintWindow
= NullWindow
;
1332 if (syncEvents
.playingEvents
)
1333 mouse
->grabTime
= syncEvents
.time
;
1335 mouse
->grabTime
= time
;
1337 grab
->cursor
->refcnt
++;
1338 mouse
->activeGrab
= *grab
;
1339 mouse
->grab
= &mouse
->activeGrab
;
1340 mouse
->fromPassiveGrab
= autoGrab
;
1342 CheckGrabForSyncs(mouse
,(Bool
)grab
->pointerMode
, (Bool
)grab
->keyboardMode
);
1346 * Delete grab on given device, update the sprite.
1348 * As a pointer grab can only be issued on the core devices, mouse is always
1349 * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
1352 DeactivatePointerGrab(DeviceIntPtr mouse
)
1354 GrabPtr grab
= mouse
->grab
;
1357 mouse
->valuator
->motionHintWindow
= NullWindow
;
1358 mouse
->grab
= NullGrab
;
1359 mouse
->sync
.state
= NOT_GRABBED
;
1360 mouse
->fromPassiveGrab
= FALSE
;
1361 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1363 if (dev
->sync
.other
== grab
)
1364 dev
->sync
.other
= NullGrab
;
1366 DoEnterLeaveEvents(grab
->window
, sprite
.win
, NotifyUngrab
);
1367 if (grab
->confineTo
)
1368 ConfineCursorToWindow(ROOT
, FALSE
, FALSE
);
1371 FreeCursor(grab
->cursor
, (Cursor
)0);
1376 * Activate a keyboard grab on the given device.
1378 * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1381 ActivateKeyboardGrab(DeviceIntPtr keybd
, GrabPtr grab
, TimeStamp time
, Bool passive
)
1386 oldWin
= keybd
->grab
->window
;
1387 else if (keybd
->focus
)
1388 oldWin
= keybd
->focus
->win
;
1390 oldWin
= sprite
.win
;
1391 if (oldWin
== FollowKeyboardWin
)
1392 oldWin
= inputInfo
.keyboard
->focus
->win
;
1393 if (keybd
->valuator
)
1394 keybd
->valuator
->motionHintWindow
= NullWindow
;
1395 DoFocusEvents(keybd
, oldWin
, grab
->window
, NotifyGrab
);
1396 if (syncEvents
.playingEvents
)
1397 keybd
->grabTime
= syncEvents
.time
;
1399 keybd
->grabTime
= time
;
1400 keybd
->activeGrab
= *grab
;
1401 keybd
->grab
= &keybd
->activeGrab
;
1402 keybd
->fromPassiveGrab
= passive
;
1403 CheckGrabForSyncs(keybd
, (Bool
)grab
->keyboardMode
, (Bool
)grab
->pointerMode
);
1407 * Delete keyboard grab for the given device.
1410 DeactivateKeyboardGrab(DeviceIntPtr keybd
)
1412 GrabPtr grab
= keybd
->grab
;
1414 WindowPtr focusWin
= keybd
->focus
? keybd
->focus
->win
1417 if (focusWin
== FollowKeyboardWin
)
1418 focusWin
= inputInfo
.keyboard
->focus
->win
;
1419 if (keybd
->valuator
)
1420 keybd
->valuator
->motionHintWindow
= NullWindow
;
1421 keybd
->grab
= NullGrab
;
1422 keybd
->sync
.state
= NOT_GRABBED
;
1423 keybd
->fromPassiveGrab
= FALSE
;
1424 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1426 if (dev
->sync
.other
== grab
)
1427 dev
->sync
.other
= NullGrab
;
1429 DoFocusEvents(keybd
, grab
->window
, focusWin
, NotifyUngrab
);
1434 AllowSome(ClientPtr client
, TimeStamp time
, DeviceIntPtr thisDev
, int newState
)
1436 Bool thisGrabbed
, otherGrabbed
, othersFrozen
, thisSynced
;
1440 thisGrabbed
= thisDev
->grab
&& SameClient(thisDev
->grab
, client
);
1442 otherGrabbed
= FALSE
;
1443 othersFrozen
= TRUE
;
1444 grabTime
= thisDev
->grabTime
;
1445 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1449 if (dev
->grab
&& SameClient(dev
->grab
, client
))
1451 if (!(thisGrabbed
|| otherGrabbed
) ||
1452 (CompareTimeStamps(dev
->grabTime
, grabTime
) == LATER
))
1453 grabTime
= dev
->grabTime
;
1454 otherGrabbed
= TRUE
;
1455 if (thisDev
->sync
.other
== dev
->grab
)
1457 if (dev
->sync
.state
< FROZEN
)
1458 othersFrozen
= FALSE
;
1460 else if (!dev
->sync
.other
|| !SameClient(dev
->sync
.other
, client
))
1461 othersFrozen
= FALSE
;
1463 if (!((thisGrabbed
&& thisDev
->sync
.state
>= FROZEN
) || thisSynced
))
1465 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
1466 (CompareTimeStamps(time
, grabTime
) == EARLIER
))
1470 case THAWED
: /* Async */
1472 thisDev
->sync
.state
= THAWED
;
1474 thisDev
->sync
.other
= NullGrab
;
1477 case FREEZE_NEXT_EVENT
: /* Sync */
1480 thisDev
->sync
.state
= FREEZE_NEXT_EVENT
;
1482 thisDev
->sync
.other
= NullGrab
;
1486 case THAWED_BOTH
: /* AsyncBoth */
1489 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1491 if (dev
->grab
&& SameClient(dev
->grab
, client
))
1492 dev
->sync
.state
= THAWED
;
1493 if (dev
->sync
.other
&& SameClient(dev
->sync
.other
, client
))
1494 dev
->sync
.other
= NullGrab
;
1499 case FREEZE_BOTH_NEXT_EVENT
: /* SyncBoth */
1502 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1504 if (dev
->grab
&& SameClient(dev
->grab
, client
))
1505 dev
->sync
.state
= FREEZE_BOTH_NEXT_EVENT
;
1506 if (dev
->sync
.other
&& SameClient(dev
->sync
.other
, client
))
1507 dev
->sync
.other
= NullGrab
;
1512 case NOT_GRABBED
: /* Replay */
1513 if (thisGrabbed
&& thisDev
->sync
.state
== FROZEN_WITH_EVENT
)
1516 thisDev
->sync
.other
= NullGrab
;
1517 syncEvents
.replayDev
= thisDev
;
1518 syncEvents
.replayWin
= thisDev
->grab
->window
;
1519 (*thisDev
->DeactivateGrab
)(thisDev
);
1520 syncEvents
.replayDev
= (DeviceIntPtr
)NULL
;
1523 case THAW_OTHERS
: /* AsyncOthers */
1526 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1530 if (dev
->grab
&& SameClient(dev
->grab
, client
))
1531 dev
->sync
.state
= THAWED
;
1532 if (dev
->sync
.other
&& SameClient(dev
->sync
.other
, client
))
1533 dev
->sync
.other
= NullGrab
;
1542 * Server-side protocol handling for AllowEvents request.
1544 * Release some events from a frozen device. Only applicable for core devices.
1547 ProcAllowEvents(ClientPtr client
)
1550 DeviceIntPtr mouse
= inputInfo
.pointer
;
1551 DeviceIntPtr keybd
= inputInfo
.keyboard
;
1552 REQUEST(xAllowEventsReq
);
1554 REQUEST_SIZE_MATCH(xAllowEventsReq
);
1555 time
= ClientTimeToServerTime(stuff
->time
);
1556 switch (stuff
->mode
)
1559 AllowSome(client
, time
, mouse
, NOT_GRABBED
);
1562 AllowSome(client
, time
, mouse
, FREEZE_NEXT_EVENT
);
1565 AllowSome(client
, time
, mouse
, THAWED
);
1567 case ReplayKeyboard
:
1568 AllowSome(client
, time
, keybd
, NOT_GRABBED
);
1571 AllowSome(client
, time
, keybd
, FREEZE_NEXT_EVENT
);
1574 AllowSome(client
, time
, keybd
, THAWED
);
1577 AllowSome(client
, time
, keybd
, FREEZE_BOTH_NEXT_EVENT
);
1580 AllowSome(client
, time
, keybd
, THAWED_BOTH
);
1583 client
->errorValue
= stuff
->mode
;
1590 * Deactivate grabs from any device that has been grabbed by the client.
1593 ReleaseActiveGrabs(ClientPtr client
)
1598 /* XXX CloseDownClient should remove passive grabs before
1599 * releasing active grabs.
1603 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
1605 if (dev
->grab
&& SameClient(dev
->grab
, client
))
1607 (*dev
->DeactivateGrab
)(dev
);
1614 /**************************************************************************
1615 * The following procedures deal with delivering events *
1616 **************************************************************************/
1619 * Deliver the given events to the given client.
1621 * More than one event may be delivered at a time. This is the case with
1622 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1624 * TryClientEvents() is the last station before actually writing the events to
1625 * the socket. Anything that is not filtered here, will get delivered to the
1627 * An event is only delivered if
1628 * - mask and filter match up.
1629 * - no other client has a grab on the device that caused the event.
1632 * @param client The target client to deliver to.
1633 * @param pEvents The events to be delivered.
1634 * @param count Number of elements in pEvents.
1635 * @param mask Event mask as set by the window.
1636 * @param filter Mask based on event type.
1637 * @param grab Possible grab on the device that caused the event.
1639 * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1643 TryClientEvents (ClientPtr client
, xEvent
*pEvents
, int count
, Mask mask
,
1644 Mask filter
, GrabPtr grab
)
1650 ErrorF("Event([%d, %d], mask=0x%x), client=%d",
1651 pEvents
->u
.u
.type
, pEvents
->u
.u
.detail
, mask
, client
->index
);
1653 if ((client
) && (client
!= serverClient
) && (!client
->clientGone
) &&
1654 ((filter
== CantBeFiltered
) || (mask
& filter
)))
1656 if (grab
&& !SameClient(grab
, client
))
1657 return -1; /* don't send, but notify caller */
1658 type
= pEvents
->u
.u
.type
;
1659 if (type
== MotionNotify
)
1661 if (mask
& PointerMotionHintMask
)
1663 if (WID(inputInfo
.pointer
->valuator
->motionHintWindow
) ==
1664 pEvents
->u
.keyButtonPointer
.event
)
1668 ErrorF("motionHintWindow == keyButtonPointer.event\n");
1670 return 1; /* don't send, but pretend we did */
1672 pEvents
->u
.u
.detail
= NotifyHint
;
1676 pEvents
->u
.u
.detail
= NotifyNormal
;
1682 if ((type
== DeviceMotionNotify
) &&
1683 MaybeSendDeviceMotionNotifyHint
1684 ((deviceKeyButtonPointer
*)pEvents
, mask
) != 0)
1689 if (type
!= KeymapNotify
)
1691 /* all extension events must have a sequence number */
1692 for (i
= 0; i
< count
; i
++)
1693 pEvents
[i
].u
.u
.sequenceNumber
= client
->sequence
;
1696 if (BitIsOn(criticalEvents
, type
))
1698 #ifdef SMART_SCHEDULE
1699 if (client
->smart_priority
< SMART_MAX_PRIORITY
)
1700 client
->smart_priority
++;
1702 SetCriticalOutputPending();
1705 WriteEventsToClient(client
, count
, pEvents
);
1707 ErrorF( " delivered\n");
1721 * Deliver events to a window. At this point, we do not yet know if the event
1722 * actually needs to be delivered. May activate a grab if the event is a
1725 * More than one event may be delivered at a time. This is the case with
1726 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1728 * @param pWin The window that would get the event.
1729 * @param pEvents The events to be delivered.
1730 * @param count Number of elements in pEvents.
1731 * @param filter Mask based on event type.
1732 * @param grab Possible grab on the device that caused the event.
1733 * @param mskidx Mask index, depending on device that caused event.
1735 * @return Number of events delivered to various clients.
1738 DeliverEventsToWindow(WindowPtr pWin
, xEvent
*pEvents
, int count
,
1739 Mask filter
, GrabPtr grab
, int mskidx
)
1741 int deliveries
= 0, nondeliveries
= 0;
1743 InputClients
*other
;
1744 ClientPtr client
= NullClient
;
1745 Mask deliveryMask
= 0; /* If a grab occurs due to a button press, then
1746 this mask is the mask of the grab. */
1747 int type
= pEvents
->u
.u
.type
;
1749 /* CantBeFiltered means only window owner gets the event */
1750 if ((filter
== CantBeFiltered
) || !(type
& EXTENSION_EVENT_BASE
))
1752 /* if nobody ever wants to see this event, skip some work */
1753 if (filter
!= CantBeFiltered
&&
1754 !((wOtherEventMasks(pWin
)|pWin
->eventMask
) & filter
))
1756 if ( (attempt
= TryClientEvents(wClient(pWin
), pEvents
, count
,
1757 pWin
->eventMask
, filter
, grab
)) )
1762 client
= wClient(pWin
);
1763 deliveryMask
= pWin
->eventMask
;
1768 if (filter
!= CantBeFiltered
)
1770 if (type
& EXTENSION_EVENT_BASE
)
1772 OtherInputMasks
*inputMasks
;
1774 inputMasks
= wOtherInputMasks(pWin
);
1776 !(inputMasks
->inputEvents
[mskidx
] & filter
))
1778 other
= inputMasks
->inputClients
;
1781 other
= (InputClients
*)wOtherClients(pWin
);
1782 for (; other
; other
= other
->next
)
1784 if ( (attempt
= TryClientEvents(rClient(other
), pEvents
, count
,
1785 other
->mask
[mskidx
], filter
, grab
)) )
1790 client
= rClient(other
);
1791 deliveryMask
= other
->mask
[mskidx
];
1797 if ((type
== ButtonPress
) && deliveries
&& (!grab
))
1801 tempGrab
.device
= inputInfo
.pointer
;
1802 tempGrab
.resource
= client
->clientAsMask
;
1803 tempGrab
.window
= pWin
;
1804 tempGrab
.ownerEvents
= (deliveryMask
& OwnerGrabButtonMask
) ? TRUE
: FALSE
;
1805 tempGrab
.eventMask
= deliveryMask
;
1806 tempGrab
.keyboardMode
= GrabModeAsync
;
1807 tempGrab
.pointerMode
= GrabModeAsync
;
1808 tempGrab
.confineTo
= NullWindow
;
1809 tempGrab
.cursor
= NullCursor
;
1810 (*inputInfo
.pointer
->ActivateGrab
)(inputInfo
.pointer
, &tempGrab
,
1813 else if ((type
== MotionNotify
) && deliveries
)
1814 inputInfo
.pointer
->valuator
->motionHintWindow
= pWin
;
1818 if (((type
== DeviceMotionNotify
)
1820 || (type
== DeviceButtonPress
)
1823 CheckDeviceGrabAndHintWindow (pWin
, type
,
1824 (deviceKeyButtonPointer
*) pEvents
,
1825 grab
, client
, deliveryMask
);
1830 return nondeliveries
;
1833 /* If the event goes to dontClient, don't send it and return 0. if
1834 send works, return 1 or if send didn't work, return 2.
1835 Only works for core events.
1840 XineramaTryClientEventsResult(
1846 if ((client
) && (client
!= serverClient
) && (!client
->clientGone
) &&
1847 ((filter
== CantBeFiltered
) || (mask
& filter
)))
1849 if (grab
&& !SameClient(grab
, client
)) return -1;
1857 * Try to deliver events to the interested parties.
1859 * @param pWin The window that would get the event.
1860 * @param pEvents The events to be delivered.
1861 * @param count Number of elements in pEvents.
1862 * @param filter Mask based on event type.
1863 * @param dontClient Don't deliver to the dontClient.
1866 MaybeDeliverEventsToClient(WindowPtr pWin
, xEvent
*pEvents
,
1867 int count
, Mask filter
, ClientPtr dontClient
)
1869 OtherClients
*other
;
1872 if (pWin
->eventMask
& filter
)
1874 if (wClient(pWin
) == dontClient
)
1877 if(!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
)
1878 return XineramaTryClientEventsResult(
1879 wClient(pWin
), NullGrab
, pWin
->eventMask
, filter
);
1881 return TryClientEvents(wClient(pWin
), pEvents
, count
,
1882 pWin
->eventMask
, filter
, NullGrab
);
1884 for (other
= wOtherClients(pWin
); other
; other
= other
->next
)
1886 if (other
->mask
& filter
)
1888 if (SameClient(other
, dontClient
))
1891 if(!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
)
1892 return XineramaTryClientEventsResult(
1893 rClient(other
), NullGrab
, other
->mask
, filter
);
1895 return TryClientEvents(rClient(other
), pEvents
, count
,
1896 other
->mask
, filter
, NullGrab
);
1903 * Adjust event fields to comply with the window properties.
1905 * @param xE Event to be modified in place
1906 * @param pWin The window to get the information from.
1907 * @param child Child window setting for event (if applicable)
1908 * @param calcChild If True, calculate the child window.
1911 FixUpEventFromWindow(
1919 WindowPtr w
=spriteTrace
[spriteTraceGood
-1];
1920 /* If the search ends up past the root should the child field be
1921 set to none or should the value in the argument be passed
1922 through. It probably doesn't matter since everyone calls
1923 this function with child == None anyway. */
1927 /* If the source window is same as event window, child should be
1928 none. Don't bother going all all the way back to the root. */
1936 if (w
->parent
== pWin
)
1938 child
= w
->drawable
.id
;
1944 XE_KBPTR
.root
= ROOT
->drawable
.id
;
1945 XE_KBPTR
.event
= pWin
->drawable
.id
;
1946 if (sprite
.hot
.pScreen
== pWin
->drawable
.pScreen
)
1948 XE_KBPTR
.sameScreen
= xTrue
;
1949 XE_KBPTR
.child
= child
;
1951 XE_KBPTR
.rootX
- pWin
->drawable
.x
;
1953 XE_KBPTR
.rootY
- pWin
->drawable
.y
;
1957 XE_KBPTR
.sameScreen
= xFalse
;
1958 XE_KBPTR
.child
= None
;
1959 XE_KBPTR
.eventX
= 0;
1960 XE_KBPTR
.eventY
= 0;
1965 * Deliver events caused by input devices. Called for all core input events
1966 * and XI events. No filtering of events happens before DeliverDeviceEvents(),
1967 * it will be called for any event that comes out of the event queue.
1969 * For all core events, dev is either inputInfo.pointer or inputInfo.keyboard.
1970 * For all extension events, dev is the device that caused the event.
1972 * @param pWin Window to deliver event to.
1973 * @param xE Events to deliver.
1974 * @param grab Possible grab on a device.
1975 * @param stopAt Don't recurse up to the root window.
1976 * @param dev The device that is responsible for the event.
1977 * @param count number of events in xE.
1981 DeliverDeviceEvents(WindowPtr pWin
, xEvent
*xE
, GrabPtr grab
,
1982 WindowPtr stopAt
, DeviceIntPtr dev
, int count
)
1984 Window child
= None
;
1985 int type
= xE
->u
.u
.type
;
1986 Mask filter
= filters
[type
];
1989 if (type
& EXTENSION_EVENT_BASE
)
1991 OtherInputMasks
*inputMasks
;
1992 int mskidx
= dev
->id
;
1994 inputMasks
= wOtherInputMasks(pWin
);
1995 if (inputMasks
&& !(filter
& inputMasks
->deliverableEvents
[mskidx
]))
1999 if (inputMasks
&& (inputMasks
->inputEvents
[mskidx
] & filter
))
2001 FixUpEventFromWindow(xE
, pWin
, child
, FALSE
);
2002 deliveries
= DeliverEventsToWindow(pWin
, xE
, count
, filter
,
2007 if ((deliveries
< 0) ||
2010 (filter
& inputMasks
->dontPropagateMask
[mskidx
])))
2012 child
= pWin
->drawable
.id
;
2013 pWin
= pWin
->parent
;
2015 inputMasks
= wOtherInputMasks(pWin
);
2020 if (!(filter
& pWin
->deliverableEvents
))
2024 if ((wOtherEventMasks(pWin
)|pWin
->eventMask
) & filter
)
2026 FixUpEventFromWindow(xE
, pWin
, child
, FALSE
);
2027 deliveries
= DeliverEventsToWindow(pWin
, xE
, count
, filter
,
2032 if ((deliveries
< 0) ||
2034 (filter
& wDontPropagateMask(pWin
)))
2036 child
= pWin
->drawable
.id
;
2037 pWin
= pWin
->parent
;
2044 * Deliver event to a window and it's immediate parent. Used for most window
2045 * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2046 * propagate up the tree or extension events
2048 * In case of a ReparentNotify event, the event will be delivered to the
2049 * otherParent as well.
2051 * @param pWin Window to deliver events to.
2052 * @param xE Events to deliver.
2053 * @param count number of events in xE.
2054 * @param otherParent Used for ReparentNotify events.
2057 DeliverEvents(WindowPtr pWin
, xEvent
*xE
, int count
,
2058 WindowPtr otherParent
)
2064 if(!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
)
2070 filter
= filters
[xE
->u
.u
.type
];
2071 if ((filter
& SubstructureNotifyMask
) && (xE
->u
.u
.type
!= CreateNotify
))
2072 xE
->u
.destroyNotify
.event
= pWin
->drawable
.id
;
2073 if (filter
!= StructureAndSubMask
)
2074 return DeliverEventsToWindow(pWin
, xE
, count
, filter
, NullGrab
, 0);
2075 deliveries
= DeliverEventsToWindow(pWin
, xE
, count
, StructureNotifyMask
,
2079 xE
->u
.destroyNotify
.event
= pWin
->parent
->drawable
.id
;
2080 deliveries
+= DeliverEventsToWindow(pWin
->parent
, xE
, count
,
2081 SubstructureNotifyMask
, NullGrab
,
2083 if (xE
->u
.u
.type
== ReparentNotify
)
2085 xE
->u
.destroyNotify
.event
= otherParent
->drawable
.id
;
2086 deliveries
+= DeliverEventsToWindow(otherParent
, xE
, count
,
2087 SubstructureNotifyMask
,
2096 PointInBorderSize(WindowPtr pWin
, int x
, int y
)
2100 if(POINT_IN_REGION(pWin
->drawable
.pScreen
, &pWin
->borderSize
, x
, y
, &box
))
2104 if(!noPanoramiXExtension
&& XineramaSetWindowPntrs(pWin
)) {
2107 for(i
= 1; i
< PanoramiXNumScreens
; i
++) {
2108 if(POINT_IN_REGION(sprite
.screen
,
2109 &sprite
.windows
[i
]->borderSize
,
2110 x
+ panoramiXdataPtr
[0].x
- panoramiXdataPtr
[i
].x
,
2111 y
+ panoramiXdataPtr
[0].y
- panoramiXdataPtr
[i
].y
,
2121 * Traversed from the root window to the window at the position x/y. While
2122 * traversing, it sets up the traversal history in the spriteTrace array.
2123 * After completing, the spriteTrace history is set in the following way:
2124 * spriteTrace[0] ... root window
2125 * spriteTrace[1] ... top level window that encloses x/y
2127 * spriteTrace[spriteTraceGood - 1] ... window at x/y
2129 * @returns the window at the given coordinates.
2132 XYToWindow(int x
, int y
)
2137 spriteTraceGood
= 1; /* root window still there */
2138 pWin
= ROOT
->firstChild
;
2141 if ((pWin
->mapped
) &&
2142 (x
>= pWin
->drawable
.x
- wBorderWidth (pWin
)) &&
2143 (x
< pWin
->drawable
.x
+ (int)pWin
->drawable
.width
+
2144 wBorderWidth(pWin
)) &&
2145 (y
>= pWin
->drawable
.y
- wBorderWidth (pWin
)) &&
2146 (y
< pWin
->drawable
.y
+ (int)pWin
->drawable
.height
+
2147 wBorderWidth (pWin
))
2149 /* When a window is shaped, a further check
2150 * is made to see if the point is inside
2153 && (!wBoundingShape(pWin
) || PointInBorderSize(pWin
, x
, y
))
2154 && (!wInputShape(pWin
) ||
2155 POINT_IN_REGION(pWin
->drawable
.pScreen
,
2157 x
- pWin
->drawable
.x
,
2158 y
- pWin
->drawable
.y
, &box
))
2162 if (spriteTraceGood
>= spriteTraceSize
)
2164 spriteTraceSize
+= 10;
2165 Must_have_memory
= TRUE
; /* XXX */
2166 spriteTrace
= (WindowPtr
*)xrealloc(
2167 spriteTrace
, spriteTraceSize
*sizeof(WindowPtr
));
2168 Must_have_memory
= FALSE
; /* XXX */
2170 spriteTrace
[spriteTraceGood
++] = pWin
;
2171 pWin
= pWin
->firstChild
;
2174 pWin
= pWin
->nextSib
;
2176 return spriteTrace
[spriteTraceGood
-1];
2180 * Update the sprite coordinates based on the event. Update the cursor
2181 * position, then update the event with the new coordinates that may have been
2182 * changed. If the window underneath the sprite has changed, change to new
2183 * cursor and send enter/leave events.
2186 CheckMotion(xEvent
*xE
)
2188 WindowPtr prevSpriteWin
= sprite
.win
;
2191 if(!noPanoramiXExtension
)
2192 return XineramaCheckMotion(xE
);
2195 if (xE
&& !syncEvents
.playingEvents
)
2197 if (sprite
.hot
.pScreen
!= sprite
.hotPhys
.pScreen
)
2199 sprite
.hot
.pScreen
= sprite
.hotPhys
.pScreen
;
2200 ROOT
= WindowTable
[sprite
.hot
.pScreen
->myNum
];
2202 sprite
.hot
.x
= XE_KBPTR
.rootX
;
2203 sprite
.hot
.y
= XE_KBPTR
.rootY
;
2204 if (sprite
.hot
.x
< sprite
.physLimits
.x1
)
2205 sprite
.hot
.x
= sprite
.physLimits
.x1
;
2206 else if (sprite
.hot
.x
>= sprite
.physLimits
.x2
)
2207 sprite
.hot
.x
= sprite
.physLimits
.x2
- 1;
2208 if (sprite
.hot
.y
< sprite
.physLimits
.y1
)
2209 sprite
.hot
.y
= sprite
.physLimits
.y1
;
2210 else if (sprite
.hot
.y
>= sprite
.physLimits
.y2
)
2211 sprite
.hot
.y
= sprite
.physLimits
.y2
- 1;
2213 if (sprite
.hotShape
)
2214 ConfineToShape(sprite
.hotShape
, &sprite
.hot
.x
, &sprite
.hot
.y
);
2217 xeviehot
.x
= sprite
.hot
.x
;
2218 xeviehot
.y
= sprite
.hot
.y
;
2220 sprite
.hotPhys
= sprite
.hot
;
2221 if ((sprite
.hotPhys
.x
!= XE_KBPTR
.rootX
) ||
2222 (sprite
.hotPhys
.y
!= XE_KBPTR
.rootY
))
2224 (*sprite
.hotPhys
.pScreen
->SetCursorPosition
)(
2225 sprite
.hotPhys
.pScreen
,
2226 sprite
.hotPhys
.x
, sprite
.hotPhys
.y
, FALSE
);
2228 XE_KBPTR
.rootX
= sprite
.hot
.x
;
2229 XE_KBPTR
.rootY
= sprite
.hot
.y
;
2235 sprite
.win
= XYToWindow(sprite
.hot
.x
, sprite
.hot
.y
);
2237 if (!(sprite
.win
->deliverableEvents
&
2238 Motion_Filter(inputInfo
.pointer
->button
))
2239 !syncEvents
.playingEvents
)
2241 /* XXX Do PointerNonInterestBox here */
2244 if (sprite
.win
!= prevSpriteWin
)
2246 if (prevSpriteWin
!= NullWindow
) {
2248 UpdateCurrentTimeIf();
2249 DoEnterLeaveEvents(prevSpriteWin
, sprite
.win
, NotifyNormal
);
2258 * Windows have restructured, we need to update the sprite position and the
2262 WindowsRestructured(void)
2264 (void) CheckMotion((xEvent
*)NULL
);
2268 /* This was added to support reconfiguration under Xdmx. The problem is
2269 * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin
2270 * other than 0,0, the information in the private sprite structure must
2271 * be updated accordingly, or XYToWindow (and other routines) will not
2272 * compute correctly. */
2273 void ReinitializeRootWindow(WindowPtr win
, int xoff
, int yoff
)
2277 if (noPanoramiXExtension
) return;
2279 sprite
.hot
.x
-= xoff
;
2280 sprite
.hot
.y
-= yoff
;
2282 sprite
.hotPhys
.x
-= xoff
;
2283 sprite
.hotPhys
.y
-= yoff
;
2285 sprite
.hotLimits
.x1
-= xoff
;
2286 sprite
.hotLimits
.y1
-= yoff
;
2287 sprite
.hotLimits
.x2
-= xoff
;
2288 sprite
.hotLimits
.y2
-= yoff
;
2290 if (REGION_NOTEMPTY(sprite
.screen
, &sprite
.Reg1
))
2291 REGION_TRANSLATE(sprite
.screen
, &sprite
.Reg1
, xoff
, yoff
);
2292 if (REGION_NOTEMPTY(sprite
.screen
, &sprite
.Reg2
))
2293 REGION_TRANSLATE(sprite
.screen
, &sprite
.Reg2
, xoff
, yoff
);
2295 /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
2296 if ((grab
= inputInfo
.pointer
->grab
) && grab
->confineTo
) {
2297 if (grab
->confineTo
->drawable
.pScreen
!= sprite
.hotPhys
.pScreen
)
2298 sprite
.hotPhys
.x
= sprite
.hotPhys
.y
= 0;
2299 ConfineCursorToWindow(grab
->confineTo
, TRUE
, TRUE
);
2301 ConfineCursorToWindow(WindowTable
[sprite
.hotPhys
.pScreen
->myNum
],
2307 * Set the given window to sane values, display the cursor in the center of
2308 * the screen. Called from main() with the root window on the first screen.
2311 DefineInitialRootWindow(WindowPtr win
)
2313 ScreenPtr pScreen
= win
->drawable
.pScreen
;
2315 sprite
.hotPhys
.pScreen
= pScreen
;
2316 sprite
.hotPhys
.x
= pScreen
->width
/ 2;
2317 sprite
.hotPhys
.y
= pScreen
->height
/ 2;
2318 sprite
.hot
= sprite
.hotPhys
;
2319 sprite
.hotLimits
.x2
= pScreen
->width
;
2320 sprite
.hotLimits
.y2
= pScreen
->height
;
2325 sprite
.current
= wCursor (win
);
2326 sprite
.current
->refcnt
++;
2327 spriteTraceGood
= 1;
2329 (*pScreen
->CursorLimits
) (
2330 pScreen
, sprite
.current
, &sprite
.hotLimits
, &sprite
.physLimits
);
2331 sprite
.confined
= FALSE
;
2332 (*pScreen
->ConstrainCursor
) (pScreen
, &sprite
.physLimits
);
2333 (*pScreen
->SetCursorPosition
) (pScreen
, sprite
.hot
.x
, sprite
.hot
.y
, FALSE
);
2334 (*pScreen
->DisplayCursor
) (pScreen
, sprite
.current
);
2337 if(!noPanoramiXExtension
) {
2338 sprite
.hotLimits
.x1
= -panoramiXdataPtr
[0].x
;
2339 sprite
.hotLimits
.y1
= -panoramiXdataPtr
[0].y
;
2340 sprite
.hotLimits
.x2
= PanoramiXPixWidth
- panoramiXdataPtr
[0].x
;
2341 sprite
.hotLimits
.y2
= PanoramiXPixHeight
- panoramiXdataPtr
[0].y
;
2342 sprite
.physLimits
= sprite
.hotLimits
;
2343 sprite
.confineWin
= NullWindow
;
2345 sprite
.hotShape
= NullRegion
;
2347 sprite
.screen
= pScreen
;
2348 /* gotta UNINIT these someplace */
2349 REGION_NULL(pScreen
, &sprite
.Reg1
);
2350 REGION_NULL(pScreen
, &sprite
.Reg2
);
2356 * This does not take any shortcuts, and even ignores its argument, since
2357 * it does not happen very often, and one has to walk up the tree since
2358 * this might be a newly instantiated cursor for an intermediate window
2359 * between the one the pointer is in and the one that the last cursor was
2360 * instantiated from.
2363 WindowHasNewCursor(WindowPtr pWin
)
2369 NewCurrentScreen(ScreenPtr newScreen
, int x
, int y
)
2371 sprite
.hotPhys
.x
= x
;
2372 sprite
.hotPhys
.y
= y
;
2374 if(!noPanoramiXExtension
) {
2375 sprite
.hotPhys
.x
+= panoramiXdataPtr
[newScreen
->myNum
].x
-
2376 panoramiXdataPtr
[0].x
;
2377 sprite
.hotPhys
.y
+= panoramiXdataPtr
[newScreen
->myNum
].y
-
2378 panoramiXdataPtr
[0].y
;
2379 if (newScreen
!= sprite
.screen
) {
2380 sprite
.screen
= newScreen
;
2381 /* Make sure we tell the DDX to update its copy of the screen */
2382 if(sprite
.confineWin
)
2383 XineramaConfineCursorToWindow(sprite
.confineWin
, TRUE
);
2385 XineramaConfineCursorToWindow(WindowTable
[0], TRUE
);
2386 /* if the pointer wasn't confined, the DDX won't get
2387 told of the pointer warp so we reposition it here */
2388 if(!syncEvents
.playingEvents
)
2389 (*sprite
.screen
->SetCursorPosition
)(sprite
.screen
,
2390 sprite
.hotPhys
.x
+ panoramiXdataPtr
[0].x
-
2391 panoramiXdataPtr
[sprite
.screen
->myNum
].x
,
2392 sprite
.hotPhys
.y
+ panoramiXdataPtr
[0].y
-
2393 panoramiXdataPtr
[sprite
.screen
->myNum
].y
, FALSE
);
2397 if (newScreen
!= sprite
.hotPhys
.pScreen
)
2398 ConfineCursorToWindow(WindowTable
[newScreen
->myNum
], TRUE
, FALSE
);
2404 XineramaPointInWindowIsVisible(
2410 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
2414 if (!pWin
->realized
) return FALSE
;
2416 if (POINT_IN_REGION(pScreen
, &pWin
->borderClip
, x
, y
, &box
))
2419 if(!XineramaSetWindowPntrs(pWin
)) return FALSE
;
2421 xoff
= x
+ panoramiXdataPtr
[0].x
;
2422 yoff
= y
+ panoramiXdataPtr
[0].y
;
2424 for(i
= 1; i
< PanoramiXNumScreens
; i
++) {
2425 pWin
= sprite
.windows
[i
];
2426 pScreen
= pWin
->drawable
.pScreen
;
2427 x
= xoff
- panoramiXdataPtr
[i
].x
;
2428 y
= yoff
- panoramiXdataPtr
[i
].y
;
2430 if(POINT_IN_REGION(pScreen
, &pWin
->borderClip
, x
, y
, &box
)
2431 && (!wInputShape(pWin
) ||
2432 POINT_IN_REGION(pWin
->drawable
.pScreen
,
2434 x
- pWin
->drawable
.x
,
2435 y
- pWin
->drawable
.y
, &box
)))
2444 XineramaWarpPointer(ClientPtr client
)
2446 WindowPtr dest
= NULL
;
2449 REQUEST(xWarpPointerReq
);
2452 if (stuff
->dstWid
!= None
) {
2453 rc
= dixLookupWindow(&dest
, stuff
->dstWid
, client
, DixReadAccess
);
2457 x
= sprite
.hotPhys
.x
;
2458 y
= sprite
.hotPhys
.y
;
2460 if (stuff
->srcWid
!= None
)
2463 XID winID
= stuff
->srcWid
;
2466 rc
= dixLookupWindow(&source
, winID
, client
, DixReadAccess
);
2470 winX
= source
->drawable
.x
;
2471 winY
= source
->drawable
.y
;
2472 if(source
== WindowTable
[0]) {
2473 winX
-= panoramiXdataPtr
[0].x
;
2474 winY
-= panoramiXdataPtr
[0].y
;
2476 if (x
< winX
+ stuff
->srcX
||
2477 y
< winY
+ stuff
->srcY
||
2478 (stuff
->srcWidth
!= 0 &&
2479 winX
+ stuff
->srcX
+ (int)stuff
->srcWidth
< x
) ||
2480 (stuff
->srcHeight
!= 0 &&
2481 winY
+ stuff
->srcY
+ (int)stuff
->srcHeight
< y
) ||
2482 !XineramaPointInWindowIsVisible(source
, x
, y
))
2486 x
= dest
->drawable
.x
;
2487 y
= dest
->drawable
.y
;
2488 if(dest
== WindowTable
[0]) {
2489 x
-= panoramiXdataPtr
[0].x
;
2490 y
-= panoramiXdataPtr
[0].y
;
2497 if (x
< sprite
.physLimits
.x1
)
2498 x
= sprite
.physLimits
.x1
;
2499 else if (x
>= sprite
.physLimits
.x2
)
2500 x
= sprite
.physLimits
.x2
- 1;
2501 if (y
< sprite
.physLimits
.y1
)
2502 y
= sprite
.physLimits
.y1
;
2503 else if (y
>= sprite
.physLimits
.y2
)
2504 y
= sprite
.physLimits
.y2
- 1;
2505 if (sprite
.hotShape
)
2506 ConfineToShape(sprite
.hotShape
, &x
, &y
);
2508 XineramaSetCursorPosition(x
, y
, TRUE
);
2517 * Server-side protocol handling for WarpPointer request.
2518 * Warps the cursor position to the coordinates given in the request.
2521 ProcWarpPointer(ClientPtr client
)
2523 WindowPtr dest
= NULL
;
2525 ScreenPtr newScreen
;
2527 REQUEST(xWarpPointerReq
);
2529 REQUEST_SIZE_MATCH(xWarpPointerReq
);
2532 if(!noPanoramiXExtension
)
2533 return XineramaWarpPointer(client
);
2536 if (stuff
->dstWid
!= None
) {
2537 rc
= dixLookupWindow(&dest
, stuff
->dstWid
, client
, DixReadAccess
);
2541 x
= sprite
.hotPhys
.x
;
2542 y
= sprite
.hotPhys
.y
;
2544 if (stuff
->srcWid
!= None
)
2547 XID winID
= stuff
->srcWid
;
2550 rc
= dixLookupWindow(&source
, winID
, client
, DixReadAccess
);
2554 winX
= source
->drawable
.x
;
2555 winY
= source
->drawable
.y
;
2556 if (source
->drawable
.pScreen
!= sprite
.hotPhys
.pScreen
||
2557 x
< winX
+ stuff
->srcX
||
2558 y
< winY
+ stuff
->srcY
||
2559 (stuff
->srcWidth
!= 0 &&
2560 winX
+ stuff
->srcX
+ (int)stuff
->srcWidth
< x
) ||
2561 (stuff
->srcHeight
!= 0 &&
2562 winY
+ stuff
->srcY
+ (int)stuff
->srcHeight
< y
) ||
2563 !PointInWindowIsVisible(source
, x
, y
))
2568 x
= dest
->drawable
.x
;
2569 y
= dest
->drawable
.y
;
2570 newScreen
= dest
->drawable
.pScreen
;
2572 newScreen
= sprite
.hotPhys
.pScreen
;
2579 else if (x
>= newScreen
->width
)
2580 x
= newScreen
->width
- 1;
2583 else if (y
>= newScreen
->height
)
2584 y
= newScreen
->height
- 1;
2586 if (newScreen
== sprite
.hotPhys
.pScreen
)
2588 if (x
< sprite
.physLimits
.x1
)
2589 x
= sprite
.physLimits
.x1
;
2590 else if (x
>= sprite
.physLimits
.x2
)
2591 x
= sprite
.physLimits
.x2
- 1;
2592 if (y
< sprite
.physLimits
.y1
)
2593 y
= sprite
.physLimits
.y1
;
2594 else if (y
>= sprite
.physLimits
.y2
)
2595 y
= sprite
.physLimits
.y2
- 1;
2597 if (sprite
.hotShape
)
2598 ConfineToShape(sprite
.hotShape
, &x
, &y
);
2600 (*newScreen
->SetCursorPosition
)(newScreen
, x
, y
, TRUE
);
2602 else if (!PointerConfinedToScreen())
2604 NewCurrentScreen(newScreen
, x
, y
);
2610 BorderSizeNotEmpty(WindowPtr pWin
)
2612 if(REGION_NOTEMPTY(sprite
.hotPhys
.pScreen
, &pWin
->borderSize
))
2616 if(!noPanoramiXExtension
&& XineramaSetWindowPntrs(pWin
)) {
2619 for(i
= 1; i
< PanoramiXNumScreens
; i
++) {
2620 if(REGION_NOTEMPTY(sprite
.screen
, &sprite
.windows
[i
]->borderSize
))
2629 * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
2630 * passive grab set on the window to be activated.
2631 * If a passive grab is activated, the event will be delivered to the client.
2633 * @param pWin The window that may be subject to a passive grab.
2634 * @param device Device that caused the event.
2635 * @param xE List of events (multiple ones for DeviceMotionNotify)
2636 * @count number of elements in xE.
2640 CheckPassiveGrabsOnWindow(
2642 DeviceIntPtr device
,
2646 GrabPtr grab
= wPassiveGrabs(pWin
);
2652 tempGrab
.window
= pWin
;
2653 tempGrab
.device
= device
;
2654 tempGrab
.type
= xE
->u
.u
.type
;
2655 tempGrab
.detail
.exact
= xE
->u
.u
.detail
;
2656 tempGrab
.detail
.pMask
= NULL
;
2657 tempGrab
.modifiersDetail
.pMask
= NULL
;
2658 for (; grab
; grab
= grab
->next
)
2664 gdev
= grab
->modifierDevice
;
2665 xkbi
= gdev
->key
->xkbInfo
;
2667 tempGrab
.modifierDevice
= grab
->modifierDevice
;
2668 if ((device
== grab
->modifierDevice
) &&
2669 ((xE
->u
.u
.type
== KeyPress
)
2670 #if defined(XINPUT) && defined(XKB)
2671 || (xE
->u
.u
.type
== DeviceKeyPress
)
2674 tempGrab
.modifiersDetail
.exact
=
2676 (noXkbExtension
?gdev
->key
->prev_state
:xkbi
->state
.grab_mods
);
2678 grab
->modifierDevice
->key
->prev_state
;
2681 tempGrab
.modifiersDetail
.exact
=
2683 (noXkbExtension
? gdev
->key
->state
: xkbi
->state
.grab_mods
);
2685 grab
->modifierDevice
->key
->state
;
2687 if (GrabMatchesSecond(&tempGrab
, grab
) &&
2688 (!grab
->confineTo
||
2689 (grab
->confineTo
->realized
&&
2690 BorderSizeNotEmpty(grab
->confineTo
))))
2692 if (!XaceHook(XACE_DEVICE_ACCESS
, wClient(pWin
), device
, FALSE
))
2695 if (!noXkbExtension
) {
2696 XE_KBPTR
.state
&= 0x1f00;
2698 tempGrab
.modifiersDetail
.exact
&(~0x1f00);
2701 (*device
->ActivateGrab
)(device
, grab
, currentTime
, TRUE
);
2703 FixUpEventFromWindow(xE
, grab
->window
, None
, TRUE
);
2705 (void) TryClientEvents(rClient(grab
), xE
, count
,
2706 filters
[xE
->u
.u
.type
],
2707 filters
[xE
->u
.u
.type
], grab
);
2709 if (device
->sync
.state
== FROZEN_NO_EVENT
)
2711 if (device
->sync
.evcount
< count
)
2713 Must_have_memory
= TRUE
; /* XXX */
2714 device
->sync
.event
= (xEvent
*)xrealloc(device
->sync
.event
,
2717 Must_have_memory
= FALSE
; /* XXX */
2719 device
->sync
.evcount
= count
;
2720 for (dxE
= device
->sync
.event
; --count
>= 0; dxE
++, xE
++)
2722 device
->sync
.state
= FROZEN_WITH_EVENT
;
2731 * CheckDeviceGrabs handles both keyboard and pointer events that may cause
2732 * a passive grab to be activated.
2734 * If the event is a keyboard event, the ancestors of the focus window are
2735 * traced down and tried to see if they have any passive grabs to be
2736 * activated. If the focus window itself is reached and it's descendants
2737 * contain the pointer, the ancestors of the window that the pointer is in
2738 * are then traced down starting at the focus window, otherwise no grabs are
2740 * If the event is a pointer event, the ancestors of the window that the
2741 * pointer is in are traced down starting at the root until CheckPassiveGrabs
2742 * causes a passive grab to activate or all the windows are
2745 * If a grab is activated, the event has been sent to the client already!
2747 * @param device The device that caused the event.
2748 * @param xE The event to handle (most likely {Device}ButtonPress).
2749 * @param count Number of events in list.
2750 * @return TRUE if a grab has been activated or false otherwise.
2754 CheckDeviceGrabs(DeviceIntPtr device
, xEvent
*xE
,
2755 int checkFirst
, int count
)
2758 WindowPtr pWin
= NULL
;
2759 FocusClassPtr focus
= device
->focus
;
2761 if (((xE
->u
.u
.type
== ButtonPress
)
2762 #if defined(XINPUT) && defined(XKB)
2763 || (xE
->u
.u
.type
== DeviceButtonPress
)
2765 ) && (device
->button
->buttonsDown
!= 1))
2772 for (; i
< focus
->traceGood
; i
++)
2774 pWin
= focus
->trace
[i
];
2775 if (pWin
->optional
&&
2776 CheckPassiveGrabsOnWindow(pWin
, device
, xE
, count
))
2780 if ((focus
->win
== NoneWin
) ||
2781 (i
>= spriteTraceGood
) ||
2782 ((i
> checkFirst
) && (pWin
!= spriteTrace
[i
-1])))
2786 for (; i
< spriteTraceGood
; i
++)
2788 pWin
= spriteTrace
[i
];
2789 if (pWin
->optional
&&
2790 CheckPassiveGrabsOnWindow(pWin
, device
, xE
, count
))
2798 * Called for keyboard events to deliver event to whatever client owns the
2799 * focus. Event is delivered to the keyboard's focus window, the root window
2800 * or to the window owning the input focus.
2802 * @param keybd The keyboard originating the event.
2803 * @param xE The event list.
2804 * @param window Window underneath the sprite.
2805 * @param count number of events in xE.
2808 DeliverFocusedEvent(DeviceIntPtr keybd
, xEvent
*xE
, WindowPtr window
, int count
)
2810 WindowPtr focus
= keybd
->focus
->win
;
2813 if (focus
== FollowKeyboardWin
)
2814 focus
= inputInfo
.keyboard
->focus
->win
;
2817 if (focus
== PointerRootWin
)
2819 DeliverDeviceEvents(window
, xE
, NullGrab
, NullWindow
, keybd
, count
);
2822 if ((focus
== window
) || IsParent(focus
, window
))
2824 if (DeliverDeviceEvents(window
, xE
, NullGrab
, focus
, keybd
, count
))
2827 /* just deliver it to the focus window */
2828 FixUpEventFromWindow(xE
, focus
, None
, FALSE
);
2829 if (xE
->u
.u
.type
& EXTENSION_EVENT_BASE
)
2831 (void)DeliverEventsToWindow(focus
, xE
, count
, filters
[xE
->u
.u
.type
],
2836 * Deliver an event from a device that is currently grabbed. Uses
2837 * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
2838 * grab. If not, TryClientEvents() is used.
2840 * @param deactivateGrab True if the device's grab should be deactivated.
2843 DeliverGrabbedEvent(xEvent
*xE
, DeviceIntPtr thisDev
,
2844 Bool deactivateGrab
, int count
)
2846 GrabPtr grab
= thisDev
->grab
;
2851 if (grab
->ownerEvents
)
2857 focus
= thisDev
->focus
->win
;
2858 if (focus
== FollowKeyboardWin
)
2859 focus
= inputInfo
.keyboard
->focus
->win
;
2862 focus
= PointerRootWin
;
2863 if (focus
== PointerRootWin
)
2864 deliveries
= DeliverDeviceEvents(sprite
.win
, xE
, grab
, NullWindow
,
2866 else if (focus
&& (focus
== sprite
.win
|| IsParent(focus
, sprite
.win
)))
2867 deliveries
= DeliverDeviceEvents(sprite
.win
, xE
, grab
, focus
,
2870 deliveries
= DeliverDeviceEvents(focus
, xE
, grab
, focus
,
2875 FixUpEventFromWindow(xE
, grab
->window
, None
, TRUE
);
2876 deliveries
= TryClientEvents(rClient(grab
), xE
, count
,
2877 (Mask
)grab
->eventMask
,
2878 filters
[xE
->u
.u
.type
], grab
);
2879 if (deliveries
&& (xE
->u
.u
.type
== MotionNotify
2881 || xE
->u
.u
.type
== DeviceMotionNotify
2884 thisDev
->valuator
->motionHintWindow
= grab
->window
;
2886 if (deliveries
&& !deactivateGrab
&& (xE
->u
.u
.type
!= MotionNotify
2888 && xE
->u
.u
.type
!= DeviceMotionNotify
2891 switch (thisDev
->sync
.state
)
2893 case FREEZE_BOTH_NEXT_EVENT
:
2894 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
)
2898 FreezeThaw(dev
, TRUE
);
2899 if ((dev
->sync
.state
== FREEZE_BOTH_NEXT_EVENT
) &&
2900 (CLIENT_BITS(dev
->grab
->resource
) ==
2901 CLIENT_BITS(thisDev
->grab
->resource
)))
2902 dev
->sync
.state
= FROZEN_NO_EVENT
;
2904 dev
->sync
.other
= thisDev
->grab
;
2907 case FREEZE_NEXT_EVENT
:
2908 thisDev
->sync
.state
= FROZEN_WITH_EVENT
;
2909 FreezeThaw(thisDev
, TRUE
);
2910 if (thisDev
->sync
.evcount
< count
)
2912 Must_have_memory
= TRUE
; /* XXX */
2913 thisDev
->sync
.event
= (xEvent
*)xrealloc(thisDev
->sync
.event
,
2914 count
*sizeof(xEvent
));
2915 Must_have_memory
= FALSE
; /* XXX */
2917 thisDev
->sync
.evcount
= count
;
2918 for (dxE
= thisDev
->sync
.event
; --count
>= 0; dxE
++, xE
++)
2925 * Main keyboard event processing function for core keyboard events.
2926 * Updates the events fields from the current pointer state and delivers the
2929 * For key events, xE will always be a single event.
2931 * @param xE Event list
2932 * @param keybd The device that caused an event.
2933 * @param count Number of elements in xE.
2937 CoreProcessKeyboardEvent (xEvent
*xE
, DeviceIntPtr keybd
, int count
)
2939 ProcessKeyboardEvent (xEvent
*xE
, DeviceIntPtr keybd
, int count
)
2947 GrabPtr grab
= keybd
->grab
;
2948 Bool deactivateGrab
= FALSE
;
2949 KeyClassPtr keyc
= keybd
->key
;
2951 static Window rootWin
= 0;
2953 if(!xeviegrabState
&& xevieFlag
&& clients
[xevieClientIndex
] &&
2954 (xevieMask
& xevieFilters
[xE
->u
.u
.type
])) {
2955 key
= xE
->u
.u
.detail
;
2956 kptr
= &keyc
->down
[key
>> 3];
2957 bit
= 1 << (key
& 7);
2958 if((xE
->u
.u
.type
== KeyPress
&& (*kptr
& bit
)) ||
2959 (xE
->u
.u
.type
== KeyRelease
&& !(*kptr
& bit
)))
2963 xevieKBEventSent
= 1;
2965 if(!xevieKBEventSent
)
2969 rootWin
= GetCurrentRootWindow()->drawable
.id
;
2971 xE
->u
.keyButtonPointer
.event
= xeviewin
->drawable
.id
;
2972 xE
->u
.keyButtonPointer
.root
= rootWin
;
2973 xE
->u
.keyButtonPointer
.child
= (xeviewin
->firstChild
) ? xeviewin
->firstChild
->
2975 xE
->u
.keyButtonPointer
.rootX
= xeviehot
.x
;
2976 xE
->u
.keyButtonPointer
.rootY
= xeviehot
.y
;
2977 xE
->u
.keyButtonPointer
.state
= keyc
->state
;
2978 WriteToClient(clients
[xevieClientIndex
], sizeof(xEvent
), (char *)xE
);
2984 xevieKBEventSent
= 0;
2990 if (!syncEvents
.playingEvents
)
2993 if (DeviceEventCallback
)
2995 DeviceEventInfoRec eventinfo
;
2996 eventinfo
.events
= xE
;
2997 eventinfo
.count
= count
;
2998 CallCallbacks(&DeviceEventCallback
, (pointer
)&eventinfo
);
3002 /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */
3003 if(!(!xeviegrabState
&& xevieFlag
&& clients
[xevieClientIndex
] &&
3004 (xevieMask
& xevieFilters
[xE
->u
.u
.type
]
3010 XE_KBPTR
.state
= (keyc
->state
| inputInfo
.pointer
->button
->state
);
3011 XE_KBPTR
.rootX
= sprite
.hot
.x
;
3012 XE_KBPTR
.rootY
= sprite
.hot
.y
;
3013 key
= xE
->u
.u
.detail
;
3014 kptr
= &keyc
->down
[key
>> 3];
3015 bit
= 1 << (key
& 7);
3016 modifiers
= keyc
->modifierMap
[key
];
3017 #if defined(XKB) && defined(XEVIE)
3018 if(!noXkbExtension
&& !xeviegrabState
&&
3019 xevieFlag
&& clients
[xevieClientIndex
] &&
3020 (xevieMask
& xevieFilters
[xE
->u
.u
.type
])) {
3021 switch(xE
->u
.u
.type
) {
3022 case KeyPress
: *kptr
&= ~bit
; break;
3023 case KeyRelease
: *kptr
|= bit
; break;
3028 switch (xE
->u
.u
.type
)
3031 if (*kptr
& bit
) /* allow ddx to generate multiple downs */
3035 xE
->u
.u
.type
= KeyRelease
;
3036 (*keybd
->public.processInputProc
)(xE
, keybd
, count
);
3037 xE
->u
.u
.type
= KeyPress
;
3038 /* release can have side effects, don't fall through */
3039 (*keybd
->public.processInputProc
)(xE
, keybd
, count
);
3043 inputInfo
.pointer
->valuator
->motionHintWindow
= NullWindow
;
3045 keyc
->prev_state
= keyc
->state
;
3046 for (i
= 0, mask
= 1; modifiers
; i
++, mask
<<= 1)
3048 if (mask
& modifiers
)
3050 /* This key affects modifier "i" */
3051 keyc
->modifierKeyCount
[i
]++;
3052 keyc
->state
|= mask
;
3056 if (!grab
&& CheckDeviceGrabs(keybd
, xE
, 0, count
))
3058 keybd
->activatingKey
= key
;
3063 if (!(*kptr
& bit
)) /* guard against duplicates */
3065 inputInfo
.pointer
->valuator
->motionHintWindow
= NullWindow
;
3067 keyc
->prev_state
= keyc
->state
;
3068 for (i
= 0, mask
= 1; modifiers
; i
++, mask
<<= 1)
3070 if (mask
& modifiers
) {
3071 /* This key affects modifier "i" */
3072 if (--keyc
->modifierKeyCount
[i
] <= 0) {
3073 keyc
->state
&= ~mask
;
3074 keyc
->modifierKeyCount
[i
] = 0;
3079 if (keybd
->fromPassiveGrab
&& (key
== keybd
->activatingKey
))
3080 deactivateGrab
= TRUE
;
3083 FatalError("Impossible keyboard event");
3086 DeliverGrabbedEvent(xE
, keybd
, deactivateGrab
, count
);
3088 DeliverFocusedEvent(keybd
, xE
, sprite
.win
, count
);
3090 (*keybd
->DeactivateGrab
)(keybd
);
3092 XaceHook(XACE_KEY_AVAIL
, xE
, keybd
, count
);
3096 /* This function is used to set the key pressed or key released state -
3097 this is only used when the pressing of keys does not cause
3098 CoreProcessKeyEvent to be called, as in for example Mouse Keys.
3101 FixKeyState (xEvent
*xE
, DeviceIntPtr keybd
)
3105 KeyClassPtr keyc
= keybd
->key
;
3107 key
= xE
->u
.u
.detail
;
3108 kptr
= &keyc
->down
[key
>> 3];
3109 bit
= 1 << (key
& 7);
3111 if (((xE
->u
.u
.type
==KeyPress
)||(xE
->u
.u
.type
==KeyRelease
))) {
3112 DebugF("FixKeyState: Key %d %s\n",key
,
3113 (xE
->u
.u
.type
==KeyPress
?"down":"up"));
3116 switch (xE
->u
.u
.type
)
3125 FatalError("Impossible keyboard event");
3131 * Main pointer event processing function for core pointer events.
3132 * For motion events: update the sprite.
3133 * For all other events: Update the event fields based on the current sprite
3136 * For core pointer events, xE will always be a single event.
3138 * @param xE Event list
3139 * @param mouse The device that caused an event.
3140 * @param count Number of elements in xE.
3144 CoreProcessPointerEvent (xEvent
*xE
, DeviceIntPtr mouse
, int count
)
3146 ProcessPointerEvent (xEvent
*xE
, DeviceIntPtr mouse
, int count
)
3149 GrabPtr grab
= mouse
->grab
;
3150 Bool deactivateGrab
= FALSE
;
3151 ButtonClassPtr butc
= mouse
->button
;
3153 XkbSrvInfoPtr xkbi
= inputInfo
.keyboard
->key
->xkbInfo
;
3156 if(xevieFlag
&& clients
[xevieClientIndex
] && !xeviegrabState
&&
3157 (xevieMask
& xevieFilters
[xE
->u
.u
.type
])) {
3162 WriteToClient(clients
[xevieClientIndex
], sizeof(xEvent
), (char *)xE
);
3168 if (!syncEvents
.playingEvents
)
3170 XE_KBPTR
.state
= (butc
->state
| (
3173 inputInfo
.keyboard
->key
->state
:
3174 xkbi
->state
.grab_mods
)
3176 inputInfo
.keyboard
->key
->state
3181 if (DeviceEventCallback
)
3183 DeviceEventInfoRec eventinfo
;
3184 /* see comment in EnqueueEvents regarding the next three lines */
3185 if (xE
->u
.u
.type
== MotionNotify
)
3187 WindowTable
[sprite
.hotPhys
.pScreen
->myNum
]->drawable
.id
;
3188 eventinfo
.events
= xE
;
3189 eventinfo
.count
= count
;
3190 CallCallbacks(&DeviceEventCallback
, (pointer
)&eventinfo
);
3193 if (xE
->u
.u
.type
!= MotionNotify
)
3199 XE_KBPTR
.rootX
= sprite
.hot
.x
;
3200 XE_KBPTR
.rootY
= sprite
.hot
.y
;
3202 key
= xE
->u
.u
.detail
;
3203 kptr
= &butc
->down
[key
>> 3];
3204 bit
= 1 << (key
& 7);
3205 switch (xE
->u
.u
.type
)
3208 mouse
->valuator
->motionHintWindow
= NullWindow
;
3210 butc
->buttonsDown
++;
3211 butc
->motionMask
= ButtonMotionMask
;
3213 if (xE
->u
.u
.detail
== 0)
3215 if (xE
->u
.u
.detail
<= 5)
3216 butc
->state
|= (Button1Mask
>> 1) << xE
->u
.u
.detail
;
3217 filters
[MotionNotify
] = Motion_Filter(butc
);
3219 if (CheckDeviceGrabs(mouse
, xE
, 0, count
))
3223 mouse
->valuator
->motionHintWindow
= NullWindow
;
3225 --butc
->buttonsDown
;
3226 if (!butc
->buttonsDown
)
3227 butc
->motionMask
= 0;
3229 if (xE
->u
.u
.detail
== 0)
3231 if (xE
->u
.u
.detail
<= 5)
3232 butc
->state
&= ~((Button1Mask
>> 1) << xE
->u
.u
.detail
);
3233 filters
[MotionNotify
] = Motion_Filter(butc
);
3234 if (!butc
->state
&& mouse
->fromPassiveGrab
)
3235 deactivateGrab
= TRUE
;
3238 FatalError("bogus pointer event from ddx");
3241 else if (!CheckMotion(xE
))
3244 DeliverGrabbedEvent(xE
, mouse
, deactivateGrab
, count
);
3246 DeliverDeviceEvents(sprite
.win
, xE
, NullGrab
, NullWindow
,
3249 (*mouse
->DeactivateGrab
)(mouse
);
3252 #define AtMostOneClient \
3253 (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
3256 * Recalculate which events may be deliverable for the given window.
3257 * Recalculated mask is used for quicker determination which events may be
3258 * delivered to a window.
3260 * The otherEventMasks on a WindowOptional is the combination of all event
3261 * masks set by all clients on the window.
3262 * deliverableEventMask is the combination of the eventMask and the
3265 * Traverses to siblings and parents of the window.
3268 RecalculateDeliverableEvents(pWin
)
3271 OtherClients
*others
;
3277 if (pChild
->optional
)
3279 pChild
->optional
->otherEventMasks
= 0;
3280 for (others
= wOtherClients(pChild
); others
; others
= others
->next
)
3282 pChild
->optional
->otherEventMasks
|= others
->mask
;
3285 pChild
->deliverableEvents
= pChild
->eventMask
|
3286 wOtherEventMasks(pChild
);
3288 pChild
->deliverableEvents
|=
3289 (pChild
->parent
->deliverableEvents
&
3290 ~wDontPropagateMask(pChild
) & PropagateMask
);
3291 if (pChild
->firstChild
)
3293 pChild
= pChild
->firstChild
;
3296 while (!pChild
->nextSib
&& (pChild
!= pWin
))
3297 pChild
= pChild
->parent
;
3300 pChild
= pChild
->nextSib
;
3306 * \param value must conform to DeleteType
3309 OtherClientGone(pointer value
, XID id
)
3311 OtherClientsPtr other
, prev
;
3312 WindowPtr pWin
= (WindowPtr
)value
;
3315 for (other
= wOtherClients(pWin
); other
; other
= other
->next
)
3317 if (other
->resource
== id
)
3320 prev
->next
= other
->next
;
3323 if (!(pWin
->optional
->otherClients
= other
->next
))
3324 CheckWindowOptionalNeed (pWin
);
3327 RecalculateDeliverableEvents(pWin
);
3332 FatalError("client not on event list");
3334 return -1; /* make compiler happy */
3338 EventSelectForWindow(WindowPtr pWin
, ClientPtr client
, Mask mask
)
3341 OtherClients
* others
;
3343 if (mask
& ~AllEventMasks
)
3345 client
->errorValue
= mask
;
3348 check
= (mask
& AtMostOneClient
);
3349 if (check
& (pWin
->eventMask
|wOtherEventMasks(pWin
)))
3350 { /* It is illegal for two different
3351 clients to select on any of the
3352 events for AtMostOneClient. However,
3353 it is OK, for some client to
3354 continue selecting on one of those
3356 if ((wClient(pWin
) != client
) && (check
& pWin
->eventMask
))
3358 for (others
= wOtherClients (pWin
); others
; others
= others
->next
)
3360 if (!SameClient(others
, client
) && (check
& others
->mask
))
3364 if (wClient (pWin
) == client
)
3366 check
= pWin
->eventMask
;
3367 pWin
->eventMask
= mask
;
3371 for (others
= wOtherClients (pWin
); others
; others
= others
->next
)
3373 if (SameClient(others
, client
))
3375 check
= others
->mask
;
3378 FreeResource(others
->resource
, RT_NONE
);
3382 others
->mask
= mask
;
3387 if (!pWin
->optional
&& !MakeWindowOptional (pWin
))
3389 others
= (OtherClients
*) xalloc(sizeof(OtherClients
));
3392 others
->mask
= mask
;
3393 others
->resource
= FakeClientID(client
->index
);
3394 others
->next
= pWin
->optional
->otherClients
;
3395 pWin
->optional
->otherClients
= others
;
3396 if (!AddResource(others
->resource
, RT_OTHERCLIENT
, (pointer
)pWin
))
3400 if ((inputInfo
.pointer
->valuator
->motionHintWindow
== pWin
) &&
3401 (mask
& PointerMotionHintMask
) &&
3402 !(check
& PointerMotionHintMask
) &&
3403 !inputInfo
.pointer
->grab
)
3404 inputInfo
.pointer
->valuator
->motionHintWindow
= NullWindow
;
3405 RecalculateDeliverableEvents(pWin
);
3410 EventSuppressForWindow(WindowPtr pWin
, ClientPtr client
,
3411 Mask mask
, Bool
*checkOptional
)
3415 if (mask
& ~PropagateMask
)
3417 client
->errorValue
= mask
;
3420 if (pWin
->dontPropagate
)
3421 DontPropagateRefCnts
[pWin
->dontPropagate
]--;
3426 for (i
= DNPMCOUNT
, free
= 0; --i
> 0; )
3428 if (!DontPropagateRefCnts
[i
])
3430 else if (mask
== DontPropagateMasks
[i
])
3436 DontPropagateMasks
[i
] = mask
;
3441 pWin
->dontPropagate
= i
;
3443 DontPropagateRefCnts
[i
]++;
3446 pWin
->optional
->dontPropagateMask
= mask
;
3447 *checkOptional
= TRUE
;
3452 if (!pWin
->optional
&& !MakeWindowOptional (pWin
))
3454 if (pWin
->dontPropagate
)
3455 DontPropagateRefCnts
[pWin
->dontPropagate
]++;
3458 pWin
->dontPropagate
= 0;
3459 pWin
->optional
->dontPropagateMask
= mask
;
3461 RecalculateDeliverableEvents(pWin
);
3466 * @return The window that is the first ancestor of both a and b.
3473 for (b
= b
->parent
; b
; b
= b
->parent
)
3474 if (IsParent(b
, a
)) return b
;
3479 * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
3480 * The core devices are used to fill in the event fields.
3491 DeviceIntPtr keybd
= inputInfo
.keyboard
;
3493 DeviceIntPtr mouse
= inputInfo
.pointer
;
3494 GrabPtr grab
= mouse
->grab
;
3497 if ((pWin
== mouse
->valuator
->motionHintWindow
) &&
3498 (detail
!= NotifyInferior
))
3499 mouse
->valuator
->motionHintWindow
= NullWindow
;
3502 mask
= (pWin
== grab
->window
) ? grab
->eventMask
: 0;
3503 if (grab
->ownerEvents
)
3504 mask
|= EventMaskForClient(pWin
, rClient(grab
));
3508 mask
= pWin
->eventMask
| wOtherEventMasks(pWin
);
3510 if (mask
& filters
[type
])
3512 event
.u
.u
.type
= type
;
3513 event
.u
.u
.detail
= detail
;
3514 event
.u
.enterLeave
.time
= currentTime
.milliseconds
;
3515 event
.u
.enterLeave
.rootX
= sprite
.hot
.x
;
3516 event
.u
.enterLeave
.rootY
= sprite
.hot
.y
;
3517 /* Counts on the same initial structure of crossing & button events! */
3518 FixUpEventFromWindow(&event
, pWin
, None
, FALSE
);
3519 /* Enter/Leave events always set child */
3520 event
.u
.enterLeave
.child
= child
;
3521 event
.u
.enterLeave
.flags
= event
.u
.keyButtonPointer
.sameScreen
?
3522 ELFlagSameScreen
: 0;
3524 if (!noXkbExtension
) {
3525 event
.u
.enterLeave
.state
= mouse
->button
->state
& 0x1f00;
3526 event
.u
.enterLeave
.state
|=
3527 XkbGrabStateFromRec(&keybd
->key
->xkbInfo
->state
);
3530 event
.u
.enterLeave
.state
= keybd
->key
->state
| mouse
->button
->state
;
3531 event
.u
.enterLeave
.mode
= mode
;
3532 focus
= keybd
->focus
->win
;
3533 if ((focus
!= NoneWin
) &&
3534 ((pWin
== focus
) || (focus
== PointerRootWin
) ||
3535 IsParent(focus
, pWin
)))
3536 event
.u
.enterLeave
.flags
|= ELFlagFocus
;
3538 (void)TryClientEvents(rClient(grab
), &event
, 1, mask
,
3539 filters
[type
], grab
);
3541 (void)DeliverEventsToWindow(pWin
, &event
, 1, filters
[type
],
3544 if ((type
== EnterNotify
) && (mask
& KeymapStateMask
))
3547 ClientPtr client
= grab
? rClient(grab
)
3548 : clients
[CLIENT_ID(pWin
->drawable
.id
)];
3549 if (XaceHook(XACE_DEVICE_ACCESS
, client
, keybd
, FALSE
))
3550 memmove((char *)&ke
.map
[0], (char *)&keybd
->key
->down
[1], 31);
3552 bzero((char *)&ke
.map
[0], 31);
3554 ke
.type
= KeymapNotify
;
3556 (void)TryClientEvents(rClient(grab
), (xEvent
*)&ke
, 1, mask
,
3557 KeymapStateMask
, grab
);
3559 (void)DeliverEventsToWindow(pWin
, (xEvent
*)&ke
, 1,
3560 KeymapStateMask
, NullGrab
, 0);
3565 * Send enter notifies to all parent windows up to ancestor.
3566 * This function recurses.
3569 EnterNotifies(WindowPtr ancestor
, WindowPtr child
, int mode
, int detail
)
3571 WindowPtr parent
= child
->parent
;
3573 if (ancestor
== parent
)
3575 EnterNotifies(ancestor
, parent
, mode
, detail
);
3576 EnterLeaveEvent(EnterNotify
, mode
, detail
, parent
, child
->drawable
.id
);
3581 * Send leave notifies to all parent windows up to ancestor.
3582 * This function recurses.
3585 LeaveNotifies(WindowPtr child
, WindowPtr ancestor
, int mode
, int detail
)
3589 if (ancestor
== child
)
3591 for (pWin
= child
->parent
; pWin
!= ancestor
; pWin
= pWin
->parent
)
3593 EnterLeaveEvent(LeaveNotify
, mode
, detail
, pWin
, child
->drawable
.id
);
3599 * Figure out if enter/leave events are necessary and send them to the
3600 * appropriate windows.
3602 * @param fromWin Window the sprite moved out of.
3603 * @param toWin Window the sprite moved into.
3606 DoEnterLeaveEvents(WindowPtr fromWin
, WindowPtr toWin
, int mode
)
3608 if (fromWin
== toWin
)
3610 if (IsParent(fromWin
, toWin
))
3612 EnterLeaveEvent(LeaveNotify
, mode
, NotifyInferior
, fromWin
, None
);
3613 EnterNotifies(fromWin
, toWin
, mode
, NotifyVirtual
);
3614 EnterLeaveEvent(EnterNotify
, mode
, NotifyAncestor
, toWin
, None
);
3616 else if (IsParent(toWin
, fromWin
))
3618 EnterLeaveEvent(LeaveNotify
, mode
, NotifyAncestor
, fromWin
, None
);
3619 LeaveNotifies(fromWin
, toWin
, mode
, NotifyVirtual
);
3620 EnterLeaveEvent(EnterNotify
, mode
, NotifyInferior
, toWin
, None
);
3623 { /* neither fromWin nor toWin is descendent of the other */
3624 WindowPtr common
= CommonAncestor(toWin
, fromWin
);
3625 /* common == NullWindow ==> different screens */
3626 EnterLeaveEvent(LeaveNotify
, mode
, NotifyNonlinear
, fromWin
, None
);
3627 LeaveNotifies(fromWin
, common
, mode
, NotifyNonlinearVirtual
);
3628 EnterNotifies(common
, toWin
, mode
, NotifyNonlinearVirtual
);
3629 EnterLeaveEvent(EnterNotify
, mode
, NotifyNonlinear
, toWin
, None
);
3634 FocusEvent(DeviceIntPtr dev
, int type
, int mode
, int detail
, WindowPtr pWin
)
3639 if (dev
!= inputInfo
.keyboard
)
3641 DeviceFocusEvent(dev
, type
, mode
, detail
, pWin
);
3645 event
.u
.focus
.mode
= mode
;
3646 event
.u
.u
.type
= type
;
3647 event
.u
.u
.detail
= detail
;
3648 event
.u
.focus
.window
= pWin
->drawable
.id
;
3649 (void)DeliverEventsToWindow(pWin
, &event
, 1, filters
[type
], NullGrab
,
3651 if ((type
== FocusIn
) &&
3652 ((pWin
->eventMask
| wOtherEventMasks(pWin
)) & KeymapStateMask
))
3655 ClientPtr client
= clients
[CLIENT_ID(pWin
->drawable
.id
)];
3656 if (XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, FALSE
))
3657 memmove((char *)&ke
.map
[0], (char *)&dev
->key
->down
[1], 31);
3659 bzero((char *)&ke
.map
[0], 31);
3661 ke
.type
= KeymapNotify
;
3662 (void)DeliverEventsToWindow(pWin
, (xEvent
*)&ke
, 1,
3663 KeymapStateMask
, NullGrab
, 0);
3668 * recursive because it is easier
3669 * no-op if child not descended from ancestor
3674 WindowPtr ancestor
, WindowPtr child
, WindowPtr skipChild
,
3675 int mode
, int detail
,
3678 if (child
== NullWindow
)
3679 return ancestor
== NullWindow
;
3680 if (ancestor
== child
)
3683 FocusEvent(dev
, FocusIn
, mode
, detail
, child
);
3686 if (FocusInEvents(dev
, ancestor
, child
->parent
, skipChild
, mode
, detail
,
3689 if (child
!= skipChild
)
3690 FocusEvent(dev
, FocusIn
, mode
, detail
, child
);
3696 /* dies horribly if ancestor is not an ancestor of child */
3700 WindowPtr child
, WindowPtr ancestor
,
3701 int mode
, int detail
,
3706 for (pWin
= child
; pWin
!= ancestor
; pWin
= pWin
->parent
)
3707 FocusEvent(dev
, FocusOut
, mode
, detail
, pWin
);
3709 FocusEvent(dev
, FocusOut
, mode
, detail
, ancestor
);
3713 DoFocusEvents(DeviceIntPtr dev
, WindowPtr fromWin
, WindowPtr toWin
, int mode
)
3715 int out
, in
; /* for holding details for to/from
3719 if (fromWin
== toWin
)
3721 out
= (fromWin
== NoneWin
) ? NotifyDetailNone
: NotifyPointerRoot
;
3722 in
= (toWin
== NoneWin
) ? NotifyDetailNone
: NotifyPointerRoot
;
3723 /* wrong values if neither, but then not referenced */
3725 if ((toWin
== NullWindow
) || (toWin
== PointerRootWin
))
3727 if ((fromWin
== NullWindow
) || (fromWin
== PointerRootWin
))
3729 if (fromWin
== PointerRootWin
)
3730 FocusOutEvents(dev
, sprite
.win
, ROOT
, mode
, NotifyPointer
,
3732 /* Notify all the roots */
3734 if ( !noPanoramiXExtension
)
3735 FocusEvent(dev
, FocusOut
, mode
, out
, WindowTable
[0]);
3738 for (i
=0; i
<screenInfo
.numScreens
; i
++)
3739 FocusEvent(dev
, FocusOut
, mode
, out
, WindowTable
[i
]);
3743 if (IsParent(fromWin
, sprite
.win
))
3744 FocusOutEvents(dev
, sprite
.win
, fromWin
, mode
, NotifyPointer
,
3746 FocusEvent(dev
, FocusOut
, mode
, NotifyNonlinear
, fromWin
);
3747 /* next call catches the root too, if the screen changed */
3748 FocusOutEvents(dev
, fromWin
->parent
, NullWindow
, mode
,
3749 NotifyNonlinearVirtual
, FALSE
);
3751 /* Notify all the roots */
3753 if ( !noPanoramiXExtension
)
3754 FocusEvent(dev
, FocusIn
, mode
, in
, WindowTable
[0]);
3757 for (i
=0; i
<screenInfo
.numScreens
; i
++)
3758 FocusEvent(dev
, FocusIn
, mode
, in
, WindowTable
[i
]);
3759 if (toWin
== PointerRootWin
)
3760 (void)FocusInEvents(dev
, ROOT
, sprite
.win
, NullWindow
, mode
,
3761 NotifyPointer
, TRUE
);
3765 if ((fromWin
== NullWindow
) || (fromWin
== PointerRootWin
))
3767 if (fromWin
== PointerRootWin
)
3768 FocusOutEvents(dev
, sprite
.win
, ROOT
, mode
, NotifyPointer
,
3771 if ( !noPanoramiXExtension
)
3772 FocusEvent(dev
, FocusOut
, mode
, out
, WindowTable
[0]);
3775 for (i
=0; i
<screenInfo
.numScreens
; i
++)
3776 FocusEvent(dev
, FocusOut
, mode
, out
, WindowTable
[i
]);
3777 if (toWin
->parent
!= NullWindow
)
3778 (void)FocusInEvents(dev
, ROOT
, toWin
, toWin
, mode
,
3779 NotifyNonlinearVirtual
, TRUE
);
3780 FocusEvent(dev
, FocusIn
, mode
, NotifyNonlinear
, toWin
);
3781 if (IsParent(toWin
, sprite
.win
))
3782 (void)FocusInEvents(dev
, toWin
, sprite
.win
, NullWindow
, mode
,
3783 NotifyPointer
, FALSE
);
3787 if (IsParent(toWin
, fromWin
))
3789 FocusEvent(dev
, FocusOut
, mode
, NotifyAncestor
, fromWin
);
3790 FocusOutEvents(dev
, fromWin
->parent
, toWin
, mode
,
3791 NotifyVirtual
, FALSE
);
3792 FocusEvent(dev
, FocusIn
, mode
, NotifyInferior
, toWin
);
3793 if ((IsParent(toWin
, sprite
.win
)) &&
3794 (sprite
.win
!= fromWin
) &&
3795 (!IsParent(fromWin
, sprite
.win
)) &&
3796 (!IsParent(sprite
.win
, fromWin
)))
3797 (void)FocusInEvents(dev
, toWin
, sprite
.win
, NullWindow
,
3798 mode
, NotifyPointer
, FALSE
);
3801 if (IsParent(fromWin
, toWin
))
3803 if ((IsParent(fromWin
, sprite
.win
)) &&
3804 (sprite
.win
!= fromWin
) &&
3805 (!IsParent(toWin
, sprite
.win
)) &&
3806 (!IsParent(sprite
.win
, toWin
)))
3807 FocusOutEvents(dev
, sprite
.win
, fromWin
, mode
,
3808 NotifyPointer
, FALSE
);
3809 FocusEvent(dev
, FocusOut
, mode
, NotifyInferior
, fromWin
);
3810 (void)FocusInEvents(dev
, fromWin
, toWin
, toWin
, mode
,
3811 NotifyVirtual
, FALSE
);
3812 FocusEvent(dev
, FocusIn
, mode
, NotifyAncestor
, toWin
);
3816 /* neither fromWin or toWin is child of other */
3817 WindowPtr common
= CommonAncestor(toWin
, fromWin
);
3818 /* common == NullWindow ==> different screens */
3819 if (IsParent(fromWin
, sprite
.win
))
3820 FocusOutEvents(dev
, sprite
.win
, fromWin
, mode
,
3821 NotifyPointer
, FALSE
);
3822 FocusEvent(dev
, FocusOut
, mode
, NotifyNonlinear
, fromWin
);
3823 if (fromWin
->parent
!= NullWindow
)
3824 FocusOutEvents(dev
, fromWin
->parent
, common
, mode
,
3825 NotifyNonlinearVirtual
, FALSE
);
3826 if (toWin
->parent
!= NullWindow
)
3827 (void)FocusInEvents(dev
, common
, toWin
, toWin
, mode
,
3828 NotifyNonlinearVirtual
, FALSE
);
3829 FocusEvent(dev
, FocusIn
, mode
, NotifyNonlinear
, toWin
);
3830 if (IsParent(toWin
, sprite
.win
))
3831 (void)FocusInEvents(dev
, toWin
, sprite
.win
, NullWindow
,
3832 mode
, NotifyPointer
, FALSE
);
3839 * Set the input focus to the given window. Subsequent keyboard events will be
3840 * delivered to the given window.
3842 * Usually called from ProcSetInputFocus as result of a client request. If so,
3843 * the device is the inputInfo.keyboard.
3844 * If called from ProcXSetInputFocus as result of a client xinput request, the
3845 * device is set to the device specified by the client.
3847 * @param client Client that requested input focus change.
3848 * @param dev Focus device.
3849 * @param focusID The window to obtain the focus. Can be PointerRoot or None.
3850 * @param revertTo Specifies where the focus reverts to when window becomes
3852 * @param ctime Specifies the time.
3853 * @param followOK True if pointer is allowed to follow the keyboard.
3864 FocusClassPtr focus
;
3869 UpdateCurrentTime();
3870 if ((revertTo
!= RevertToParent
) &&
3871 (revertTo
!= RevertToPointerRoot
) &&
3872 (revertTo
!= RevertToNone
) &&
3873 ((revertTo
!= RevertToFollowKeyboard
) || !followOK
))
3875 client
->errorValue
= revertTo
;
3878 time
= ClientTimeToServerTime(ctime
);
3879 if ((focusID
== None
) || (focusID
== PointerRoot
))
3880 focusWin
= (WindowPtr
)(long)focusID
;
3881 else if ((focusID
== FollowKeyboard
) && followOK
)
3882 focusWin
= inputInfo
.keyboard
->focus
->win
;
3884 rc
= dixLookupWindow(&focusWin
, focusID
, client
, DixReadAccess
);
3887 /* It is a match error to try to set the input focus to an
3888 unviewable window. */
3889 if(!focusWin
->realized
)
3893 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
3894 (CompareTimeStamps(time
, focus
->time
) == EARLIER
))
3896 mode
= (dev
->grab
) ? NotifyWhileGrabbed
: NotifyNormal
;
3897 if (focus
->win
== FollowKeyboardWin
)
3898 DoFocusEvents(dev
, inputInfo
.keyboard
->focus
->win
, focusWin
, mode
);
3900 DoFocusEvents(dev
, focus
->win
, focusWin
, mode
);
3902 focus
->revert
= revertTo
;
3903 if (focusID
== FollowKeyboard
)
3904 focus
->win
= FollowKeyboardWin
;
3906 focus
->win
= focusWin
;
3907 if ((focusWin
== NoneWin
) || (focusWin
== PointerRootWin
))
3908 focus
->traceGood
= 0;
3914 for (pWin
= focusWin
; pWin
; pWin
= pWin
->parent
) depth
++;
3915 if (depth
> focus
->traceSize
)
3917 focus
->traceSize
= depth
+1;
3918 Must_have_memory
= TRUE
; /* XXX */
3919 focus
->trace
= (WindowPtr
*)xrealloc(focus
->trace
,
3922 Must_have_memory
= FALSE
; /* XXX */
3924 focus
->traceGood
= depth
;
3925 for (pWin
= focusWin
, depth
--; pWin
; pWin
= pWin
->parent
, depth
--)
3926 focus
->trace
[depth
] = pWin
;
3932 * Server-side protocol handling for SetInputFocus request.
3934 * Sets the input focus for the virtual core keyboard.
3937 ProcSetInputFocus(client
)
3940 REQUEST(xSetInputFocusReq
);
3942 REQUEST_SIZE_MATCH(xSetInputFocusReq
);
3944 if (!XaceHook(XACE_DEVICE_ACCESS
, client
, inputInfo
.keyboard
, TRUE
))
3947 return SetInputFocus(client
, inputInfo
.keyboard
, stuff
->focus
,
3948 stuff
->revertTo
, stuff
->time
, FALSE
);
3952 * Server-side protocol handling for GetInputFocus request.
3954 * Sends the current input focus for the virtual core keyboard back to the
3958 ProcGetInputFocus(ClientPtr client
)
3960 xGetInputFocusReply rep
;
3961 /* REQUEST(xReq); */
3962 FocusClassPtr focus
= inputInfo
.keyboard
->focus
;
3964 REQUEST_SIZE_MATCH(xReq
);
3967 rep
.sequenceNumber
= client
->sequence
;
3968 if (focus
->win
== NoneWin
)
3970 else if (focus
->win
== PointerRootWin
)
3971 rep
.focus
= PointerRoot
;
3972 else rep
.focus
= focus
->win
->drawable
.id
;
3973 rep
.revertTo
= focus
->revert
;
3974 WriteReplyToClient(client
, sizeof(xGetInputFocusReply
), &rep
);
3979 * Server-side protocol handling for Grabpointer request.
3981 * Sets an active grab on the inputInfo.pointer and returns success status to
3985 ProcGrabPointer(ClientPtr client
)
3987 xGrabPointerReply rep
;
3988 DeviceIntPtr device
= inputInfo
.pointer
;
3990 WindowPtr pWin
, confineTo
;
3991 CursorPtr cursor
, oldCursor
;
3992 REQUEST(xGrabPointerReq
);
3996 REQUEST_SIZE_MATCH(xGrabPointerReq
);
3997 UpdateCurrentTime();
3998 if ((stuff
->pointerMode
!= GrabModeSync
) &&
3999 (stuff
->pointerMode
!= GrabModeAsync
))
4001 client
->errorValue
= stuff
->pointerMode
;
4004 if ((stuff
->keyboardMode
!= GrabModeSync
) &&
4005 (stuff
->keyboardMode
!= GrabModeAsync
))
4007 client
->errorValue
= stuff
->keyboardMode
;
4010 if ((stuff
->ownerEvents
!= xFalse
) && (stuff
->ownerEvents
!= xTrue
))
4012 client
->errorValue
= stuff
->ownerEvents
;
4015 if (stuff
->eventMask
& ~PointerGrabMask
)
4017 client
->errorValue
= stuff
->eventMask
;
4020 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixReadAccess
);
4023 if (stuff
->confineTo
== None
)
4024 confineTo
= NullWindow
;
4027 rc
= dixLookupWindow(&confineTo
, stuff
->confineTo
, client
,
4032 if (stuff
->cursor
== None
)
4033 cursor
= NullCursor
;
4036 cursor
= (CursorPtr
)SecurityLookupIDByType(client
, stuff
->cursor
,
4037 RT_CURSOR
, DixReadAccess
);
4040 client
->errorValue
= stuff
->cursor
;
4044 /* at this point, some sort of reply is guaranteed. */
4045 time
= ClientTimeToServerTime(stuff
->time
);
4047 rep
.sequenceNumber
= client
->sequence
;
4049 grab
= device
->grab
;
4050 if ((grab
) && !SameClient(grab
, client
))
4051 rep
.status
= AlreadyGrabbed
;
4052 else if ((!pWin
->realized
) ||
4054 !(confineTo
->realized
&& BorderSizeNotEmpty(confineTo
))))
4055 rep
.status
= GrabNotViewable
;
4056 else if (device
->sync
.frozen
&&
4057 device
->sync
.other
&& !SameClient(device
->sync
.other
, client
))
4058 rep
.status
= GrabFrozen
;
4059 else if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
4060 (CompareTimeStamps(time
, device
->grabTime
) == EARLIER
))
4061 rep
.status
= GrabInvalidTime
;
4066 oldCursor
= NullCursor
;
4069 if (grab
->confineTo
&& !confineTo
)
4070 ConfineCursorToWindow(ROOT
, FALSE
, FALSE
);
4071 oldCursor
= grab
->cursor
;
4073 tempGrab
.cursor
= cursor
;
4074 tempGrab
.resource
= client
->clientAsMask
;
4075 tempGrab
.ownerEvents
= stuff
->ownerEvents
;
4076 tempGrab
.eventMask
= stuff
->eventMask
;
4077 tempGrab
.confineTo
= confineTo
;
4078 tempGrab
.window
= pWin
;
4079 tempGrab
.keyboardMode
= stuff
->keyboardMode
;
4080 tempGrab
.pointerMode
= stuff
->pointerMode
;
4081 tempGrab
.device
= device
;
4082 (*device
->ActivateGrab
)(device
, &tempGrab
, time
, FALSE
);
4084 FreeCursor (oldCursor
, (Cursor
)0);
4085 rep
.status
= GrabSuccess
;
4087 WriteReplyToClient(client
, sizeof(xGrabPointerReply
), &rep
);
4092 * Server-side protocol handling for ChangeActivePointerGrab request.
4094 * Changes properties of the grab hold by the client. If the client does not
4095 * hold an active grab on the device, nothing happens.
4097 * Works on the core pointer only.
4100 ProcChangeActivePointerGrab(ClientPtr client
)
4102 DeviceIntPtr device
= inputInfo
.pointer
;
4103 GrabPtr grab
= device
->grab
;
4104 CursorPtr newCursor
, oldCursor
;
4105 REQUEST(xChangeActivePointerGrabReq
);
4108 REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq
);
4109 if (stuff
->eventMask
& ~PointerGrabMask
)
4111 client
->errorValue
= stuff
->eventMask
;
4114 if (stuff
->cursor
== None
)
4115 newCursor
= NullCursor
;
4118 newCursor
= (CursorPtr
)SecurityLookupIDByType(client
, stuff
->cursor
,
4119 RT_CURSOR
, DixReadAccess
);
4122 client
->errorValue
= stuff
->cursor
;
4128 if (!SameClient(grab
, client
))
4130 time
= ClientTimeToServerTime(stuff
->time
);
4131 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
4132 (CompareTimeStamps(time
, device
->grabTime
) == EARLIER
))
4134 oldCursor
= grab
->cursor
;
4135 grab
->cursor
= newCursor
;
4137 newCursor
->refcnt
++;
4140 FreeCursor(oldCursor
, (Cursor
)0);
4141 grab
->eventMask
= stuff
->eventMask
;
4146 * Server-side protocol handling for UngrabPointer request.
4148 * Deletes the pointer grab on the core pointer device.
4151 ProcUngrabPointer(ClientPtr client
)
4153 DeviceIntPtr device
= inputInfo
.pointer
;
4156 REQUEST(xResourceReq
);
4158 REQUEST_SIZE_MATCH(xResourceReq
);
4159 UpdateCurrentTime();
4160 grab
= device
->grab
;
4161 time
= ClientTimeToServerTime(stuff
->id
);
4162 if ((CompareTimeStamps(time
, currentTime
) != LATER
) &&
4163 (CompareTimeStamps(time
, device
->grabTime
) != EARLIER
) &&
4164 (grab
) && SameClient(grab
, client
))
4165 (*device
->DeactivateGrab
)(device
);
4170 * Sets a grab on the given device.
4172 * Called from ProcGrabKeyboard to work on the inputInfo.keyboard.
4173 * Called from ProcXGrabDevice to work on the device specified by the client.
4175 * The parameters this_mode and other_mode represent the keyboard_mode and
4176 * pointer_mode parameters of XGrabKeyboard().
4177 * See man page for details on all the parameters
4179 * @param client Client that owns the grab.
4180 * @param dev The device to grab.
4181 * @param this_mode GrabModeSync or GrabModeAsync
4182 * @param other_mode GrabModeSync or GrabModeAsync
4183 * @param status Return code to be returned to the caller.
4185 * @returns Success or BadValue.
4188 GrabDevice(ClientPtr client
, DeviceIntPtr dev
,
4189 unsigned this_mode
, unsigned other_mode
, Window grabWindow
,
4190 unsigned ownerEvents
, Time ctime
, Mask mask
, CARD8
*status
)
4197 UpdateCurrentTime();
4198 if ((this_mode
!= GrabModeSync
) && (this_mode
!= GrabModeAsync
))
4200 client
->errorValue
= this_mode
;
4203 if ((other_mode
!= GrabModeSync
) && (other_mode
!= GrabModeAsync
))
4205 client
->errorValue
= other_mode
;
4208 if ((ownerEvents
!= xFalse
) && (ownerEvents
!= xTrue
))
4210 client
->errorValue
= ownerEvents
;
4213 rc
= dixLookupWindow(&pWin
, grabWindow
, client
, DixReadAccess
);
4216 time
= ClientTimeToServerTime(ctime
);
4218 if (grab
&& !SameClient(grab
, client
))
4219 *status
= AlreadyGrabbed
;
4220 else if (!pWin
->realized
)
4221 *status
= GrabNotViewable
;
4222 else if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
4223 (CompareTimeStamps(time
, dev
->grabTime
) == EARLIER
))
4224 *status
= GrabInvalidTime
;
4225 else if (dev
->sync
.frozen
&&
4226 dev
->sync
.other
&& !SameClient(dev
->sync
.other
, client
))
4227 *status
= GrabFrozen
;
4232 tempGrab
.window
= pWin
;
4233 tempGrab
.resource
= client
->clientAsMask
;
4234 tempGrab
.ownerEvents
= ownerEvents
;
4235 tempGrab
.keyboardMode
= this_mode
;
4236 tempGrab
.pointerMode
= other_mode
;
4237 tempGrab
.eventMask
= mask
;
4238 tempGrab
.device
= dev
;
4239 (*dev
->ActivateGrab
)(dev
, &tempGrab
, time
, FALSE
);
4240 *status
= GrabSuccess
;
4246 * Server-side protocol handling for GrabKeyboard request.
4248 * Grabs the inputInfo.keyboad and returns success status to client.
4251 ProcGrabKeyboard(ClientPtr client
)
4253 xGrabKeyboardReply rep
;
4254 REQUEST(xGrabKeyboardReq
);
4257 REQUEST_SIZE_MATCH(xGrabKeyboardReq
);
4259 if (XaceHook(XACE_DEVICE_ACCESS
, client
, inputInfo
.keyboard
, TRUE
))
4260 result
= GrabDevice(client
, inputInfo
.keyboard
, stuff
->keyboardMode
,
4261 stuff
->pointerMode
, stuff
->grabWindow
,
4262 stuff
->ownerEvents
, stuff
->time
,
4263 KeyPressMask
| KeyReleaseMask
, &rep
.status
);
4266 rep
.status
= AlreadyGrabbed
;
4269 if (result
!= Success
)
4272 rep
.sequenceNumber
= client
->sequence
;
4274 WriteReplyToClient(client
, sizeof(xGrabKeyboardReply
), &rep
);
4279 * Server-side protocol handling for UngrabKeyboard request.
4281 * Deletes a possible grab on the inputInfo.keyboard.
4284 ProcUngrabKeyboard(ClientPtr client
)
4286 DeviceIntPtr device
= inputInfo
.keyboard
;
4289 REQUEST(xResourceReq
);
4291 REQUEST_SIZE_MATCH(xResourceReq
);
4292 UpdateCurrentTime();
4293 grab
= device
->grab
;
4294 time
= ClientTimeToServerTime(stuff
->id
);
4295 if ((CompareTimeStamps(time
, currentTime
) != LATER
) &&
4296 (CompareTimeStamps(time
, device
->grabTime
) != EARLIER
) &&
4297 (grab
) && SameClient(grab
, client
))
4298 (*device
->DeactivateGrab
)(device
);
4303 * Server-side protocol handling for QueryPointer request.
4305 * Returns the current state and position of the core pointer to the client.
4308 ProcQueryPointer(ClientPtr client
)
4310 xQueryPointerReply rep
;
4312 REQUEST(xResourceReq
);
4313 DeviceIntPtr mouse
= inputInfo
.pointer
;
4316 REQUEST_SIZE_MATCH(xResourceReq
);
4317 rc
= dixLookupWindow(&pWin
, stuff
->id
, client
, DixReadAccess
);
4320 if (mouse
->valuator
->motionHintWindow
)
4321 MaybeStopHint(mouse
, client
);
4323 rep
.sequenceNumber
= client
->sequence
;
4324 rep
.mask
= mouse
->button
->state
| inputInfo
.keyboard
->key
->state
;
4326 rep
.root
= (ROOT
)->drawable
.id
;
4327 rep
.rootX
= sprite
.hot
.x
;
4328 rep
.rootY
= sprite
.hot
.y
;
4330 if (sprite
.hot
.pScreen
== pWin
->drawable
.pScreen
)
4332 rep
.sameScreen
= xTrue
;
4333 rep
.winX
= sprite
.hot
.x
- pWin
->drawable
.x
;
4334 rep
.winY
= sprite
.hot
.y
- pWin
->drawable
.y
;
4335 for (t
= sprite
.win
; t
; t
= t
->parent
)
4336 if (t
->parent
== pWin
)
4338 rep
.child
= t
->drawable
.id
;
4344 rep
.sameScreen
= xFalse
;
4350 if(!noPanoramiXExtension
) {
4351 rep
.rootX
+= panoramiXdataPtr
[0].x
;
4352 rep
.rootY
+= panoramiXdataPtr
[0].y
;
4353 if(stuff
->id
== rep
.root
) {
4354 rep
.winX
+= panoramiXdataPtr
[0].x
;
4355 rep
.winY
+= panoramiXdataPtr
[0].y
;
4360 WriteReplyToClient(client
, sizeof(xQueryPointerReply
), &rep
);
4366 * Initializes the device list and the DIX sprite to sane values. Allocates
4367 * trace memory used for quick window traversal.
4374 sprite
.hot
.pScreen
= sprite
.hotPhys
.pScreen
= (ScreenPtr
)NULL
;
4375 inputInfo
.numDevices
= 0;
4376 inputInfo
.devices
= (DeviceIntPtr
)NULL
;
4377 inputInfo
.off_devices
= (DeviceIntPtr
)NULL
;
4378 inputInfo
.keyboard
= (DeviceIntPtr
)NULL
;
4379 inputInfo
.pointer
= (DeviceIntPtr
)NULL
;
4380 if (spriteTraceSize
== 0)
4382 spriteTraceSize
= 32;
4383 spriteTrace
= (WindowPtr
*)xalloc(32*sizeof(WindowPtr
));
4385 FatalError("failed to allocate spriteTrace");
4387 spriteTraceGood
= 0;
4388 lastEventMask
= OwnerGrabButtonMask
;
4389 filters
[MotionNotify
] = PointerMotionMask
;
4393 sprite
.win
= NullWindow
;
4394 sprite
.current
= NullCursor
;
4395 sprite
.hotLimits
.x1
= 0;
4396 sprite
.hotLimits
.y1
= 0;
4397 sprite
.hotLimits
.x2
= 0;
4398 sprite
.hotLimits
.y2
= 0;
4399 sprite
.confined
= FALSE
;
4400 syncEvents
.replayDev
= (DeviceIntPtr
)NULL
;
4401 syncEvents
.replayWin
= NullWindow
;
4402 while (syncEvents
.pending
)
4404 QdEventPtr next
= syncEvents
.pending
->next
;
4405 xfree(syncEvents
.pending
);
4406 syncEvents
.pending
= next
;
4408 syncEvents
.pendtail
= &syncEvents
.pending
;
4409 syncEvents
.playingEvents
= FALSE
;
4410 syncEvents
.time
.months
= 0;
4411 syncEvents
.time
.milliseconds
= 0; /* hardly matters */
4412 currentTime
.months
= 0;
4413 currentTime
.milliseconds
= GetTimeInMillis();
4414 lastDeviceEventTime
= currentTime
;
4415 for (i
= 0; i
< DNPMCOUNT
; i
++)
4417 DontPropagateMasks
[i
] = 0;
4418 DontPropagateRefCnts
[i
] = 0;
4423 CloseDownEvents(void)
4427 spriteTraceSize
= 0;
4431 * Server-side protocol handling for SendEvent request.
4433 * Locates the window to send the event to and forwards the event.
4436 ProcSendEvent(ClientPtr client
)
4439 WindowPtr effectiveFocus
= NullWindow
; /* only set if dest==InputFocus */
4440 REQUEST(xSendEventReq
);
4442 REQUEST_SIZE_MATCH(xSendEventReq
);
4444 /* The client's event type must be a core event type or one defined by an
4447 if ( ! ((stuff
->event
.u
.u
.type
> X_Reply
&&
4448 stuff
->event
.u
.u
.type
< LASTEvent
) ||
4449 (stuff
->event
.u
.u
.type
>= EXTENSION_EVENT_BASE
&&
4450 stuff
->event
.u
.u
.type
< (unsigned)lastEvent
)))
4452 client
->errorValue
= stuff
->event
.u
.u
.type
;
4455 if (stuff
->event
.u
.u
.type
== ClientMessage
&&
4456 stuff
->event
.u
.u
.detail
!= 8 &&
4457 stuff
->event
.u
.u
.detail
!= 16 &&
4458 stuff
->event
.u
.u
.detail
!= 32)
4460 client
->errorValue
= stuff
->event
.u
.u
.detail
;
4463 if (stuff
->eventMask
& ~AllEventMasks
)
4465 client
->errorValue
= stuff
->eventMask
;
4469 if (stuff
->destination
== PointerWindow
)
4471 else if (stuff
->destination
== InputFocus
)
4473 WindowPtr inputFocus
= inputInfo
.keyboard
->focus
->win
;
4475 if (inputFocus
== NoneWin
)
4478 /* If the input focus is PointerRootWin, send the event to where
4479 the pointer is if possible, then perhaps propogate up to root. */
4480 if (inputFocus
== PointerRootWin
)
4483 if (IsParent(inputFocus
, sprite
.win
))
4485 effectiveFocus
= inputFocus
;
4489 effectiveFocus
= pWin
= inputFocus
;
4492 dixLookupWindow(&pWin
, stuff
->destination
, client
, DixReadAccess
);
4496 if ((stuff
->propagate
!= xFalse
) && (stuff
->propagate
!= xTrue
))
4498 client
->errorValue
= stuff
->propagate
;
4501 stuff
->event
.u
.u
.type
|= 0x80;
4502 if (stuff
->propagate
)
4504 for (;pWin
; pWin
= pWin
->parent
)
4506 if (DeliverEventsToWindow(pWin
, &stuff
->event
, 1, stuff
->eventMask
,
4509 if (pWin
== effectiveFocus
)
4511 stuff
->eventMask
&= ~wDontPropagateMask(pWin
);
4512 if (!stuff
->eventMask
)
4517 (void)DeliverEventsToWindow(pWin
, &stuff
->event
, 1, stuff
->eventMask
,
4523 * Server-side protocol handling for UngrabKey request.
4525 * Deletes a passive grab for the given key. Only works on the
4526 * inputInfo.keyboard.
4529 ProcUngrabKey(ClientPtr client
)
4531 REQUEST(xUngrabKeyReq
);
4534 DeviceIntPtr keybd
= inputInfo
.keyboard
;
4537 REQUEST_SIZE_MATCH(xUngrabKeyReq
);
4538 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixReadAccess
);
4542 if (((stuff
->key
> keybd
->key
->curKeySyms
.maxKeyCode
) ||
4543 (stuff
->key
< keybd
->key
->curKeySyms
.minKeyCode
))
4544 && (stuff
->key
!= AnyKey
))
4546 client
->errorValue
= stuff
->key
;
4549 if ((stuff
->modifiers
!= AnyModifier
) &&
4550 (stuff
->modifiers
& ~AllModifiersMask
))
4552 client
->errorValue
= stuff
->modifiers
;
4555 tempGrab
.resource
= client
->clientAsMask
;
4556 tempGrab
.device
= keybd
;
4557 tempGrab
.window
= pWin
;
4558 tempGrab
.modifiersDetail
.exact
= stuff
->modifiers
;
4559 tempGrab
.modifiersDetail
.pMask
= NULL
;
4560 tempGrab
.modifierDevice
= inputInfo
.keyboard
;
4561 tempGrab
.type
= KeyPress
;
4562 tempGrab
.detail
.exact
= stuff
->key
;
4563 tempGrab
.detail
.pMask
= NULL
;
4565 if (!DeletePassiveGrabFromList(&tempGrab
))
4571 * Server-side protocol handling for GrabKey request.
4573 * Creates a grab for the inputInfo.keyboard and adds it to the list of
4577 ProcGrabKey(ClientPtr client
)
4580 REQUEST(xGrabKeyReq
);
4582 DeviceIntPtr keybd
= inputInfo
.keyboard
;
4585 REQUEST_SIZE_MATCH(xGrabKeyReq
);
4586 if ((stuff
->ownerEvents
!= xTrue
) && (stuff
->ownerEvents
!= xFalse
))
4588 client
->errorValue
= stuff
->ownerEvents
;
4591 if ((stuff
->pointerMode
!= GrabModeSync
) &&
4592 (stuff
->pointerMode
!= GrabModeAsync
))
4594 client
->errorValue
= stuff
->pointerMode
;
4597 if ((stuff
->keyboardMode
!= GrabModeSync
) &&
4598 (stuff
->keyboardMode
!= GrabModeAsync
))
4600 client
->errorValue
= stuff
->keyboardMode
;
4603 if (((stuff
->key
> keybd
->key
->curKeySyms
.maxKeyCode
) ||
4604 (stuff
->key
< keybd
->key
->curKeySyms
.minKeyCode
))
4605 && (stuff
->key
!= AnyKey
))
4607 client
->errorValue
= stuff
->key
;
4610 if ((stuff
->modifiers
!= AnyModifier
) &&
4611 (stuff
->modifiers
& ~AllModifiersMask
))
4613 client
->errorValue
= stuff
->modifiers
;
4616 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixReadAccess
);
4620 grab
= CreateGrab(client
->index
, keybd
, pWin
,
4621 (Mask
)(KeyPressMask
| KeyReleaseMask
), (Bool
)stuff
->ownerEvents
,
4622 (Bool
)stuff
->keyboardMode
, (Bool
)stuff
->pointerMode
,
4623 keybd
, stuff
->modifiers
, KeyPress
, stuff
->key
,
4624 NullWindow
, NullCursor
);
4627 return AddPassiveGrabToList(grab
);
4632 * Server-side protocol handling for GrabButton request.
4634 * Creates a grab for the inputInfo.pointer and adds it as a passive grab to
4638 ProcGrabButton(ClientPtr client
)
4640 WindowPtr pWin
, confineTo
;
4641 REQUEST(xGrabButtonReq
);
4646 REQUEST_SIZE_MATCH(xGrabButtonReq
);
4647 if ((stuff
->pointerMode
!= GrabModeSync
) &&
4648 (stuff
->pointerMode
!= GrabModeAsync
))
4650 client
->errorValue
= stuff
->pointerMode
;
4653 if ((stuff
->keyboardMode
!= GrabModeSync
) &&
4654 (stuff
->keyboardMode
!= GrabModeAsync
))
4656 client
->errorValue
= stuff
->keyboardMode
;
4659 if ((stuff
->modifiers
!= AnyModifier
) &&
4660 (stuff
->modifiers
& ~AllModifiersMask
))
4662 client
->errorValue
= stuff
->modifiers
;
4665 if ((stuff
->ownerEvents
!= xFalse
) && (stuff
->ownerEvents
!= xTrue
))
4667 client
->errorValue
= stuff
->ownerEvents
;
4670 if (stuff
->eventMask
& ~PointerGrabMask
)
4672 client
->errorValue
= stuff
->eventMask
;
4675 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixReadAccess
);
4678 if (stuff
->confineTo
== None
)
4679 confineTo
= NullWindow
;
4681 rc
= dixLookupWindow(&confineTo
, stuff
->confineTo
, client
,
4686 if (stuff
->cursor
== None
)
4687 cursor
= NullCursor
;
4690 cursor
= (CursorPtr
)SecurityLookupIDByType(client
, stuff
->cursor
,
4691 RT_CURSOR
, DixReadAccess
);
4694 client
->errorValue
= stuff
->cursor
;
4700 grab
= CreateGrab(client
->index
, inputInfo
.pointer
, pWin
,
4701 (Mask
)stuff
->eventMask
, (Bool
)stuff
->ownerEvents
,
4702 (Bool
) stuff
->keyboardMode
, (Bool
)stuff
->pointerMode
,
4703 inputInfo
.keyboard
, stuff
->modifiers
, ButtonPress
,
4704 stuff
->button
, confineTo
, cursor
);
4707 return AddPassiveGrabToList(grab
);
4711 * Server-side protocol handling for UngrabButton request.
4713 * Deletes a passive grab on the inputInfo.pointer from the list.
4716 ProcUngrabButton(ClientPtr client
)
4718 REQUEST(xUngrabButtonReq
);
4723 REQUEST_SIZE_MATCH(xUngrabButtonReq
);
4724 if ((stuff
->modifiers
!= AnyModifier
) &&
4725 (stuff
->modifiers
& ~AllModifiersMask
))
4727 client
->errorValue
= stuff
->modifiers
;
4730 rc
= dixLookupWindow(&pWin
, stuff
->grabWindow
, client
, DixReadAccess
);
4733 tempGrab
.resource
= client
->clientAsMask
;
4734 tempGrab
.device
= inputInfo
.pointer
;
4735 tempGrab
.window
= pWin
;
4736 tempGrab
.modifiersDetail
.exact
= stuff
->modifiers
;
4737 tempGrab
.modifiersDetail
.pMask
= NULL
;
4738 tempGrab
.modifierDevice
= inputInfo
.keyboard
;
4739 tempGrab
.type
= ButtonPress
;
4740 tempGrab
.detail
.exact
= stuff
->button
;
4741 tempGrab
.detail
.pMask
= NULL
;
4743 if (!DeletePassiveGrabFromList(&tempGrab
))
4749 * Deactivate any grab that may be on the window, remove the focus.
4750 * Delete any XInput extension events from the window too. Does not change the
4751 * window mask. Use just before the window is deleted.
4753 * If freeResources is set, passive grabs on the window are deleted.
4755 * @param pWin The window to delete events from.
4756 * @param freeResources True if resources associated with the window should be
4760 DeleteWindowFromAnyEvents(WindowPtr pWin
, Bool freeResources
)
4763 DeviceIntPtr mouse
= inputInfo
.pointer
;
4764 DeviceIntPtr keybd
= inputInfo
.keyboard
;
4765 FocusClassPtr focus
= keybd
->focus
;
4770 /* Deactivate any grabs performed on this window, before making any
4771 input focus changes. */
4774 ((mouse
->grab
->window
== pWin
) || (mouse
->grab
->confineTo
== pWin
)))
4775 (*mouse
->DeactivateGrab
)(mouse
);
4777 /* Deactivating a keyboard grab should cause focus events. */
4779 if (keybd
->grab
&& (keybd
->grab
->window
== pWin
))
4780 (*keybd
->DeactivateGrab
)(keybd
);
4782 /* If the focus window is a root window (ie. has no parent) then don't
4783 delete the focus from it. */
4785 if ((pWin
== focus
->win
) && (pWin
->parent
!= NullWindow
))
4787 int focusEventMode
= NotifyNormal
;
4789 /* If a grab is in progress, then alter the mode of focus events. */
4792 focusEventMode
= NotifyWhileGrabbed
;
4794 switch (focus
->revert
)
4797 DoFocusEvents(keybd
, pWin
, NoneWin
, focusEventMode
);
4798 focus
->win
= NoneWin
;
4799 focus
->traceGood
= 0;
4801 case RevertToParent
:
4805 parent
= parent
->parent
;
4807 } while (!parent
->realized
4808 /* This would be a good protocol change -- windows being reparented
4809 during SaveSet processing would cause the focus to revert to the
4810 nearest enclosing window which will survive the death of the exiting
4811 client, instead of ending up reverting to a dying window and thence
4815 || clients
[CLIENT_ID(parent
->drawable
.id
)]->clientGone
4818 DoFocusEvents(keybd
, pWin
, parent
, focusEventMode
);
4819 focus
->win
= parent
;
4820 focus
->revert
= RevertToNone
;
4822 case RevertToPointerRoot
:
4823 DoFocusEvents(keybd
, pWin
, PointerRootWin
, focusEventMode
);
4824 focus
->win
= PointerRootWin
;
4825 focus
->traceGood
= 0;
4830 if (mouse
->valuator
->motionHintWindow
== pWin
)
4831 mouse
->valuator
->motionHintWindow
= NullWindow
;
4835 if (pWin
->dontPropagate
)
4836 DontPropagateRefCnts
[pWin
->dontPropagate
]--;
4837 while ( (oc
= wOtherClients(pWin
)) )
4838 FreeResource(oc
->resource
, RT_NONE
);
4839 while ( (passive
= wPassiveGrabs(pWin
)) )
4840 FreeResource(passive
->resource
, RT_NONE
);
4843 DeleteWindowFromAnyExtEvents(pWin
, freeResources
);
4848 * Call this whenever some window at or below pWin has changed geometry. If
4849 * there is a grab on the window, the cursor will be re-confined into the
4853 CheckCursorConfinement(WindowPtr pWin
)
4855 GrabPtr grab
= inputInfo
.pointer
->grab
;
4856 WindowPtr confineTo
;
4859 if(!noPanoramiXExtension
&& pWin
->drawable
.pScreen
->myNum
) return;
4862 if (grab
&& (confineTo
= grab
->confineTo
))
4864 if (!BorderSizeNotEmpty(confineTo
))
4865 (*inputInfo
.pointer
->DeactivateGrab
)(inputInfo
.pointer
);
4866 else if ((pWin
== confineTo
) || IsParent(pWin
, confineTo
))
4867 ConfineCursorToWindow(confineTo
, TRUE
, TRUE
);
4872 EventMaskForClient(WindowPtr pWin
, ClientPtr client
)
4874 OtherClientsPtr other
;
4876 if (wClient (pWin
) == client
)
4877 return pWin
->eventMask
;
4878 for (other
= wOtherClients(pWin
); other
; other
= other
->next
)
4880 if (SameClient(other
, client
))
4887 * Server-side protocol handling for RecolorCursor request.
4890 ProcRecolorCursor(ClientPtr client
)
4896 REQUEST(xRecolorCursorReq
);
4898 REQUEST_SIZE_MATCH(xRecolorCursorReq
);
4899 pCursor
= (CursorPtr
)SecurityLookupIDByType(client
, stuff
->cursor
,
4900 RT_CURSOR
, DixWriteAccess
);
4903 client
->errorValue
= stuff
->cursor
;
4907 pCursor
->foreRed
= stuff
->foreRed
;
4908 pCursor
->foreGreen
= stuff
->foreGreen
;
4909 pCursor
->foreBlue
= stuff
->foreBlue
;
4911 pCursor
->backRed
= stuff
->backRed
;
4912 pCursor
->backGreen
= stuff
->backGreen
;
4913 pCursor
->backBlue
= stuff
->backBlue
;
4915 for (nscr
= 0; nscr
< screenInfo
.numScreens
; nscr
++)
4917 pscr
= screenInfo
.screens
[nscr
];
4919 if(!noPanoramiXExtension
)
4920 displayed
= (pscr
== sprite
.screen
);
4923 displayed
= (pscr
== sprite
.hotPhys
.pScreen
);
4924 ( *pscr
->RecolorCursor
)(pscr
, pCursor
,
4925 (pCursor
== sprite
.current
) && displayed
);
4931 * Write the given events to a client, swapping the byte order if necessary.
4932 * To swap the byte ordering, a callback is called that has to be set up for
4933 * the given event type.
4935 * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
4936 * can be more than one. Usually it's just one event.
4938 * Do not modify the event structure passed in. See comment below.
4940 * @param pClient Client to send events to.
4941 * @param count Number of events.
4942 * @param events The event list.
4945 WriteEventsToClient(ClientPtr pClient
, int count
, xEvent
*events
)
4950 xEvent eventTo
, *eventFrom
;
4954 if ((!noXkbExtension
)&&(!XkbFilterEvents(pClient
, count
, events
)))
4959 if(!noPanoramiXExtension
&&
4960 (panoramiXdataPtr
[0].x
|| panoramiXdataPtr
[0].y
))
4962 switch(events
->u
.u
.type
) {
4971 When multiple clients want the same event DeliverEventsToWindow
4972 passes the same event structure multiple times so we can't
4973 modify the one passed to us
4975 count
= 1; /* should always be 1 */
4976 memcpy(&eventCopy
, events
, sizeof(xEvent
));
4977 eventCopy
.u
.keyButtonPointer
.rootX
+= panoramiXdataPtr
[0].x
;
4978 eventCopy
.u
.keyButtonPointer
.rootY
+= panoramiXdataPtr
[0].y
;
4979 if(eventCopy
.u
.keyButtonPointer
.event
==
4980 eventCopy
.u
.keyButtonPointer
.root
)
4982 eventCopy
.u
.keyButtonPointer
.eventX
+= panoramiXdataPtr
[0].x
;
4983 eventCopy
.u
.keyButtonPointer
.eventY
+= panoramiXdataPtr
[0].y
;
4985 events
= &eventCopy
;
4994 EventInfoRec eventinfo
;
4995 eventinfo
.client
= pClient
;
4996 eventinfo
.events
= events
;
4997 eventinfo
.count
= count
;
4998 CallCallbacks(&EventCallback
, (pointer
)&eventinfo
);
5000 #ifdef XSERVER_DTRACE
5001 if (XSERVER_SEND_EVENT_ENABLED()) {
5002 for (i
= 0; i
< count
; i
++)
5004 XSERVER_SEND_EVENT(pClient
->index
, events
[i
].u
.u
.type
, &events
[i
]);
5008 if(pClient
->swapped
)
5010 for(i
= 0; i
< count
; i
++)
5012 eventFrom
= &events
[i
];
5013 /* Remember to strip off the leading bit of type in case
5014 this event was sent with "SendEvent." */
5015 (*EventSwapVector
[eventFrom
->u
.u
.type
& 0177])
5016 (eventFrom
, &eventTo
);
5017 (void)WriteToClient(pClient
, sizeof(xEvent
), (char *)&eventTo
);
5022 (void)WriteToClient(pClient
, count
* sizeof(xEvent
), (char *) events
);