1 /************************************************************
3 Copyright 1989, 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.
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Hewlett-Packard not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
37 HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 ********************************************************/
47 /********************************************************************
49 * Routines to register and initialize extension input devices.
50 * This also contains ProcessOtherEvent, the routine called from DDX
51 * to route extension events.
56 #ifdef HAVE_DIX_CONFIG_H
57 #include <dix-config.h>
61 #include <X11/Xproto.h>
62 #include <X11/extensions/XI.h>
63 #include <X11/extensions/XIproto.h>
65 #include "windowstr.h"
66 #include "miscstruct.h"
69 #include "extnsionst.h"
70 #include "extinit.h" /* LookupDeviceIntRec */
71 #include "exglobals.h"
72 #include "dixevents.h" /* DeliverFocusedEvent */
73 #include "dixgrabs.h" /* CreateGrab() */
74 #include "scrnintstr.h"
76 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
77 #define AllModifiersMask ( \
78 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
79 Mod3Mask | Mod4Mask | Mod5Mask )
80 #define AllButtonsMask ( \
81 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
82 #define Motion_Filter(class) (DevicePointerMotionMask | \
83 (class)->state | (class)->motionMask)
85 static Bool
ShouldFreeInputMasks(WindowPtr
/* pWin */ ,
86 Bool
/* ignoreSelectedEvents */
88 static Bool
MakeInputMasks(WindowPtr
/* pWin */
91 /**************************************************************************
93 * Procedures for extension device event routing.
98 RegisterOtherDevice(DeviceIntPtr device
)
100 device
->public.processInputProc
= ProcessOtherEvent
;
101 device
->public.realInputProc
= ProcessOtherEvent
;
102 (device
)->ActivateGrab
= ActivateKeyboardGrab
;
103 (device
)->DeactivateGrab
= DeactivateKeyboardGrab
;
107 ProcessOtherEvent(xEventPtr xE
, DeviceIntPtr other
, int count
)
113 GrabPtr grab
= other
->grab
;
114 Bool deactivateDeviceGrab
= FALSE
;
115 int key
= 0, bit
= 0, rootX
, rootY
;
116 ButtonClassPtr b
= other
->button
;
117 KeyClassPtr k
= other
->key
;
118 ValuatorClassPtr v
= other
->valuator
;
119 deviceValuator
*xV
= (deviceValuator
*) xE
;
121 if (xE
->u
.u
.type
!= DeviceValuator
) {
122 GetSpritePosition(&rootX
, &rootY
);
123 xE
->u
.keyButtonPointer
.rootX
= rootX
;
124 xE
->u
.keyButtonPointer
.rootY
= rootY
;
125 key
= xE
->u
.u
.detail
;
127 xE
->u
.keyButtonPointer
.state
= inputInfo
.keyboard
->key
->state
|
128 inputInfo
.pointer
->button
->state
;
129 bit
= 1 << (key
& 7);
131 if (DeviceEventCallback
) {
132 DeviceEventInfoRec eventinfo
;
134 eventinfo
.events
= (xEventPtr
) xE
;
135 eventinfo
.count
= count
;
136 CallCallbacks(&DeviceEventCallback
, (pointer
) & eventinfo
);
138 for (i
= 1; i
< count
; i
++)
139 if ((++xV
)->type
== DeviceValuator
) {
140 int first
= xV
->first_valuator
;
143 if (xV
->num_valuators
145 || (xV
->num_valuators
146 && (first
+ xV
->num_valuators
> v
->numAxes
))))
147 FatalError("Bad valuators reported for device %s\n",
149 xV
->device_state
= 0;
151 xV
->device_state
|= k
->state
;
153 xV
->device_state
|= b
->state
;
154 if (v
&& v
->axisVal
) {
155 axisvals
= v
->axisVal
;
156 switch (xV
->num_valuators
) {
158 *(axisvals
+ first
+ 5) = xV
->valuator5
;
160 *(axisvals
+ first
+ 4) = xV
->valuator4
;
162 *(axisvals
+ first
+ 3) = xV
->valuator3
;
164 *(axisvals
+ first
+ 2) = xV
->valuator2
;
166 *(axisvals
+ first
+ 1) = xV
->valuator1
;
168 *(axisvals
+ first
) = xV
->valuator0
;
176 if (xE
->u
.u
.type
== DeviceKeyPress
) {
180 modifiers
= k
->modifierMap
[key
];
181 kptr
= &k
->down
[key
>> 3];
182 if (*kptr
& bit
) { /* allow ddx to generate multiple downs */
184 xE
->u
.u
.type
= DeviceKeyRelease
;
185 ProcessOtherEvent(xE
, other
, count
);
186 xE
->u
.u
.type
= DeviceKeyPress
;
187 /* release can have side effects, don't fall through */
188 ProcessOtherEvent(xE
, other
, count
);
193 other
->valuator
->motionHintWindow
= NullWindow
;
195 k
->prev_state
= k
->state
;
196 for (i
= 0, mask
= 1; modifiers
; i
++, mask
<<= 1) {
197 if (mask
& modifiers
) {
198 /* This key affects modifier "i" */
199 k
->modifierKeyCount
[i
]++;
204 if (!grab
&& CheckDeviceGrabs(other
, xE
, 0, count
)) {
205 other
->activatingKey
= key
;
208 } else if (xE
->u
.u
.type
== DeviceKeyRelease
) {
212 kptr
= &k
->down
[key
>> 3];
213 if (!(*kptr
& bit
)) /* guard against duplicates */
215 modifiers
= k
->modifierMap
[key
];
217 other
->valuator
->motionHintWindow
= NullWindow
;
219 k
->prev_state
= k
->state
;
220 for (i
= 0, mask
= 1; modifiers
; i
++, mask
<<= 1) {
221 if (mask
& modifiers
) {
222 /* This key affects modifier "i" */
223 if (--k
->modifierKeyCount
[i
] <= 0) {
224 k
->modifierKeyCount
[i
] = 0;
231 if (other
->fromPassiveGrab
&& (key
== other
->activatingKey
))
232 deactivateDeviceGrab
= TRUE
;
233 } else if (xE
->u
.u
.type
== DeviceButtonPress
) {
237 kptr
= &b
->down
[key
>> 3];
240 other
->valuator
->motionHintWindow
= NullWindow
;
242 b
->motionMask
= DeviceButtonMotionMask
;
243 xE
->u
.u
.detail
= b
->map
[key
];
244 if (xE
->u
.u
.detail
== 0)
246 if (xE
->u
.u
.detail
<= 5)
247 b
->state
|= (Button1Mask
>> 1) << xE
->u
.u
.detail
;
248 SetMaskForEvent(Motion_Filter(b
), DeviceMotionNotify
);
250 if (CheckDeviceGrabs(other
, xE
, 0, count
))
251 /* if a passive grab was activated, the event has been sent
255 } else if (xE
->u
.u
.type
== DeviceButtonRelease
) {
259 kptr
= &b
->down
[key
>> 3];
262 other
->valuator
->motionHintWindow
= NullWindow
;
263 if (b
->buttonsDown
>= 1 && !--b
->buttonsDown
)
265 xE
->u
.u
.detail
= b
->map
[key
];
266 if (xE
->u
.u
.detail
== 0)
268 if (xE
->u
.u
.detail
<= 5)
269 b
->state
&= ~((Button1Mask
>> 1) << xE
->u
.u
.detail
);
270 SetMaskForEvent(Motion_Filter(b
), DeviceMotionNotify
);
271 if (!b
->state
&& other
->fromPassiveGrab
)
272 deactivateDeviceGrab
= TRUE
;
273 } else if (xE
->u
.u
.type
== ProximityIn
)
274 other
->valuator
->mode
&= ~OutOfProximity
;
275 else if (xE
->u
.u
.type
== ProximityOut
)
276 other
->valuator
->mode
|= OutOfProximity
;
279 DeliverGrabbedEvent(xE
, other
, deactivateDeviceGrab
, count
);
280 else if (other
->focus
)
281 DeliverFocusedEvent(other
, xE
, GetSpriteWindow(), count
);
283 DeliverDeviceEvents(GetSpriteWindow(), xE
, NullGrab
, NullWindow
,
286 if (deactivateDeviceGrab
== TRUE
)
287 (*other
->DeactivateGrab
) (other
);
291 InitProximityClassDeviceStruct(DeviceIntPtr dev
)
293 ProximityClassPtr proxc
;
295 proxc
= (ProximityClassPtr
) xalloc(sizeof(ProximityClassRec
));
298 dev
->proximity
= proxc
;
303 InitValuatorAxisStruct(DeviceIntPtr dev
, int axnum
, int minval
, int maxval
,
304 int resolution
, int min_res
, int max_res
)
308 if (!dev
|| !dev
->valuator
)
311 ax
= dev
->valuator
->axes
+ axnum
;
313 ax
->min_value
= minval
;
314 ax
->max_value
= maxval
;
315 ax
->resolution
= resolution
;
316 ax
->min_resolution
= min_res
;
317 ax
->max_resolution
= max_res
;
321 FixDeviceStateNotify(DeviceIntPtr dev
, deviceStateNotify
* ev
, KeyClassPtr k
,
322 ButtonClassPtr b
, ValuatorClassPtr v
, int first
)
324 ev
->type
= DeviceStateNotify
;
325 ev
->deviceid
= dev
->id
;
326 ev
->time
= currentTime
.milliseconds
;
327 ev
->classes_reported
= 0;
330 ev
->num_valuators
= 0;
333 ev
->classes_reported
|= (1 << ButtonClass
);
334 ev
->num_buttons
= b
->numButtons
;
335 memmove((char *)&ev
->buttons
[0], (char *)b
->down
, 4);
337 ev
->classes_reported
|= (1 << KeyClass
);
338 ev
->num_keys
= k
->curKeySyms
.maxKeyCode
- k
->curKeySyms
.minKeyCode
;
339 memmove((char *)&ev
->keys
[0], (char *)k
->down
, 4);
342 int nval
= v
->numAxes
- first
;
344 ev
->classes_reported
|= (1 << ValuatorClass
);
345 ev
->classes_reported
|= (dev
->valuator
->mode
<< ModeBitsShift
);
346 ev
->num_valuators
= nval
< 3 ? nval
: 3;
347 switch (ev
->num_valuators
) {
349 ev
->valuator2
= v
->axisVal
[first
+ 2];
351 ev
->valuator1
= v
->axisVal
[first
+ 1];
353 ev
->valuator0
= v
->axisVal
[first
];
360 FixDeviceValuator(DeviceIntPtr dev
, deviceValuator
* ev
, ValuatorClassPtr v
,
363 int nval
= v
->numAxes
- first
;
365 ev
->type
= DeviceValuator
;
366 ev
->deviceid
= dev
->id
;
367 ev
->num_valuators
= nval
< 3 ? nval
: 3;
368 ev
->first_valuator
= first
;
369 switch (ev
->num_valuators
) {
371 ev
->valuator2
= v
->axisVal
[first
+ 2];
373 ev
->valuator1
= v
->axisVal
[first
+ 1];
375 ev
->valuator0
= v
->axisVal
[first
];
378 first
+= ev
->num_valuators
;
382 DeviceFocusEvent(DeviceIntPtr dev
, int type
, int mode
, int detail
,
388 type
= DeviceFocusIn
;
390 type
= DeviceFocusOut
;
392 event
.deviceid
= dev
->id
;
395 event
.detail
= detail
;
396 event
.window
= pWin
->drawable
.id
;
397 event
.time
= currentTime
.milliseconds
;
399 (void)DeliverEventsToWindow(pWin
, (xEvent
*) & event
, 1,
400 DeviceFocusChangeMask
, NullGrab
, dev
->id
);
402 if ((type
== DeviceFocusIn
) &&
403 (wOtherInputMasks(pWin
)) &&
404 (wOtherInputMasks(pWin
)->inputEvents
[dev
->id
] & DeviceStateNotifyMask
))
407 deviceStateNotify
*ev
, *sev
;
408 deviceKeyStateNotify
*kev
;
409 deviceButtonStateNotify
*bev
;
414 int nval
= 0, nkeys
= 0, nbuttons
= 0, first
= 0;
416 if ((b
= dev
->button
) != NULL
) {
417 nbuttons
= b
->numButtons
;
421 if ((k
= dev
->key
) != NULL
) {
422 nkeys
= k
->curKeySyms
.maxKeyCode
- k
->curKeySyms
.minKeyCode
;
429 if ((v
= dev
->valuator
) != NULL
) {
438 evcount
+= ((nval
- 7) / 3);
442 sev
= ev
= (deviceStateNotify
*) xalloc(evcount
* sizeof(xEvent
));
443 FixDeviceStateNotify(dev
, ev
, NULL
, NULL
, NULL
, first
);
446 FixDeviceStateNotify(dev
, ev
++, NULL
, b
, v
, first
);
450 (ev
- 1)->deviceid
|= MORE_EVENTS
;
451 bev
= (deviceButtonStateNotify
*) ev
++;
452 bev
->type
= DeviceButtonStateNotify
;
453 bev
->deviceid
= dev
->id
;
454 memmove((char *)&bev
->buttons
[0], (char *)&b
->down
[4], 28);
457 (ev
- 1)->deviceid
|= MORE_EVENTS
;
458 FixDeviceValuator(dev
, (deviceValuator
*) ev
++, v
, first
);
465 FixDeviceStateNotify(dev
, ev
++, k
, NULL
, v
, first
);
469 (ev
- 1)->deviceid
|= MORE_EVENTS
;
470 kev
= (deviceKeyStateNotify
*) ev
++;
471 kev
->type
= DeviceKeyStateNotify
;
472 kev
->deviceid
= dev
->id
;
473 memmove((char *)&kev
->keys
[0], (char *)&k
->down
[4], 28);
476 (ev
- 1)->deviceid
|= MORE_EVENTS
;
477 FixDeviceValuator(dev
, (deviceValuator
*) ev
++, v
, first
);
484 FixDeviceStateNotify(dev
, ev
++, NULL
, NULL
, v
, first
);
488 (ev
- 1)->deviceid
|= MORE_EVENTS
;
489 FixDeviceValuator(dev
, (deviceValuator
*) ev
++, v
, first
);
495 (void)DeliverEventsToWindow(pWin
, (xEvent
*) sev
, evcount
,
496 DeviceStateNotifyMask
, NullGrab
, dev
->id
);
502 GrabButton(ClientPtr client
, DeviceIntPtr dev
, BYTE this_device_mode
,
503 BYTE other_devices_mode
, CARD16 modifiers
,
504 DeviceIntPtr modifier_device
, CARD8 button
, Window grabWindow
,
505 BOOL ownerEvents
, Cursor rcursor
, Window rconfineTo
, Mask eventMask
)
507 WindowPtr pWin
, confineTo
;
512 if ((this_device_mode
!= GrabModeSync
) &&
513 (this_device_mode
!= GrabModeAsync
)) {
514 client
->errorValue
= this_device_mode
;
517 if ((other_devices_mode
!= GrabModeSync
) &&
518 (other_devices_mode
!= GrabModeAsync
)) {
519 client
->errorValue
= other_devices_mode
;
522 if ((modifiers
!= AnyModifier
) && (modifiers
& ~AllModifiersMask
)) {
523 client
->errorValue
= modifiers
;
526 if ((ownerEvents
!= xFalse
) && (ownerEvents
!= xTrue
)) {
527 client
->errorValue
= ownerEvents
;
530 rc
= dixLookupWindow(&pWin
, grabWindow
, client
, DixUnknownAccess
);
533 if (rconfineTo
== None
)
534 confineTo
= NullWindow
;
536 rc
= dixLookupWindow(&confineTo
, rconfineTo
, client
, DixUnknownAccess
);
543 cursor
= (CursorPtr
) LookupIDByType(rcursor
, RT_CURSOR
);
545 client
->errorValue
= rcursor
;
550 grab
= CreateGrab(client
->index
, dev
, pWin
, eventMask
,
551 (Bool
) ownerEvents
, (Bool
) this_device_mode
,
552 (Bool
) other_devices_mode
, modifier_device
, modifiers
,
553 DeviceButtonPress
, button
, confineTo
, cursor
);
556 return AddPassiveGrabToList(grab
);
560 GrabKey(ClientPtr client
, DeviceIntPtr dev
, BYTE this_device_mode
,
561 BYTE other_devices_mode
, CARD16 modifiers
,
562 DeviceIntPtr modifier_device
, CARD8 key
, Window grabWindow
,
563 BOOL ownerEvents
, Mask mask
)
567 KeyClassPtr k
= dev
->key
;
572 if ((other_devices_mode
!= GrabModeSync
) &&
573 (other_devices_mode
!= GrabModeAsync
)) {
574 client
->errorValue
= other_devices_mode
;
577 if ((this_device_mode
!= GrabModeSync
) &&
578 (this_device_mode
!= GrabModeAsync
)) {
579 client
->errorValue
= this_device_mode
;
582 if (((key
> k
->curKeySyms
.maxKeyCode
) || (key
< k
->curKeySyms
.minKeyCode
))
583 && (key
!= AnyKey
)) {
584 client
->errorValue
= key
;
587 if ((modifiers
!= AnyModifier
) && (modifiers
& ~AllModifiersMask
)) {
588 client
->errorValue
= modifiers
;
591 if ((ownerEvents
!= xTrue
) && (ownerEvents
!= xFalse
)) {
592 client
->errorValue
= ownerEvents
;
595 rc
= dixLookupWindow(&pWin
, grabWindow
, client
, DixUnknownAccess
);
599 grab
= CreateGrab(client
->index
, dev
, pWin
,
600 mask
, ownerEvents
, this_device_mode
, other_devices_mode
,
601 modifier_device
, modifiers
, DeviceKeyPress
, key
,
602 NullWindow
, NullCursor
);
605 return AddPassiveGrabToList(grab
);
609 SelectForWindow(DeviceIntPtr dev
, WindowPtr pWin
, ClientPtr client
,
610 Mask mask
, Mask exclusivemasks
, Mask validmasks
)
612 int mskidx
= dev
->id
;
615 InputClientsPtr others
;
617 if (mask
& ~validmasks
) {
618 client
->errorValue
= mask
;
621 check
= (mask
& exclusivemasks
);
622 if (wOtherInputMasks(pWin
)) {
623 if (check
& wOtherInputMasks(pWin
)->inputEvents
[mskidx
]) { /* It is illegal for two different
624 * clients to select on any of the
625 * events for maskcheck. However,
626 * it is OK, for some client to
627 * continue selecting on one of those
629 for (others
= wOtherInputMasks(pWin
)->inputClients
; others
;
630 others
= others
->next
) {
631 if (!SameClient(others
, client
) && (check
&
632 others
->mask
[mskidx
]))
636 for (others
= wOtherInputMasks(pWin
)->inputClients
; others
;
637 others
= others
->next
) {
638 if (SameClient(others
, client
)) {
639 check
= others
->mask
[mskidx
];
640 others
->mask
[mskidx
] = mask
;
642 for (i
= 0; i
< EMASKSIZE
; i
++)
643 if (i
!= mskidx
&& others
->mask
[i
] != 0)
645 if (i
== EMASKSIZE
) {
646 RecalculateDeviceDeliverableEvents(pWin
);
647 if (ShouldFreeInputMasks(pWin
, FALSE
))
648 FreeResource(others
->resource
, RT_NONE
);
657 if ((ret
= AddExtensionClient(pWin
, client
, mask
, mskidx
)) != Success
)
661 if ((dev
->valuator
->motionHintWindow
== pWin
) &&
662 (mask
& DevicePointerMotionHintMask
) &&
663 !(check
& DevicePointerMotionHintMask
) && !dev
->grab
)
664 dev
->valuator
->motionHintWindow
= NullWindow
;
665 RecalculateDeviceDeliverableEvents(pWin
);
670 AddExtensionClient(WindowPtr pWin
, ClientPtr client
, Mask mask
, int mskidx
)
672 InputClientsPtr others
;
674 if (!pWin
->optional
&& !MakeWindowOptional(pWin
))
676 others
= (InputClients
*) xalloc(sizeof(InputClients
));
679 if (!pWin
->optional
->inputMasks
&& !MakeInputMasks(pWin
))
681 bzero((char *)&others
->mask
[0], sizeof(Mask
) * EMASKSIZE
);
682 others
->mask
[mskidx
] = mask
;
683 others
->resource
= FakeClientID(client
->index
);
684 others
->next
= pWin
->optional
->inputMasks
->inputClients
;
685 pWin
->optional
->inputMasks
->inputClients
= others
;
686 if (!AddResource(others
->resource
, RT_INPUTCLIENT
, (pointer
) pWin
))
692 MakeInputMasks(WindowPtr pWin
)
694 struct _OtherInputMasks
*imasks
;
696 imasks
= (struct _OtherInputMasks
*)
697 xalloc(sizeof(struct _OtherInputMasks
));
700 bzero((char *)imasks
, sizeof(struct _OtherInputMasks
));
701 pWin
->optional
->inputMasks
= imasks
;
706 RecalculateDeviceDeliverableEvents(WindowPtr pWin
)
708 InputClientsPtr others
;
709 struct _OtherInputMasks
*inputMasks
; /* default: NULL */
710 WindowPtr pChild
, tmp
;
715 if ((inputMasks
= wOtherInputMasks(pChild
)) != 0) {
716 for (others
= inputMasks
->inputClients
; others
;
717 others
= others
->next
) {
718 for (i
= 0; i
< EMASKSIZE
; i
++)
719 inputMasks
->inputEvents
[i
] |= others
->mask
[i
];
721 for (i
= 0; i
< EMASKSIZE
; i
++)
722 inputMasks
->deliverableEvents
[i
] = inputMasks
->inputEvents
[i
];
723 for (tmp
= pChild
->parent
; tmp
; tmp
= tmp
->parent
)
724 if (wOtherInputMasks(tmp
))
725 for (i
= 0; i
< EMASKSIZE
; i
++)
726 inputMasks
->deliverableEvents
[i
] |=
727 (wOtherInputMasks(tmp
)->deliverableEvents
[i
]
729 dontPropagateMask
[i
] & PropagateMask
[i
]);
731 if (pChild
->firstChild
) {
732 pChild
= pChild
->firstChild
;
735 while (!pChild
->nextSib
&& (pChild
!= pWin
))
736 pChild
= pChild
->parent
;
739 pChild
= pChild
->nextSib
;
744 InputClientGone(WindowPtr pWin
, XID id
)
746 InputClientsPtr other
, prev
;
748 if (!wOtherInputMasks(pWin
))
751 for (other
= wOtherInputMasks(pWin
)->inputClients
; other
;
752 other
= other
->next
) {
753 if (other
->resource
== id
) {
755 prev
->next
= other
->next
;
757 } else if (!(other
->next
)) {
758 if (ShouldFreeInputMasks(pWin
, TRUE
)) {
759 wOtherInputMasks(pWin
)->inputClients
= other
->next
;
760 xfree(wOtherInputMasks(pWin
));
761 pWin
->optional
->inputMasks
= (OtherInputMasks
*) NULL
;
762 CheckWindowOptionalNeed(pWin
);
765 other
->resource
= FakeClientID(0);
766 if (!AddResource(other
->resource
, RT_INPUTCLIENT
,
771 wOtherInputMasks(pWin
)->inputClients
= other
->next
;
774 RecalculateDeviceDeliverableEvents(pWin
);
779 FatalError("client not on device event list");
783 SendEvent(ClientPtr client
, DeviceIntPtr d
, Window dest
, Bool propagate
,
784 xEvent
* ev
, Mask mask
, int count
)
787 WindowPtr effectiveFocus
= NullWindow
; /* only set if dest==InputFocus */
788 WindowPtr spriteWin
= GetSpriteWindow();
790 if (dest
== PointerWindow
)
792 else if (dest
== InputFocus
) {
793 WindowPtr inputFocus
;
796 inputFocus
= spriteWin
;
798 inputFocus
= d
->focus
->win
;
800 if (inputFocus
== FollowKeyboardWin
)
801 inputFocus
= inputInfo
.keyboard
->focus
->win
;
803 if (inputFocus
== NoneWin
)
806 /* If the input focus is PointerRootWin, send the event to where
807 * the pointer is if possible, then perhaps propogate up to root. */
808 if (inputFocus
== PointerRootWin
)
809 inputFocus
= GetCurrentRootWindow();
811 if (IsParent(inputFocus
, spriteWin
)) {
812 effectiveFocus
= inputFocus
;
815 effectiveFocus
= pWin
= inputFocus
;
817 dixLookupWindow(&pWin
, dest
, client
, DixUnknownAccess
);
820 if ((propagate
!= xFalse
) && (propagate
!= xTrue
)) {
821 client
->errorValue
= propagate
;
824 ev
->u
.u
.type
|= 0x80;
826 for (; pWin
; pWin
= pWin
->parent
) {
827 if (DeliverEventsToWindow(pWin
, ev
, count
, mask
, NullGrab
, d
->id
))
829 if (pWin
== effectiveFocus
)
831 if (wOtherInputMasks(pWin
))
832 mask
&= ~wOtherInputMasks(pWin
)->dontPropagateMask
[d
->id
];
837 (void)(DeliverEventsToWindow(pWin
, ev
, count
, mask
, NullGrab
, d
->id
));
842 SetButtonMapping(ClientPtr client
, DeviceIntPtr dev
, int nElts
, BYTE
* map
)
845 ButtonClassPtr b
= dev
->button
;
850 if (nElts
!= b
->numButtons
) {
851 client
->errorValue
= nElts
;
854 if (BadDeviceMap(&map
[0], nElts
, 1, 255, &client
->errorValue
))
856 for (i
= 0; i
< nElts
; i
++)
857 if ((b
->map
[i
+ 1] != map
[i
]) && BitIsOn(b
->down
, i
+ 1))
859 for (i
= 0; i
< nElts
; i
++)
860 b
->map
[i
+ 1] = map
[i
];
865 SetModifierMapping(ClientPtr client
, DeviceIntPtr dev
, int len
, int rlen
,
866 int numKeyPerModifier
, KeyCode
* inputMap
, KeyClassPtr
* k
)
875 if (len
!= ((numKeyPerModifier
<< 1) + rlen
))
878 inputMapLen
= 8 * numKeyPerModifier
;
881 * Now enforce the restriction that "all of the non-zero keycodes must be
882 * in the range specified by min-keycode and max-keycode in the
883 * connection setup (else a Value error)"
888 && (inputMap
[i
] < (*k
)->curKeySyms
.minKeyCode
889 || inputMap
[i
] > (*k
)->curKeySyms
.maxKeyCode
)) {
890 client
->errorValue
= inputMap
[i
];
891 return -1; /* BadValue collides with MappingFailed */
896 * Now enforce the restriction that none of the old or new
897 * modifier keys may be down while we change the mapping, and
898 * that the DDX layer likes the choice.
900 if (!AllModifierKeysAreUp(dev
, (*k
)->modifierKeyMap
,
901 (int)(*k
)->maxKeysPerModifier
, inputMap
,
902 (int)numKeyPerModifier
)
903 || !AllModifierKeysAreUp(dev
, inputMap
, (int)numKeyPerModifier
,
904 (*k
)->modifierKeyMap
,
905 (int)(*k
)->maxKeysPerModifier
)) {
908 for (i
= 0; i
< inputMapLen
; i
++) {
909 if (inputMap
[i
] && !LegalModifier(inputMap
[i
], dev
)) {
910 return MappingFailed
;
916 * Now build the keyboard's modifier bitmap from the
920 map
= (KeyCode
*) xalloc(inputMapLen
);
924 if ((*k
)->modifierKeyMap
)
925 xfree((*k
)->modifierKeyMap
);
927 (*k
)->modifierKeyMap
= map
;
928 memmove((char *)(*k
)->modifierKeyMap
, (char *)inputMap
, inputMapLen
);
930 (*k
)->modifierKeyMap
= NULL
;
932 (*k
)->maxKeysPerModifier
= numKeyPerModifier
;
933 for (i
= 0; i
< MAP_LENGTH
; i
++)
934 (*k
)->modifierMap
[i
] = 0;
935 for (i
= 0; i
< inputMapLen
; i
++)
937 (*k
)->modifierMap
[inputMap
[i
]]
938 |= (1 << (i
/ (*k
)->maxKeysPerModifier
));
941 return (MappingSuccess
);
945 SendDeviceMappingNotify(CARD8 request
,
946 KeyCode firstKeyCode
, CARD8 count
, DeviceIntPtr dev
)
949 deviceMappingNotify
*ev
= (deviceMappingNotify
*) & event
;
951 ev
->type
= DeviceMappingNotify
;
952 ev
->request
= request
;
953 ev
->deviceid
= dev
->id
;
954 ev
->time
= currentTime
.milliseconds
;
955 if (request
== MappingKeyboard
) {
956 ev
->firstKeyCode
= firstKeyCode
;
960 SendEventToAllWindows(dev
, DeviceMappingNotifyMask
, (xEvent
*) ev
, 1);
964 ChangeKeyMapping(ClientPtr client
,
968 KeyCode firstKeyCode
,
969 CARD8 keyCodes
, CARD8 keySymsPerKeyCode
, KeySym
* map
)
972 KeyClassPtr k
= dev
->key
;
977 if (len
!= (keyCodes
* keySymsPerKeyCode
))
980 if ((firstKeyCode
< k
->curKeySyms
.minKeyCode
) ||
981 (firstKeyCode
+ keyCodes
- 1 > k
->curKeySyms
.maxKeyCode
)) {
982 client
->errorValue
= firstKeyCode
;
985 if (keySymsPerKeyCode
== 0) {
986 client
->errorValue
= 0;
989 keysyms
.minKeyCode
= firstKeyCode
;
990 keysyms
.maxKeyCode
= firstKeyCode
+ keyCodes
- 1;
991 keysyms
.mapWidth
= keySymsPerKeyCode
;
993 if (!SetKeySymsMap(&k
->curKeySyms
, &keysyms
))
995 SendDeviceMappingNotify(MappingKeyboard
, firstKeyCode
, keyCodes
, dev
);
996 return client
->noClientException
;
1000 DeleteDeviceFromAnyExtEvents(WindowPtr pWin
, DeviceIntPtr dev
)
1004 /* Deactivate any grabs performed on this window, before making
1005 * any input focus changes.
1006 * Deactivating a device grab should cause focus events. */
1008 if (dev
->grab
&& (dev
->grab
->window
== pWin
))
1009 (*dev
->DeactivateGrab
) (dev
);
1011 /* If the focus window is a root window (ie. has no parent)
1012 * then don't delete the focus from it. */
1014 if (dev
->focus
&& (pWin
== dev
->focus
->win
) && (pWin
->parent
!= NullWindow
)) {
1015 int focusEventMode
= NotifyNormal
;
1017 /* If a grab is in progress, then alter the mode of focus events. */
1020 focusEventMode
= NotifyWhileGrabbed
;
1022 switch (dev
->focus
->revert
) {
1024 DoFocusEvents(dev
, pWin
, NoneWin
, focusEventMode
);
1025 dev
->focus
->win
= NoneWin
;
1026 dev
->focus
->traceGood
= 0;
1028 case RevertToParent
:
1031 parent
= parent
->parent
;
1032 dev
->focus
->traceGood
--;
1034 while (!parent
->realized
);
1035 DoFocusEvents(dev
, pWin
, parent
, focusEventMode
);
1036 dev
->focus
->win
= parent
;
1037 dev
->focus
->revert
= RevertToNone
;
1039 case RevertToPointerRoot
:
1040 DoFocusEvents(dev
, pWin
, PointerRootWin
, focusEventMode
);
1041 dev
->focus
->win
= PointerRootWin
;
1042 dev
->focus
->traceGood
= 0;
1044 case RevertToFollowKeyboard
:
1045 if (inputInfo
.keyboard
->focus
->win
) {
1046 DoFocusEvents(dev
, pWin
, inputInfo
.keyboard
->focus
->win
,
1048 dev
->focus
->win
= FollowKeyboardWin
;
1049 dev
->focus
->traceGood
= 0;
1051 DoFocusEvents(dev
, pWin
, NoneWin
, focusEventMode
);
1052 dev
->focus
->win
= NoneWin
;
1053 dev
->focus
->traceGood
= 0;
1060 if (dev
->valuator
->motionHintWindow
== pWin
)
1061 dev
->valuator
->motionHintWindow
= NullWindow
;
1065 DeleteWindowFromAnyExtEvents(WindowPtr pWin
, Bool freeResources
)
1070 struct _OtherInputMasks
*inputMasks
;
1072 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
1073 if (dev
== inputInfo
.pointer
|| dev
== inputInfo
.keyboard
)
1075 DeleteDeviceFromAnyExtEvents(pWin
, dev
);
1078 for (dev
= inputInfo
.off_devices
; dev
; dev
= dev
->next
)
1079 DeleteDeviceFromAnyExtEvents(pWin
, dev
);
1082 while ((inputMasks
= wOtherInputMasks(pWin
)) != 0) {
1083 ic
= inputMasks
->inputClients
;
1084 for (i
= 0; i
< EMASKSIZE
; i
++)
1085 inputMasks
->dontPropagateMask
[i
] = 0;
1086 FreeResource(ic
->resource
, RT_NONE
);
1091 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer
* pEvents
, Mask mask
)
1095 dev
= LookupDeviceIntRec(pEvents
->deviceid
& DEVICE_BITS
);
1099 if (pEvents
->type
== DeviceMotionNotify
) {
1100 if (mask
& DevicePointerMotionHintMask
) {
1101 if (WID(dev
->valuator
->motionHintWindow
) == pEvents
->event
) {
1102 return 1; /* don't send, but pretend we did */
1104 pEvents
->detail
= NotifyHint
;
1106 pEvents
->detail
= NotifyNormal
;
1113 CheckDeviceGrabAndHintWindow(WindowPtr pWin
, int type
,
1114 deviceKeyButtonPointer
* xE
, GrabPtr grab
,
1115 ClientPtr client
, Mask deliveryMask
)
1119 dev
= LookupDeviceIntRec(xE
->deviceid
& DEVICE_BITS
);
1123 if (type
== DeviceMotionNotify
)
1124 dev
->valuator
->motionHintWindow
= pWin
;
1125 else if ((type
== DeviceButtonPress
) && (!grab
) &&
1126 (deliveryMask
& DeviceButtonGrabMask
)) {
1129 tempGrab
.device
= dev
;
1130 tempGrab
.resource
= client
->clientAsMask
;
1131 tempGrab
.window
= pWin
;
1132 tempGrab
.ownerEvents
=
1133 (deliveryMask
& DeviceOwnerGrabButtonMask
) ? TRUE
: FALSE
;
1134 tempGrab
.eventMask
= deliveryMask
;
1135 tempGrab
.keyboardMode
= GrabModeAsync
;
1136 tempGrab
.pointerMode
= GrabModeAsync
;
1137 tempGrab
.confineTo
= NullWindow
;
1138 tempGrab
.cursor
= NullCursor
;
1139 (*dev
->ActivateGrab
) (dev
, &tempGrab
, currentTime
, TRUE
);
1144 DeviceEventMaskForClient(DeviceIntPtr dev
, WindowPtr pWin
, ClientPtr client
)
1146 InputClientsPtr other
;
1148 if (!wOtherInputMasks(pWin
))
1150 for (other
= wOtherInputMasks(pWin
)->inputClients
; other
;
1151 other
= other
->next
) {
1152 if (SameClient(other
, client
))
1153 return other
->mask
[dev
->id
];
1159 MaybeStopDeviceHint(DeviceIntPtr dev
, ClientPtr client
)
1162 GrabPtr grab
= dev
->grab
;
1164 pWin
= dev
->valuator
->motionHintWindow
;
1166 if ((grab
&& SameClient(grab
, client
) &&
1167 ((grab
->eventMask
& DevicePointerMotionHintMask
) ||
1168 (grab
->ownerEvents
&&
1169 (DeviceEventMaskForClient(dev
, pWin
, client
) &
1170 DevicePointerMotionHintMask
)))) ||
1172 (DeviceEventMaskForClient(dev
, pWin
, client
) &
1173 DevicePointerMotionHintMask
)))
1174 dev
->valuator
->motionHintWindow
= NullWindow
;
1178 DeviceEventSuppressForWindow(WindowPtr pWin
, ClientPtr client
, Mask mask
,
1181 struct _OtherInputMasks
*inputMasks
= wOtherInputMasks(pWin
);
1183 if (mask
& ~PropagateMask
[maskndx
]) {
1184 client
->errorValue
= mask
;
1190 inputMasks
->dontPropagateMask
[maskndx
] = mask
;
1193 AddExtensionClient(pWin
, client
, 0, 0);
1194 inputMasks
= wOtherInputMasks(pWin
);
1195 inputMasks
->dontPropagateMask
[maskndx
] = mask
;
1197 RecalculateDeviceDeliverableEvents(pWin
);
1198 if (ShouldFreeInputMasks(pWin
, FALSE
))
1199 FreeResource(inputMasks
->inputClients
->resource
, RT_NONE
);
1204 ShouldFreeInputMasks(WindowPtr pWin
, Bool ignoreSelectedEvents
)
1207 Mask allInputEventMasks
= 0;
1208 struct _OtherInputMasks
*inputMasks
= wOtherInputMasks(pWin
);
1210 for (i
= 0; i
< EMASKSIZE
; i
++)
1211 allInputEventMasks
|= inputMasks
->dontPropagateMask
[i
];
1212 if (!ignoreSelectedEvents
)
1213 for (i
= 0; i
< EMASKSIZE
; i
++)
1214 allInputEventMasks
|= inputMasks
->inputEvents
[i
];
1215 if (allInputEventMasks
== 0)
1221 /***********************************************************************
1223 * Walk through the window tree, finding all clients that want to know
1229 FindInterestedChildren(DeviceIntPtr dev
, WindowPtr p1
, Mask mask
,
1230 xEvent
* ev
, int count
)
1235 p2
= p1
->firstChild
;
1236 (void)DeliverEventsToWindow(p1
, ev
, count
, mask
, NullGrab
, dev
->id
);
1237 FindInterestedChildren(dev
, p2
, mask
, ev
, count
);
1242 /***********************************************************************
1244 * Send an event to interested clients in all windows on all screens.
1249 SendEventToAllWindows(DeviceIntPtr dev
, Mask mask
, xEvent
* ev
, int count
)
1254 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1255 pWin
= WindowTable
[i
];
1256 (void)DeliverEventsToWindow(pWin
, ev
, count
, mask
, NullGrab
, dev
->id
);
1257 p1
= pWin
->firstChild
;
1258 FindInterestedChildren(dev
, p1
, mask
, ev
, count
);