exevents.c revision 05b261ec
1/************************************************************
2
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27			All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Hewlett-Packard not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45********************************************************/
46
47/********************************************************************
48 *
49 *  Routines to register and initialize extension input devices.
50 *  This also contains ProcessOtherEvent, the routine called from DDX
51 *  to route extension events.
52 *
53 */
54
55#define	 NEED_EVENTS
56#ifdef HAVE_DIX_CONFIG_H
57#include <dix-config.h>
58#endif
59
60#include <X11/X.h>
61#include <X11/Xproto.h>
62#include <X11/extensions/XI.h>
63#include <X11/extensions/XIproto.h>
64#include "inputstr.h"
65#include "windowstr.h"
66#include "miscstruct.h"
67#include "region.h"
68#include "exevents.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"
75
76#ifdef XKB
77#include "xkbsrv.h"
78#endif
79
80#define WID(w) ((w) ? ((w)->drawable.id) : 0)
81#define AllModifiersMask ( \
82	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
83	Mod3Mask | Mod4Mask | Mod5Mask )
84#define AllButtonsMask ( \
85	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
86#define Motion_Filter(class) (DevicePointerMotionMask | \
87			      (class)->state | (class)->motionMask)
88
89static Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
90				 Bool	/* ignoreSelectedEvents */
91    );
92static Bool MakeInputMasks(WindowPtr	/* pWin */
93    );
94
95/**************************************************************************
96 *
97 * Procedures for extension device event routing.
98 *
99 */
100
101void
102RegisterOtherDevice(DeviceIntPtr device)
103{
104    device->public.processInputProc = ProcessOtherEvent;
105    device->public.realInputProc = ProcessOtherEvent;
106    (device)->ActivateGrab = ActivateKeyboardGrab;
107    (device)->DeactivateGrab = DeactivateKeyboardGrab;
108}
109
110 /*ARGSUSED*/ void
111ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
112{
113    BYTE *kptr;
114    int i;
115    CARD16 modifiers;
116    CARD16 mask;
117    GrabPtr grab = other->grab;
118    Bool deactivateDeviceGrab = FALSE;
119    int key = 0, bit = 0, rootX, rootY;
120    ButtonClassPtr b = other->button;
121    KeyClassPtr k = other->key;
122    ValuatorClassPtr v = other->valuator;
123    deviceValuator *xV = (deviceValuator *) xE;
124
125    if (xE->u.u.type != DeviceValuator) {
126        /* Other types already have root{X,Y} filled in. */
127        if (xE->u.u.type == DeviceKeyPress ||
128            xE->u.u.type == DeviceKeyRelease) {
129	    GetSpritePosition(&rootX, &rootY);
130	    xE->u.keyButtonPointer.rootX = rootX;
131	    xE->u.keyButtonPointer.rootY = rootY;
132        }
133
134	key = xE->u.u.detail;
135	NoticeEventTime(xE);
136	xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
137	    inputInfo.pointer->button->state;
138	bit = 1 << (key & 7);
139    }
140    if (DeviceEventCallback) {
141	DeviceEventInfoRec eventinfo;
142
143	eventinfo.events = (xEventPtr) xE;
144	eventinfo.count = count;
145	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
146    }
147    for (i = 1; i < count; i++)
148	if ((++xV)->type == DeviceValuator) {
149	    int first = xV->first_valuator;
150	    int *axisvals;
151
152	    if (xV->num_valuators
153		&& (!v
154		    || (xV->num_valuators
155			&& (first + xV->num_valuators > v->numAxes))))
156		FatalError("Bad valuators reported for device %s\n",
157			   other->name);
158	    xV->device_state = 0;
159	    if (k)
160		xV->device_state |= k->state;
161	    if (b)
162		xV->device_state |= b->state;
163	    if (v && v->axisVal) {
164		axisvals = v->axisVal;
165		switch (xV->num_valuators) {
166		case 6:
167		    *(axisvals + first + 5) = xV->valuator5;
168		case 5:
169		    *(axisvals + first + 4) = xV->valuator4;
170		case 4:
171		    *(axisvals + first + 3) = xV->valuator3;
172		case 3:
173		    *(axisvals + first + 2) = xV->valuator2;
174		case 2:
175		    *(axisvals + first + 1) = xV->valuator1;
176		case 1:
177		    *(axisvals + first) = xV->valuator0;
178		case 0:
179		default:
180		    break;
181		}
182	    }
183	}
184
185    if (xE->u.u.type == DeviceKeyPress) {
186        if (!k)
187            return;
188
189	modifiers = k->modifierMap[key];
190	kptr = &k->down[key >> 3];
191	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
192	    if (!modifiers) {
193		xE->u.u.type = DeviceKeyRelease;
194		ProcessOtherEvent(xE, other, count);
195		xE->u.u.type = DeviceKeyPress;
196		/* release can have side effects, don't fall through */
197		ProcessOtherEvent(xE, other, count);
198	    }
199	    return;
200	}
201	if (other->valuator)
202	    other->valuator->motionHintWindow = NullWindow;
203	*kptr |= bit;
204	k->prev_state = k->state;
205	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
206	    if (mask & modifiers) {
207		/* This key affects modifier "i" */
208		k->modifierKeyCount[i]++;
209		k->state |= mask;
210		modifiers &= ~mask;
211	    }
212	}
213	if (!grab && CheckDeviceGrabs(other, xE, 0, count)) {
214	    other->activatingKey = key;
215	    return;
216	}
217    } else if (xE->u.u.type == DeviceKeyRelease) {
218        if (!k)
219            return;
220
221	kptr = &k->down[key >> 3];
222	if (!(*kptr & bit))	/* guard against duplicates */
223	    return;
224	modifiers = k->modifierMap[key];
225	if (other->valuator)
226	    other->valuator->motionHintWindow = NullWindow;
227	*kptr &= ~bit;
228	k->prev_state = k->state;
229	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
230	    if (mask & modifiers) {
231		/* This key affects modifier "i" */
232		if (--k->modifierKeyCount[i] <= 0) {
233		    k->modifierKeyCount[i] = 0;
234		    k->state &= ~mask;
235		}
236		modifiers &= ~mask;
237	    }
238	}
239
240	if (other->fromPassiveGrab && (key == other->activatingKey))
241	    deactivateDeviceGrab = TRUE;
242    } else if (xE->u.u.type == DeviceButtonPress) {
243        if (!b)
244            return;
245
246	kptr = &b->down[key >> 3];
247	*kptr |= bit;
248	if (other->valuator)
249	    other->valuator->motionHintWindow = NullWindow;
250	b->buttonsDown++;
251	b->motionMask = DeviceButtonMotionMask;
252	xE->u.u.detail = key;
253	if (xE->u.u.detail == 0)
254	    return;
255	if (xE->u.u.detail <= 5)
256	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
257	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
258	if (!grab)
259	    if (CheckDeviceGrabs(other, xE, 0, count))
260                /* if a passive grab was activated, the event has been sent
261                 * already */
262                return;
263
264    } else if (xE->u.u.type == DeviceButtonRelease) {
265        if (!b)
266            return;
267
268	kptr = &b->down[key >> 3];
269	*kptr &= ~bit;
270	if (other->valuator)
271	    other->valuator->motionHintWindow = NullWindow;
272        if (b->buttonsDown >= 1 && !--b->buttonsDown)
273	    b->motionMask = 0;
274	xE->u.u.detail = key;
275	if (xE->u.u.detail == 0)
276	    return;
277	if (xE->u.u.detail <= 5)
278	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
279	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
280	if (!b->state && other->fromPassiveGrab)
281	    deactivateDeviceGrab = TRUE;
282    } else if (xE->u.u.type == ProximityIn)
283	other->valuator->mode &= ~OutOfProximity;
284    else if (xE->u.u.type == ProximityOut)
285	other->valuator->mode |= OutOfProximity;
286
287    if (grab)
288	DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
289    else if (other->focus)
290	DeliverFocusedEvent(other, xE, GetSpriteWindow(), count);
291    else
292	DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow,
293			    other, count);
294
295    if (deactivateDeviceGrab == TRUE)
296	(*other->DeactivateGrab) (other);
297}
298
299_X_EXPORT int
300InitProximityClassDeviceStruct(DeviceIntPtr dev)
301{
302    ProximityClassPtr proxc;
303
304    proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec));
305    if (!proxc)
306	return FALSE;
307    dev->proximity = proxc;
308    return TRUE;
309}
310
311_X_EXPORT void
312InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
313		       int resolution, int min_res, int max_res)
314{
315    AxisInfoPtr ax;
316
317    if (!dev || !dev->valuator)
318        return;
319
320    ax = dev->valuator->axes + axnum;
321
322    ax->min_value = minval;
323    ax->max_value = maxval;
324    ax->resolution = resolution;
325    ax->min_resolution = min_res;
326    ax->max_resolution = max_res;
327}
328
329static void
330FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
331		     ButtonClassPtr b, ValuatorClassPtr v, int first)
332{
333    ev->type = DeviceStateNotify;
334    ev->deviceid = dev->id;
335    ev->time = currentTime.milliseconds;
336    ev->classes_reported = 0;
337    ev->num_keys = 0;
338    ev->num_buttons = 0;
339    ev->num_valuators = 0;
340
341    if (b) {
342	ev->classes_reported |= (1 << ButtonClass);
343	ev->num_buttons = b->numButtons;
344	memmove((char *)&ev->buttons[0], (char *)b->down, 4);
345    } else if (k) {
346	ev->classes_reported |= (1 << KeyClass);
347	ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
348	memmove((char *)&ev->keys[0], (char *)k->down, 4);
349    }
350    if (v) {
351	int nval = v->numAxes - first;
352
353	ev->classes_reported |= (1 << ValuatorClass);
354	ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
355	ev->num_valuators = nval < 3 ? nval : 3;
356	switch (ev->num_valuators) {
357	case 3:
358	    ev->valuator2 = v->axisVal[first + 2];
359	case 2:
360	    ev->valuator1 = v->axisVal[first + 1];
361	case 1:
362	    ev->valuator0 = v->axisVal[first];
363	    break;
364	}
365    }
366}
367
368static void
369FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
370		  int first)
371{
372    int nval = v->numAxes - first;
373
374    ev->type = DeviceValuator;
375    ev->deviceid = dev->id;
376    ev->num_valuators = nval < 3 ? nval : 3;
377    ev->first_valuator = first;
378    switch (ev->num_valuators) {
379    case 3:
380	ev->valuator2 = v->axisVal[first + 2];
381    case 2:
382	ev->valuator1 = v->axisVal[first + 1];
383    case 1:
384	ev->valuator0 = v->axisVal[first];
385	break;
386    }
387    first += ev->num_valuators;
388}
389
390void
391DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
392		 WindowPtr pWin)
393{
394    deviceFocus event;
395
396    if (type == FocusIn)
397	type = DeviceFocusIn;
398    else
399	type = DeviceFocusOut;
400
401    event.deviceid = dev->id;
402    event.mode = mode;
403    event.type = type;
404    event.detail = detail;
405    event.window = pWin->drawable.id;
406    event.time = currentTime.milliseconds;
407
408    (void)DeliverEventsToWindow(pWin, (xEvent *) & event, 1,
409				DeviceFocusChangeMask, NullGrab, dev->id);
410
411    if ((type == DeviceFocusIn) &&
412	(wOtherInputMasks(pWin)) &&
413	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
414    {
415	int evcount = 1;
416	deviceStateNotify *ev, *sev;
417	deviceKeyStateNotify *kev;
418	deviceButtonStateNotify *bev;
419
420	KeyClassPtr k;
421	ButtonClassPtr b;
422	ValuatorClassPtr v;
423	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
424
425	if ((b = dev->button) != NULL) {
426	    nbuttons = b->numButtons;
427	    if (nbuttons > 32)
428		evcount++;
429	}
430	if ((k = dev->key) != NULL) {
431	    nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
432	    if (nkeys > 32)
433		evcount++;
434	    if (nbuttons > 0) {
435		evcount++;
436	    }
437	}
438	if ((v = dev->valuator) != NULL) {
439	    nval = v->numAxes;
440
441	    if (nval > 3)
442		evcount++;
443	    if (nval > 6) {
444		if (!(k && b))
445		    evcount++;
446		if (nval > 9)
447		    evcount += ((nval - 7) / 3);
448	    }
449	}
450
451	sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent));
452	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
453
454	if (b != NULL) {
455	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
456	    first += 3;
457	    nval -= 3;
458	    if (nbuttons > 32) {
459		(ev - 1)->deviceid |= MORE_EVENTS;
460		bev = (deviceButtonStateNotify *) ev++;
461		bev->type = DeviceButtonStateNotify;
462		bev->deviceid = dev->id;
463		memmove((char *)&bev->buttons[0], (char *)&b->down[4], 28);
464	    }
465	    if (nval > 0) {
466		(ev - 1)->deviceid |= MORE_EVENTS;
467		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
468		first += 3;
469		nval -= 3;
470	    }
471	}
472
473	if (k != NULL) {
474	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
475	    first += 3;
476	    nval -= 3;
477	    if (nkeys > 32) {
478		(ev - 1)->deviceid |= MORE_EVENTS;
479		kev = (deviceKeyStateNotify *) ev++;
480		kev->type = DeviceKeyStateNotify;
481		kev->deviceid = dev->id;
482		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
483	    }
484	    if (nval > 0) {
485		(ev - 1)->deviceid |= MORE_EVENTS;
486		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
487		first += 3;
488		nval -= 3;
489	    }
490	}
491
492	while (nval > 0) {
493	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
494	    first += 3;
495	    nval -= 3;
496	    if (nval > 0) {
497		(ev - 1)->deviceid |= MORE_EVENTS;
498		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
499		first += 3;
500		nval -= 3;
501	    }
502	}
503
504	(void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount,
505				    DeviceStateNotifyMask, NullGrab, dev->id);
506	xfree(sev);
507    }
508}
509
510int
511GrabButton(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
512	   BYTE other_devices_mode, CARD16 modifiers,
513	   DeviceIntPtr modifier_device, CARD8 button, Window grabWindow,
514	   BOOL ownerEvents, Cursor rcursor, Window rconfineTo, Mask eventMask)
515{
516    WindowPtr pWin, confineTo;
517    CursorPtr cursor;
518    GrabPtr grab;
519    int rc;
520
521    if ((this_device_mode != GrabModeSync) &&
522	(this_device_mode != GrabModeAsync)) {
523	client->errorValue = this_device_mode;
524	return BadValue;
525    }
526    if ((other_devices_mode != GrabModeSync) &&
527	(other_devices_mode != GrabModeAsync)) {
528	client->errorValue = other_devices_mode;
529	return BadValue;
530    }
531    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
532	client->errorValue = modifiers;
533	return BadValue;
534    }
535    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
536	client->errorValue = ownerEvents;
537	return BadValue;
538    }
539    rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess);
540    if (rc != Success)
541	return rc;
542    if (rconfineTo == None)
543	confineTo = NullWindow;
544    else {
545	rc = dixLookupWindow(&confineTo, rconfineTo, client, DixUnknownAccess);
546	if (rc != Success)
547	    return rc;
548    }
549    if (rcursor == None)
550	cursor = NullCursor;
551    else {
552	cursor = (CursorPtr) LookupIDByType(rcursor, RT_CURSOR);
553	if (!cursor) {
554	    client->errorValue = rcursor;
555	    return BadCursor;
556	}
557    }
558
559    grab = CreateGrab(client->index, dev, pWin, eventMask,
560		      (Bool) ownerEvents, (Bool) this_device_mode,
561		      (Bool) other_devices_mode, modifier_device, modifiers,
562		      DeviceButtonPress, button, confineTo, cursor);
563    if (!grab)
564	return BadAlloc;
565    return AddPassiveGrabToList(grab);
566}
567
568int
569GrabKey(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
570	BYTE other_devices_mode, CARD16 modifiers,
571	DeviceIntPtr modifier_device, CARD8 key, Window grabWindow,
572	BOOL ownerEvents, Mask mask)
573{
574    WindowPtr pWin;
575    GrabPtr grab;
576    KeyClassPtr k = dev->key;
577    int rc;
578
579    if (k == NULL)
580	return BadMatch;
581    if ((other_devices_mode != GrabModeSync) &&
582	(other_devices_mode != GrabModeAsync)) {
583	client->errorValue = other_devices_mode;
584	return BadValue;
585    }
586    if ((this_device_mode != GrabModeSync) &&
587	(this_device_mode != GrabModeAsync)) {
588	client->errorValue = this_device_mode;
589	return BadValue;
590    }
591    if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode))
592	&& (key != AnyKey)) {
593	client->errorValue = key;
594	return BadValue;
595    }
596    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
597	client->errorValue = modifiers;
598	return BadValue;
599    }
600    if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) {
601	client->errorValue = ownerEvents;
602	return BadValue;
603    }
604    rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess);
605    if (rc != Success)
606	return rc;
607
608    grab = CreateGrab(client->index, dev, pWin,
609		      mask, ownerEvents, this_device_mode, other_devices_mode,
610		      modifier_device, modifiers, DeviceKeyPress, key,
611		      NullWindow, NullCursor);
612    if (!grab)
613	return BadAlloc;
614    return AddPassiveGrabToList(grab);
615}
616
617int
618SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
619		Mask mask, Mask exclusivemasks, Mask validmasks)
620{
621    int mskidx = dev->id;
622    int i, ret;
623    Mask check;
624    InputClientsPtr others;
625
626    if (mask & ~validmasks) {
627	client->errorValue = mask;
628	return BadValue;
629    }
630    check = (mask & exclusivemasks);
631    if (wOtherInputMasks(pWin)) {
632	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
633									 * clients to select on any of the
634									 * events for maskcheck. However,
635									 * it is OK, for some client to
636									 * continue selecting on one of those
637									 * events.  */
638	    for (others = wOtherInputMasks(pWin)->inputClients; others;
639		 others = others->next) {
640		if (!SameClient(others, client) && (check &
641						    others->mask[mskidx]))
642		    return BadAccess;
643	    }
644	}
645	for (others = wOtherInputMasks(pWin)->inputClients; others;
646	     others = others->next) {
647	    if (SameClient(others, client)) {
648		check = others->mask[mskidx];
649		others->mask[mskidx] = mask;
650		if (mask == 0) {
651		    for (i = 0; i < EMASKSIZE; i++)
652			if (i != mskidx && others->mask[i] != 0)
653			    break;
654		    if (i == EMASKSIZE) {
655			RecalculateDeviceDeliverableEvents(pWin);
656			if (ShouldFreeInputMasks(pWin, FALSE))
657			    FreeResource(others->resource, RT_NONE);
658			return Success;
659		    }
660		}
661		goto maskSet;
662	    }
663	}
664    }
665    check = 0;
666    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
667	return ret;
668  maskSet:
669    if (dev->valuator)
670	if ((dev->valuator->motionHintWindow == pWin) &&
671	    (mask & DevicePointerMotionHintMask) &&
672	    !(check & DevicePointerMotionHintMask) && !dev->grab)
673	    dev->valuator->motionHintWindow = NullWindow;
674    RecalculateDeviceDeliverableEvents(pWin);
675    return Success;
676}
677
678int
679AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
680{
681    InputClientsPtr others;
682
683    if (!pWin->optional && !MakeWindowOptional(pWin))
684	return BadAlloc;
685    others = (InputClients *) xalloc(sizeof(InputClients));
686    if (!others)
687	return BadAlloc;
688    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
689	return BadAlloc;
690    bzero((char *)&others->mask[0], sizeof(Mask) * EMASKSIZE);
691    others->mask[mskidx] = mask;
692    others->resource = FakeClientID(client->index);
693    others->next = pWin->optional->inputMasks->inputClients;
694    pWin->optional->inputMasks->inputClients = others;
695    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
696	return BadAlloc;
697    return Success;
698}
699
700static Bool
701MakeInputMasks(WindowPtr pWin)
702{
703    struct _OtherInputMasks *imasks;
704
705    imasks = (struct _OtherInputMasks *)
706	xalloc(sizeof(struct _OtherInputMasks));
707    if (!imasks)
708	return FALSE;
709    bzero((char *)imasks, sizeof(struct _OtherInputMasks));
710    pWin->optional->inputMasks = imasks;
711    return TRUE;
712}
713
714void
715RecalculateDeviceDeliverableEvents(WindowPtr pWin)
716{
717    InputClientsPtr others;
718    struct _OtherInputMasks *inputMasks;	/* default: NULL */
719    WindowPtr pChild, tmp;
720    int i;
721
722    pChild = pWin;
723    while (1) {
724	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
725	    for (others = inputMasks->inputClients; others;
726		 others = others->next) {
727		for (i = 0; i < EMASKSIZE; i++)
728		    inputMasks->inputEvents[i] |= others->mask[i];
729	    }
730	    for (i = 0; i < EMASKSIZE; i++)
731		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
732	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
733		if (wOtherInputMasks(tmp))
734		    for (i = 0; i < EMASKSIZE; i++)
735			inputMasks->deliverableEvents[i] |=
736			    (wOtherInputMasks(tmp)->deliverableEvents[i]
737			     & ~inputMasks->
738			     dontPropagateMask[i] & PropagateMask[i]);
739	}
740	if (pChild->firstChild) {
741	    pChild = pChild->firstChild;
742	    continue;
743	}
744	while (!pChild->nextSib && (pChild != pWin))
745	    pChild = pChild->parent;
746	if (pChild == pWin)
747	    break;
748	pChild = pChild->nextSib;
749    }
750}
751
752int
753InputClientGone(WindowPtr pWin, XID id)
754{
755    InputClientsPtr other, prev;
756
757    if (!wOtherInputMasks(pWin))
758	return (Success);
759    prev = 0;
760    for (other = wOtherInputMasks(pWin)->inputClients; other;
761	 other = other->next) {
762	if (other->resource == id) {
763	    if (prev) {
764		prev->next = other->next;
765		xfree(other);
766	    } else if (!(other->next)) {
767		if (ShouldFreeInputMasks(pWin, TRUE)) {
768		    wOtherInputMasks(pWin)->inputClients = other->next;
769		    xfree(wOtherInputMasks(pWin));
770		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
771		    CheckWindowOptionalNeed(pWin);
772		    xfree(other);
773		} else {
774		    other->resource = FakeClientID(0);
775		    if (!AddResource(other->resource, RT_INPUTCLIENT,
776				     (pointer) pWin))
777			return BadAlloc;
778		}
779	    } else {
780		wOtherInputMasks(pWin)->inputClients = other->next;
781		xfree(other);
782	    }
783	    RecalculateDeviceDeliverableEvents(pWin);
784	    return (Success);
785	}
786	prev = other;
787    }
788    FatalError("client not on device event list");
789}
790
791int
792SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
793	  xEvent * ev, Mask mask, int count)
794{
795    WindowPtr pWin;
796    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
797    WindowPtr spriteWin = GetSpriteWindow();
798
799    if (dest == PointerWindow)
800	pWin = spriteWin;
801    else if (dest == InputFocus) {
802	WindowPtr inputFocus;
803
804	if (!d->focus)
805	    inputFocus = spriteWin;
806	else
807	    inputFocus = d->focus->win;
808
809	if (inputFocus == FollowKeyboardWin)
810	    inputFocus = inputInfo.keyboard->focus->win;
811
812	if (inputFocus == NoneWin)
813	    return Success;
814
815	/* If the input focus is PointerRootWin, send the event to where
816	 * the pointer is if possible, then perhaps propogate up to root. */
817	if (inputFocus == PointerRootWin)
818	    inputFocus = GetCurrentRootWindow();
819
820	if (IsParent(inputFocus, spriteWin)) {
821	    effectiveFocus = inputFocus;
822	    pWin = spriteWin;
823	} else
824	    effectiveFocus = pWin = inputFocus;
825    } else
826	dixLookupWindow(&pWin, dest, client, DixUnknownAccess);
827    if (!pWin)
828	return BadWindow;
829    if ((propagate != xFalse) && (propagate != xTrue)) {
830	client->errorValue = propagate;
831	return BadValue;
832    }
833    ev->u.u.type |= 0x80;
834    if (propagate) {
835	for (; pWin; pWin = pWin->parent) {
836	    if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id))
837		return Success;
838	    if (pWin == effectiveFocus)
839		return Success;
840	    if (wOtherInputMasks(pWin))
841		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
842	    if (!mask)
843		break;
844	}
845    } else
846	(void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id));
847    return Success;
848}
849
850int
851SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
852{
853    int i;
854    ButtonClassPtr b = dev->button;
855
856    if (b == NULL)
857	return BadMatch;
858
859    if (nElts != b->numButtons) {
860	client->errorValue = nElts;
861	return BadValue;
862    }
863    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
864	return BadValue;
865    for (i = 0; i < nElts; i++)
866	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
867	    return MappingBusy;
868    for (i = 0; i < nElts; i++)
869	b->map[i + 1] = map[i];
870    return Success;
871}
872
873int
874SetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen,
875		   int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k)
876{
877    KeyCode *map = NULL;
878    int inputMapLen;
879    int i;
880
881    *k = dev->key;
882    if (*k == NULL)
883	return BadMatch;
884    if (len != ((numKeyPerModifier << 1) + rlen))
885	return BadLength;
886
887    inputMapLen = 8 * numKeyPerModifier;
888
889    /*
890     *  Now enforce the restriction that "all of the non-zero keycodes must be
891     *  in the range specified by min-keycode and max-keycode in the
892     *  connection setup (else a Value error)"
893     */
894    i = inputMapLen;
895    while (i--) {
896	if (inputMap[i]
897	    && (inputMap[i] < (*k)->curKeySyms.minKeyCode
898		|| inputMap[i] > (*k)->curKeySyms.maxKeyCode)) {
899	    client->errorValue = inputMap[i];
900	    return -1;	/* BadValue collides with MappingFailed */
901	}
902    }
903
904    /*
905     *  Now enforce the restriction that none of the old or new
906     *  modifier keys may be down while we change the mapping,  and
907     *  that the DDX layer likes the choice.
908     */
909    if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap,
910			      (int)(*k)->maxKeysPerModifier, inputMap,
911			      (int)numKeyPerModifier)
912	|| !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier,
913				 (*k)->modifierKeyMap,
914				 (int)(*k)->maxKeysPerModifier)) {
915	return MappingBusy;
916    } else {
917	for (i = 0; i < inputMapLen; i++) {
918	    if (inputMap[i] && !LegalModifier(inputMap[i], dev)) {
919		return MappingFailed;
920	    }
921	}
922    }
923
924    /*
925     *  Now build the keyboard's modifier bitmap from the
926     *  list of keycodes.
927     */
928    if (inputMapLen) {
929	map = (KeyCode *) xalloc(inputMapLen);
930	if (!map)
931	    return BadAlloc;
932    }
933    if ((*k)->modifierKeyMap)
934	xfree((*k)->modifierKeyMap);
935    if (inputMapLen) {
936	(*k)->modifierKeyMap = map;
937	memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen);
938    } else
939	(*k)->modifierKeyMap = NULL;
940
941    (*k)->maxKeysPerModifier = numKeyPerModifier;
942    for (i = 0; i < MAP_LENGTH; i++)
943	(*k)->modifierMap[i] = 0;
944    for (i = 0; i < inputMapLen; i++)
945	if (inputMap[i]) {
946	    (*k)->modifierMap[inputMap[i]]
947		|= (1 << (i / (*k)->maxKeysPerModifier));
948	}
949
950    return (MappingSuccess);
951}
952
953void
954SendDeviceMappingNotify(ClientPtr client, CARD8 request,
955			KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev)
956{
957    xEvent event;
958    deviceMappingNotify *ev = (deviceMappingNotify *) & event;
959
960    ev->type = DeviceMappingNotify;
961    ev->request = request;
962    ev->deviceid = dev->id;
963    ev->time = currentTime.milliseconds;
964    if (request == MappingKeyboard) {
965	ev->firstKeyCode = firstKeyCode;
966	ev->count = count;
967    }
968
969#ifdef XKB
970    if (request == MappingKeyboard || request == MappingModifier)
971        XkbApplyMappingChange(dev, request, firstKeyCode, count, client);
972#endif
973
974    SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1);
975}
976
977int
978ChangeKeyMapping(ClientPtr client,
979		 DeviceIntPtr dev,
980		 unsigned len,
981		 int type,
982		 KeyCode firstKeyCode,
983		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
984{
985    KeySymsRec keysyms;
986    KeyClassPtr k = dev->key;
987
988    if (k == NULL)
989	return (BadMatch);
990
991    if (len != (keyCodes * keySymsPerKeyCode))
992	return BadLength;
993
994    if ((firstKeyCode < k->curKeySyms.minKeyCode) ||
995	(firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) {
996	client->errorValue = firstKeyCode;
997	return BadValue;
998    }
999    if (keySymsPerKeyCode == 0) {
1000	client->errorValue = 0;
1001	return BadValue;
1002    }
1003    keysyms.minKeyCode = firstKeyCode;
1004    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1005    keysyms.mapWidth = keySymsPerKeyCode;
1006    keysyms.map = map;
1007    if (!SetKeySymsMap(&k->curKeySyms, &keysyms))
1008	return BadAlloc;
1009    SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev);
1010    return client->noClientException;
1011}
1012
1013static void
1014DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1015{
1016    WindowPtr parent;
1017
1018    /* Deactivate any grabs performed on this window, before making
1019     * any input focus changes.
1020     * Deactivating a device grab should cause focus events. */
1021
1022    if (dev->grab && (dev->grab->window == pWin))
1023	(*dev->DeactivateGrab) (dev);
1024
1025    /* If the focus window is a root window (ie. has no parent)
1026     * then don't delete the focus from it. */
1027
1028    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1029	int focusEventMode = NotifyNormal;
1030
1031	/* If a grab is in progress, then alter the mode of focus events. */
1032
1033	if (dev->grab)
1034	    focusEventMode = NotifyWhileGrabbed;
1035
1036	switch (dev->focus->revert) {
1037	case RevertToNone:
1038	    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1039	    dev->focus->win = NoneWin;
1040	    dev->focus->traceGood = 0;
1041	    break;
1042	case RevertToParent:
1043	    parent = pWin;
1044	    do {
1045		parent = parent->parent;
1046		dev->focus->traceGood--;
1047	    }
1048	    while (!parent->realized);
1049	    DoFocusEvents(dev, pWin, parent, focusEventMode);
1050	    dev->focus->win = parent;
1051	    dev->focus->revert = RevertToNone;
1052	    break;
1053	case RevertToPointerRoot:
1054	    DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1055	    dev->focus->win = PointerRootWin;
1056	    dev->focus->traceGood = 0;
1057	    break;
1058	case RevertToFollowKeyboard:
1059	    if (inputInfo.keyboard->focus->win) {
1060		DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win,
1061			      focusEventMode);
1062		dev->focus->win = FollowKeyboardWin;
1063		dev->focus->traceGood = 0;
1064	    } else {
1065		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1066		dev->focus->win = NoneWin;
1067		dev->focus->traceGood = 0;
1068	    }
1069	    break;
1070	}
1071    }
1072
1073    if (dev->valuator)
1074	if (dev->valuator->motionHintWindow == pWin)
1075	    dev->valuator->motionHintWindow = NullWindow;
1076}
1077
1078void
1079DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1080{
1081    int i;
1082    DeviceIntPtr dev;
1083    InputClientsPtr ic;
1084    struct _OtherInputMasks *inputMasks;
1085
1086    for (dev = inputInfo.devices; dev; dev = dev->next) {
1087	if (dev == inputInfo.pointer || dev == inputInfo.keyboard)
1088	    continue;
1089	DeleteDeviceFromAnyExtEvents(pWin, dev);
1090    }
1091
1092    for (dev = inputInfo.off_devices; dev; dev = dev->next)
1093	DeleteDeviceFromAnyExtEvents(pWin, dev);
1094
1095    if (freeResources)
1096	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1097	    ic = inputMasks->inputClients;
1098	    for (i = 0; i < EMASKSIZE; i++)
1099		inputMasks->dontPropagateMask[i] = 0;
1100	    FreeResource(ic->resource, RT_NONE);
1101	}
1102}
1103
1104int
1105MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1106{
1107    DeviceIntPtr dev;
1108
1109    dev = LookupDeviceIntRec(pEvents->deviceid & DEVICE_BITS);
1110    if (!dev)
1111        return 0;
1112
1113    if (pEvents->type == DeviceMotionNotify) {
1114	if (mask & DevicePointerMotionHintMask) {
1115	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1116		return 1;	/* don't send, but pretend we did */
1117	    }
1118	    pEvents->detail = NotifyHint;
1119	} else {
1120	    pEvents->detail = NotifyNormal;
1121	}
1122    }
1123    return (0);
1124}
1125
1126void
1127CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1128			     deviceKeyButtonPointer * xE, GrabPtr grab,
1129			     ClientPtr client, Mask deliveryMask)
1130{
1131    DeviceIntPtr dev;
1132
1133    dev = LookupDeviceIntRec(xE->deviceid & DEVICE_BITS);
1134    if (!dev)
1135        return;
1136
1137    if (type == DeviceMotionNotify)
1138	dev->valuator->motionHintWindow = pWin;
1139    else if ((type == DeviceButtonPress) && (!grab) &&
1140	     (deliveryMask & DeviceButtonGrabMask)) {
1141	GrabRec tempGrab;
1142
1143	tempGrab.device = dev;
1144	tempGrab.resource = client->clientAsMask;
1145	tempGrab.window = pWin;
1146	tempGrab.ownerEvents =
1147	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
1148	tempGrab.eventMask = deliveryMask;
1149	tempGrab.keyboardMode = GrabModeAsync;
1150	tempGrab.pointerMode = GrabModeAsync;
1151	tempGrab.confineTo = NullWindow;
1152	tempGrab.cursor = NullCursor;
1153	(*dev->ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
1154    }
1155}
1156
1157static Mask
1158DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
1159{
1160    InputClientsPtr other;
1161
1162    if (!wOtherInputMasks(pWin))
1163	return 0;
1164    for (other = wOtherInputMasks(pWin)->inputClients; other;
1165	 other = other->next) {
1166	if (SameClient(other, client))
1167	    return other->mask[dev->id];
1168    }
1169    return 0;
1170}
1171
1172void
1173MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
1174{
1175    WindowPtr pWin;
1176    GrabPtr grab = dev->grab;
1177
1178    pWin = dev->valuator->motionHintWindow;
1179
1180    if ((grab && SameClient(grab, client) &&
1181	 ((grab->eventMask & DevicePointerMotionHintMask) ||
1182	  (grab->ownerEvents &&
1183	   (DeviceEventMaskForClient(dev, pWin, client) &
1184	    DevicePointerMotionHintMask)))) ||
1185	(!grab &&
1186	 (DeviceEventMaskForClient(dev, pWin, client) &
1187	  DevicePointerMotionHintMask)))
1188	dev->valuator->motionHintWindow = NullWindow;
1189}
1190
1191int
1192DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
1193			     int maskndx)
1194{
1195    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
1196
1197    if (mask & ~PropagateMask[maskndx]) {
1198	client->errorValue = mask;
1199	return BadValue;
1200    }
1201
1202    if (mask == 0) {
1203	if (inputMasks)
1204	    inputMasks->dontPropagateMask[maskndx] = mask;
1205    } else {
1206	if (!inputMasks)
1207	    AddExtensionClient(pWin, client, 0, 0);
1208	inputMasks = wOtherInputMasks(pWin);
1209	inputMasks->dontPropagateMask[maskndx] = mask;
1210    }
1211    RecalculateDeviceDeliverableEvents(pWin);
1212    if (ShouldFreeInputMasks(pWin, FALSE))
1213	FreeResource(inputMasks->inputClients->resource, RT_NONE);
1214    return Success;
1215}
1216
1217static Bool
1218ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
1219{
1220    int i;
1221    Mask allInputEventMasks = 0;
1222    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
1223
1224    for (i = 0; i < EMASKSIZE; i++)
1225	allInputEventMasks |= inputMasks->dontPropagateMask[i];
1226    if (!ignoreSelectedEvents)
1227	for (i = 0; i < EMASKSIZE; i++)
1228	    allInputEventMasks |= inputMasks->inputEvents[i];
1229    if (allInputEventMasks == 0)
1230	return TRUE;
1231    else
1232	return FALSE;
1233}
1234
1235/***********************************************************************
1236 *
1237 * Walk through the window tree, finding all clients that want to know
1238 * about the Event.
1239 *
1240 */
1241
1242static void
1243FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
1244                       xEvent * ev, int count)
1245{
1246    WindowPtr p2;
1247
1248    while (p1) {
1249        p2 = p1->firstChild;
1250        (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id);
1251        FindInterestedChildren(dev, p2, mask, ev, count);
1252        p1 = p1->nextSib;
1253    }
1254}
1255
1256/***********************************************************************
1257 *
1258 * Send an event to interested clients in all windows on all screens.
1259 *
1260 */
1261
1262void
1263SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
1264{
1265    int i;
1266    WindowPtr pWin, p1;
1267
1268    for (i = 0; i < screenInfo.numScreens; i++) {
1269        pWin = WindowTable[i];
1270        (void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id);
1271        p1 = pWin->firstChild;
1272        FindInterestedChildren(dev, p1, mask, ev, count);
1273    }
1274}
1275