First import
[xorg_rtime.git] / xorg-server-1.4 / Xi / exevents.c
blobfe297ab6afecb6c0aeb6389adbcd49195332280f
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
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
27 All Rights Reserved
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
43 SOFTWARE.
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.
55 #define NEED_EVENTS
56 #ifdef HAVE_DIX_CONFIG_H
57 #include <dix-config.h>
58 #endif
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"
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.
97 void
98 RegisterOtherDevice(DeviceIntPtr device)
100 device->public.processInputProc = ProcessOtherEvent;
101 device->public.realInputProc = ProcessOtherEvent;
102 (device)->ActivateGrab = ActivateKeyboardGrab;
103 (device)->DeactivateGrab = DeactivateKeyboardGrab;
106 /*ARGSUSED*/ void
107 ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
109 BYTE *kptr;
110 int i;
111 CARD16 modifiers;
112 CARD16 mask;
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;
126 NoticeEventTime(xE);
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;
141 int *axisvals;
143 if (xV->num_valuators
144 && (!v
145 || (xV->num_valuators
146 && (first + xV->num_valuators > v->numAxes))))
147 FatalError("Bad valuators reported for device %s\n",
148 other->name);
149 xV->device_state = 0;
150 if (k)
151 xV->device_state |= k->state;
152 if (b)
153 xV->device_state |= b->state;
154 if (v && v->axisVal) {
155 axisvals = v->axisVal;
156 switch (xV->num_valuators) {
157 case 6:
158 *(axisvals + first + 5) = xV->valuator5;
159 case 5:
160 *(axisvals + first + 4) = xV->valuator4;
161 case 4:
162 *(axisvals + first + 3) = xV->valuator3;
163 case 3:
164 *(axisvals + first + 2) = xV->valuator2;
165 case 2:
166 *(axisvals + first + 1) = xV->valuator1;
167 case 1:
168 *(axisvals + first) = xV->valuator0;
169 case 0:
170 default:
171 break;
176 if (xE->u.u.type == DeviceKeyPress) {
177 if (!k)
178 return;
180 modifiers = k->modifierMap[key];
181 kptr = &k->down[key >> 3];
182 if (*kptr & bit) { /* allow ddx to generate multiple downs */
183 if (!modifiers) {
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);
190 return;
192 if (other->valuator)
193 other->valuator->motionHintWindow = NullWindow;
194 *kptr |= bit;
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]++;
200 k->state |= mask;
201 modifiers &= ~mask;
204 if (!grab && CheckDeviceGrabs(other, xE, 0, count)) {
205 other->activatingKey = key;
206 return;
208 } else if (xE->u.u.type == DeviceKeyRelease) {
209 if (!k)
210 return;
212 kptr = &k->down[key >> 3];
213 if (!(*kptr & bit)) /* guard against duplicates */
214 return;
215 modifiers = k->modifierMap[key];
216 if (other->valuator)
217 other->valuator->motionHintWindow = NullWindow;
218 *kptr &= ~bit;
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;
225 k->state &= ~mask;
227 modifiers &= ~mask;
231 if (other->fromPassiveGrab && (key == other->activatingKey))
232 deactivateDeviceGrab = TRUE;
233 } else if (xE->u.u.type == DeviceButtonPress) {
234 if (!b)
235 return;
237 kptr = &b->down[key >> 3];
238 *kptr |= bit;
239 if (other->valuator)
240 other->valuator->motionHintWindow = NullWindow;
241 b->buttonsDown++;
242 b->motionMask = DeviceButtonMotionMask;
243 xE->u.u.detail = b->map[key];
244 if (xE->u.u.detail == 0)
245 return;
246 if (xE->u.u.detail <= 5)
247 b->state |= (Button1Mask >> 1) << xE->u.u.detail;
248 SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
249 if (!grab)
250 if (CheckDeviceGrabs(other, xE, 0, count))
251 /* if a passive grab was activated, the event has been sent
252 * already */
253 return;
255 } else if (xE->u.u.type == DeviceButtonRelease) {
256 if (!b)
257 return;
259 kptr = &b->down[key >> 3];
260 *kptr &= ~bit;
261 if (other->valuator)
262 other->valuator->motionHintWindow = NullWindow;
263 if (b->buttonsDown >= 1 && !--b->buttonsDown)
264 b->motionMask = 0;
265 xE->u.u.detail = b->map[key];
266 if (xE->u.u.detail == 0)
267 return;
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;
278 if (grab)
279 DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
280 else if (other->focus)
281 DeliverFocusedEvent(other, xE, GetSpriteWindow(), count);
282 else
283 DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow,
284 other, count);
286 if (deactivateDeviceGrab == TRUE)
287 (*other->DeactivateGrab) (other);
290 _X_EXPORT int
291 InitProximityClassDeviceStruct(DeviceIntPtr dev)
293 ProximityClassPtr proxc;
295 proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec));
296 if (!proxc)
297 return FALSE;
298 dev->proximity = proxc;
299 return TRUE;
302 _X_EXPORT void
303 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
304 int resolution, int min_res, int max_res)
306 AxisInfoPtr ax;
308 if (!dev || !dev->valuator)
309 return;
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;
320 static void
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;
328 ev->num_keys = 0;
329 ev->num_buttons = 0;
330 ev->num_valuators = 0;
332 if (b) {
333 ev->classes_reported |= (1 << ButtonClass);
334 ev->num_buttons = b->numButtons;
335 memmove((char *)&ev->buttons[0], (char *)b->down, 4);
336 } else if (k) {
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);
341 if (v) {
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) {
348 case 3:
349 ev->valuator2 = v->axisVal[first + 2];
350 case 2:
351 ev->valuator1 = v->axisVal[first + 1];
352 case 1:
353 ev->valuator0 = v->axisVal[first];
354 break;
359 static void
360 FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
361 int first)
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) {
370 case 3:
371 ev->valuator2 = v->axisVal[first + 2];
372 case 2:
373 ev->valuator1 = v->axisVal[first + 1];
374 case 1:
375 ev->valuator0 = v->axisVal[first];
376 break;
378 first += ev->num_valuators;
381 void
382 DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
383 WindowPtr pWin)
385 deviceFocus event;
387 if (type == FocusIn)
388 type = DeviceFocusIn;
389 else
390 type = DeviceFocusOut;
392 event.deviceid = dev->id;
393 event.mode = mode;
394 event.type = type;
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))
406 int evcount = 1;
407 deviceStateNotify *ev, *sev;
408 deviceKeyStateNotify *kev;
409 deviceButtonStateNotify *bev;
411 KeyClassPtr k;
412 ButtonClassPtr b;
413 ValuatorClassPtr v;
414 int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
416 if ((b = dev->button) != NULL) {
417 nbuttons = b->numButtons;
418 if (nbuttons > 32)
419 evcount++;
421 if ((k = dev->key) != NULL) {
422 nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
423 if (nkeys > 32)
424 evcount++;
425 if (nbuttons > 0) {
426 evcount++;
429 if ((v = dev->valuator) != NULL) {
430 nval = v->numAxes;
432 if (nval > 3)
433 evcount++;
434 if (nval > 6) {
435 if (!(k && b))
436 evcount++;
437 if (nval > 9)
438 evcount += ((nval - 7) / 3);
442 sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent));
443 FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
445 if (b != NULL) {
446 FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
447 first += 3;
448 nval -= 3;
449 if (nbuttons > 32) {
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);
456 if (nval > 0) {
457 (ev - 1)->deviceid |= MORE_EVENTS;
458 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
459 first += 3;
460 nval -= 3;
464 if (k != NULL) {
465 FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
466 first += 3;
467 nval -= 3;
468 if (nkeys > 32) {
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);
475 if (nval > 0) {
476 (ev - 1)->deviceid |= MORE_EVENTS;
477 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
478 first += 3;
479 nval -= 3;
483 while (nval > 0) {
484 FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
485 first += 3;
486 nval -= 3;
487 if (nval > 0) {
488 (ev - 1)->deviceid |= MORE_EVENTS;
489 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
490 first += 3;
491 nval -= 3;
495 (void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount,
496 DeviceStateNotifyMask, NullGrab, dev->id);
497 xfree(sev);
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;
508 CursorPtr cursor;
509 GrabPtr grab;
510 int rc;
512 if ((this_device_mode != GrabModeSync) &&
513 (this_device_mode != GrabModeAsync)) {
514 client->errorValue = this_device_mode;
515 return BadValue;
517 if ((other_devices_mode != GrabModeSync) &&
518 (other_devices_mode != GrabModeAsync)) {
519 client->errorValue = other_devices_mode;
520 return BadValue;
522 if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
523 client->errorValue = modifiers;
524 return BadValue;
526 if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
527 client->errorValue = ownerEvents;
528 return BadValue;
530 rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess);
531 if (rc != Success)
532 return rc;
533 if (rconfineTo == None)
534 confineTo = NullWindow;
535 else {
536 rc = dixLookupWindow(&confineTo, rconfineTo, client, DixUnknownAccess);
537 if (rc != Success)
538 return rc;
540 if (rcursor == None)
541 cursor = NullCursor;
542 else {
543 cursor = (CursorPtr) LookupIDByType(rcursor, RT_CURSOR);
544 if (!cursor) {
545 client->errorValue = rcursor;
546 return BadCursor;
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);
554 if (!grab)
555 return BadAlloc;
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)
565 WindowPtr pWin;
566 GrabPtr grab;
567 KeyClassPtr k = dev->key;
568 int rc;
570 if (k == NULL)
571 return BadMatch;
572 if ((other_devices_mode != GrabModeSync) &&
573 (other_devices_mode != GrabModeAsync)) {
574 client->errorValue = other_devices_mode;
575 return BadValue;
577 if ((this_device_mode != GrabModeSync) &&
578 (this_device_mode != GrabModeAsync)) {
579 client->errorValue = this_device_mode;
580 return BadValue;
582 if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode))
583 && (key != AnyKey)) {
584 client->errorValue = key;
585 return BadValue;
587 if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
588 client->errorValue = modifiers;
589 return BadValue;
591 if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) {
592 client->errorValue = ownerEvents;
593 return BadValue;
595 rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess);
596 if (rc != Success)
597 return rc;
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);
603 if (!grab)
604 return BadAlloc;
605 return AddPassiveGrabToList(grab);
609 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
610 Mask mask, Mask exclusivemasks, Mask validmasks)
612 int mskidx = dev->id;
613 int i, ret;
614 Mask check;
615 InputClientsPtr others;
617 if (mask & ~validmasks) {
618 client->errorValue = mask;
619 return BadValue;
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
628 * events. */
629 for (others = wOtherInputMasks(pWin)->inputClients; others;
630 others = others->next) {
631 if (!SameClient(others, client) && (check &
632 others->mask[mskidx]))
633 return BadAccess;
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;
641 if (mask == 0) {
642 for (i = 0; i < EMASKSIZE; i++)
643 if (i != mskidx && others->mask[i] != 0)
644 break;
645 if (i == EMASKSIZE) {
646 RecalculateDeviceDeliverableEvents(pWin);
647 if (ShouldFreeInputMasks(pWin, FALSE))
648 FreeResource(others->resource, RT_NONE);
649 return Success;
652 goto maskSet;
656 check = 0;
657 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
658 return ret;
659 maskSet:
660 if (dev->valuator)
661 if ((dev->valuator->motionHintWindow == pWin) &&
662 (mask & DevicePointerMotionHintMask) &&
663 !(check & DevicePointerMotionHintMask) && !dev->grab)
664 dev->valuator->motionHintWindow = NullWindow;
665 RecalculateDeviceDeliverableEvents(pWin);
666 return Success;
670 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
672 InputClientsPtr others;
674 if (!pWin->optional && !MakeWindowOptional(pWin))
675 return BadAlloc;
676 others = (InputClients *) xalloc(sizeof(InputClients));
677 if (!others)
678 return BadAlloc;
679 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
680 return BadAlloc;
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))
687 return BadAlloc;
688 return Success;
691 static Bool
692 MakeInputMasks(WindowPtr pWin)
694 struct _OtherInputMasks *imasks;
696 imasks = (struct _OtherInputMasks *)
697 xalloc(sizeof(struct _OtherInputMasks));
698 if (!imasks)
699 return FALSE;
700 bzero((char *)imasks, sizeof(struct _OtherInputMasks));
701 pWin->optional->inputMasks = imasks;
702 return TRUE;
705 void
706 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
708 InputClientsPtr others;
709 struct _OtherInputMasks *inputMasks; /* default: NULL */
710 WindowPtr pChild, tmp;
711 int i;
713 pChild = pWin;
714 while (1) {
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]
728 & ~inputMasks->
729 dontPropagateMask[i] & PropagateMask[i]);
731 if (pChild->firstChild) {
732 pChild = pChild->firstChild;
733 continue;
735 while (!pChild->nextSib && (pChild != pWin))
736 pChild = pChild->parent;
737 if (pChild == pWin)
738 break;
739 pChild = pChild->nextSib;
744 InputClientGone(WindowPtr pWin, XID id)
746 InputClientsPtr other, prev;
748 if (!wOtherInputMasks(pWin))
749 return (Success);
750 prev = 0;
751 for (other = wOtherInputMasks(pWin)->inputClients; other;
752 other = other->next) {
753 if (other->resource == id) {
754 if (prev) {
755 prev->next = other->next;
756 xfree(other);
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);
763 xfree(other);
764 } else {
765 other->resource = FakeClientID(0);
766 if (!AddResource(other->resource, RT_INPUTCLIENT,
767 (pointer) pWin))
768 return BadAlloc;
770 } else {
771 wOtherInputMasks(pWin)->inputClients = other->next;
772 xfree(other);
774 RecalculateDeviceDeliverableEvents(pWin);
775 return (Success);
777 prev = other;
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)
786 WindowPtr pWin;
787 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
788 WindowPtr spriteWin = GetSpriteWindow();
790 if (dest == PointerWindow)
791 pWin = spriteWin;
792 else if (dest == InputFocus) {
793 WindowPtr inputFocus;
795 if (!d->focus)
796 inputFocus = spriteWin;
797 else
798 inputFocus = d->focus->win;
800 if (inputFocus == FollowKeyboardWin)
801 inputFocus = inputInfo.keyboard->focus->win;
803 if (inputFocus == NoneWin)
804 return Success;
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;
813 pWin = spriteWin;
814 } else
815 effectiveFocus = pWin = inputFocus;
816 } else
817 dixLookupWindow(&pWin, dest, client, DixUnknownAccess);
818 if (!pWin)
819 return BadWindow;
820 if ((propagate != xFalse) && (propagate != xTrue)) {
821 client->errorValue = propagate;
822 return BadValue;
824 ev->u.u.type |= 0x80;
825 if (propagate) {
826 for (; pWin; pWin = pWin->parent) {
827 if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id))
828 return Success;
829 if (pWin == effectiveFocus)
830 return Success;
831 if (wOtherInputMasks(pWin))
832 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
833 if (!mask)
834 break;
836 } else
837 (void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id));
838 return Success;
842 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
844 int i;
845 ButtonClassPtr b = dev->button;
847 if (b == NULL)
848 return BadMatch;
850 if (nElts != b->numButtons) {
851 client->errorValue = nElts;
852 return BadValue;
854 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
855 return BadValue;
856 for (i = 0; i < nElts; i++)
857 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
858 return MappingBusy;
859 for (i = 0; i < nElts; i++)
860 b->map[i + 1] = map[i];
861 return Success;
865 SetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen,
866 int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k)
868 KeyCode *map = NULL;
869 int inputMapLen;
870 int i;
872 *k = dev->key;
873 if (*k == NULL)
874 return BadMatch;
875 if (len != ((numKeyPerModifier << 1) + rlen))
876 return BadLength;
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)"
885 i = inputMapLen;
886 while (i--) {
887 if (inputMap[i]
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)) {
906 return MappingBusy;
907 } else {
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
917 * list of keycodes.
919 if (inputMapLen) {
920 map = (KeyCode *) xalloc(inputMapLen);
921 if (!map)
922 return BadAlloc;
924 if ((*k)->modifierKeyMap)
925 xfree((*k)->modifierKeyMap);
926 if (inputMapLen) {
927 (*k)->modifierKeyMap = map;
928 memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen);
929 } else
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++)
936 if (inputMap[i]) {
937 (*k)->modifierMap[inputMap[i]]
938 |= (1 << (i / (*k)->maxKeysPerModifier));
941 return (MappingSuccess);
944 void
945 SendDeviceMappingNotify(CARD8 request,
946 KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev)
948 xEvent event;
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;
957 ev->count = count;
960 SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1);
964 ChangeKeyMapping(ClientPtr client,
965 DeviceIntPtr dev,
966 unsigned len,
967 int type,
968 KeyCode firstKeyCode,
969 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
971 KeySymsRec keysyms;
972 KeyClassPtr k = dev->key;
974 if (k == NULL)
975 return (BadMatch);
977 if (len != (keyCodes * keySymsPerKeyCode))
978 return BadLength;
980 if ((firstKeyCode < k->curKeySyms.minKeyCode) ||
981 (firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) {
982 client->errorValue = firstKeyCode;
983 return BadValue;
985 if (keySymsPerKeyCode == 0) {
986 client->errorValue = 0;
987 return BadValue;
989 keysyms.minKeyCode = firstKeyCode;
990 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
991 keysyms.mapWidth = keySymsPerKeyCode;
992 keysyms.map = map;
993 if (!SetKeySymsMap(&k->curKeySyms, &keysyms))
994 return BadAlloc;
995 SendDeviceMappingNotify(MappingKeyboard, firstKeyCode, keyCodes, dev);
996 return client->noClientException;
999 static void
1000 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1002 WindowPtr parent;
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. */
1019 if (dev->grab)
1020 focusEventMode = NotifyWhileGrabbed;
1022 switch (dev->focus->revert) {
1023 case RevertToNone:
1024 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1025 dev->focus->win = NoneWin;
1026 dev->focus->traceGood = 0;
1027 break;
1028 case RevertToParent:
1029 parent = pWin;
1030 do {
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;
1038 break;
1039 case RevertToPointerRoot:
1040 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1041 dev->focus->win = PointerRootWin;
1042 dev->focus->traceGood = 0;
1043 break;
1044 case RevertToFollowKeyboard:
1045 if (inputInfo.keyboard->focus->win) {
1046 DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win,
1047 focusEventMode);
1048 dev->focus->win = FollowKeyboardWin;
1049 dev->focus->traceGood = 0;
1050 } else {
1051 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1052 dev->focus->win = NoneWin;
1053 dev->focus->traceGood = 0;
1055 break;
1059 if (dev->valuator)
1060 if (dev->valuator->motionHintWindow == pWin)
1061 dev->valuator->motionHintWindow = NullWindow;
1064 void
1065 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1067 int i;
1068 DeviceIntPtr dev;
1069 InputClientsPtr ic;
1070 struct _OtherInputMasks *inputMasks;
1072 for (dev = inputInfo.devices; dev; dev = dev->next) {
1073 if (dev == inputInfo.pointer || dev == inputInfo.keyboard)
1074 continue;
1075 DeleteDeviceFromAnyExtEvents(pWin, dev);
1078 for (dev = inputInfo.off_devices; dev; dev = dev->next)
1079 DeleteDeviceFromAnyExtEvents(pWin, dev);
1081 if (freeResources)
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)
1093 DeviceIntPtr dev;
1095 dev = LookupDeviceIntRec(pEvents->deviceid & DEVICE_BITS);
1096 if (!dev)
1097 return 0;
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;
1105 } else {
1106 pEvents->detail = NotifyNormal;
1109 return (0);
1112 void
1113 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1114 deviceKeyButtonPointer * xE, GrabPtr grab,
1115 ClientPtr client, Mask deliveryMask)
1117 DeviceIntPtr dev;
1119 dev = LookupDeviceIntRec(xE->deviceid & DEVICE_BITS);
1120 if (!dev)
1121 return;
1123 if (type == DeviceMotionNotify)
1124 dev->valuator->motionHintWindow = pWin;
1125 else if ((type == DeviceButtonPress) && (!grab) &&
1126 (deliveryMask & DeviceButtonGrabMask)) {
1127 GrabRec tempGrab;
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);
1143 static Mask
1144 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
1146 InputClientsPtr other;
1148 if (!wOtherInputMasks(pWin))
1149 return 0;
1150 for (other = wOtherInputMasks(pWin)->inputClients; other;
1151 other = other->next) {
1152 if (SameClient(other, client))
1153 return other->mask[dev->id];
1155 return 0;
1158 void
1159 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
1161 WindowPtr pWin;
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)))) ||
1171 (!grab &&
1172 (DeviceEventMaskForClient(dev, pWin, client) &
1173 DevicePointerMotionHintMask)))
1174 dev->valuator->motionHintWindow = NullWindow;
1178 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
1179 int maskndx)
1181 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
1183 if (mask & ~PropagateMask[maskndx]) {
1184 client->errorValue = mask;
1185 return BadValue;
1188 if (mask == 0) {
1189 if (inputMasks)
1190 inputMasks->dontPropagateMask[maskndx] = mask;
1191 } else {
1192 if (!inputMasks)
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);
1200 return Success;
1203 static Bool
1204 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
1206 int i;
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)
1216 return TRUE;
1217 else
1218 return FALSE;
1221 /***********************************************************************
1223 * Walk through the window tree, finding all clients that want to know
1224 * about the Event.
1228 static void
1229 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
1230 xEvent * ev, int count)
1232 WindowPtr p2;
1234 while (p1) {
1235 p2 = p1->firstChild;
1236 (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id);
1237 FindInterestedChildren(dev, p2, mask, ev, count);
1238 p1 = p1->nextSib;
1242 /***********************************************************************
1244 * Send an event to interested clients in all windows on all screens.
1248 void
1249 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
1251 int i;
1252 WindowPtr pWin, p1;
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);