Bug Summary

File:src/PassivGrab.c
Location:line 741, column 33
Description:Dereference of null pointer

Annotated Source Code

1/*
2
3Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
4
5Permission is hereby granted, free of charge, to any person obtaining a
6copy of this software and associated documentation files (the "Software"),
7to deal in the Software without restriction, including without limitation
8the rights to use, copy, modify, merge, publish, distribute, sublicense,
9and/or sell copies of the Software, and to permit persons to whom the
10Software is furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice (including the next
13paragraph) shall be included in all copies or substantial portions of the
14Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22DEALINGS IN THE SOFTWARE.
23
24*/
25/********************************************************
26
27Copyright 1988 by Hewlett-Packard Company
28Copyright 1987, 1988, 1989,1990 by Digital Equipment Corporation, Maynard, Massachusetts
29
30Permission to use, copy, modify, and distribute this software
31and its documentation for any purpose and without fee is hereby
32granted, provided that the above copyright notice appear in all
33copies and that both that copyright notice and this permission
34notice appear in supporting documentation, and that the names of
35Hewlett-Packard or Digital not be used in advertising or
36publicity pertaining to distribution of the software without specific,
37written prior permission.
38
39DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45SOFTWARE.
46
47********************************************************/
48
49/*
50
51Copyright 1987, 1988, 1989, 1990, 1994, 1998 The Open Group
52
53Permission to use, copy, modify, distribute, and sell this software and its
54documentation for any purpose is hereby granted without fee, provided that
55the above copyright notice appear in all copies and that both that
56copyright notice and this permission notice appear in supporting
57documentation.
58
59The above copyright notice and this permission notice shall be included in
60all copies or substantial portions of the Software.
61
62THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
66AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
67CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68
69Except as contained in this notice, the name of The Open Group shall not be
70used in advertising or otherwise to promote the sale, use or other dealings
71in this Software without prior written authorization from The Open Group.
72
73*/
74
75#ifdef HAVE_CONFIG_H1
76#include <config.h>
77#endif
78#include "IntrinsicI.h"
79#include "StringDefs.h"
80#include "PassivGraI.h"
81
82/* typedef unsigned long Mask; */
83#define BITMASK(i)(((Mask)1) << ((i) & 31)) (((Mask)1) << ((i) & 31))
84#define MASKIDX(i)((i) >> 5) ((i) >> 5)
85#define MASKWORD(buf, i)buf[((i) >> 5)] buf[MASKIDX(i)((i) >> 5)]
86#define BITSET(buf, i)buf[((i) >> 5)] |= (((Mask)1) << ((i) & 31)) MASKWORD(buf, i)buf[((i) >> 5)] |= BITMASK(i)(((Mask)1) << ((i) & 31))
87#define BITCLEAR(buf, i)buf[((i) >> 5)] &= ~(((Mask)1) << ((i) & 31
))
MASKWORD(buf, i)buf[((i) >> 5)] &= ~BITMASK(i)(((Mask)1) << ((i) & 31))
88#define GETBIT(buf, i)(buf[((i) >> 5)] & (((Mask)1) << ((i) & 31
)))
(MASKWORD(buf, i)buf[((i) >> 5)] & BITMASK(i)(((Mask)1) << ((i) & 31)))
89#define MasksPerDetailMask8 8
90
91#define pDisplay(grabPtr)(((grabPtr)->widget)->core.screen->display) (((grabPtr)->widget)->core.screen->display)
92#define pWindow(grabPtr)(((grabPtr)->widget)->core.window) (((grabPtr)->widget)->core.window)
93
94
95/***************************************************************************/
96/*********************** Internal Support Routines *************************/
97/***************************************************************************/
98
99/*
100 * Turn off (clear) the bit in the specified detail mask which is associated
101 * with the detail.
102 */
103
104static void DeleteDetailFromMask(
105 Mask **ppDetailMask,
106 unsigned short detail)
107{
108 Mask *pDetailMask = *ppDetailMask;
109
110 if (!pDetailMask) {
111 int i;
112 pDetailMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask8);
113 for (i = MasksPerDetailMask8; --i >= 0; )
114 pDetailMask[i] = ~0;
115 *ppDetailMask = pDetailMask;
116 }
117 BITCLEAR((pDetailMask), detail)(pDetailMask)[((detail) >> 5)] &= ~(((Mask)1) <<
((detail) & 31))
;
118}
119
120
121/*
122 * Make an exact copy of the specified detail mask.
123 */
124
125static Mask *CopyDetailMask(
126 Mask *pOriginalDetailMask)
127{
128 Mask *pTempMask;
129 int i;
130
131 if (!pOriginalDetailMask)
132 return NULL((void*)0);
133
134 pTempMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask8);
135
136 for ( i = 0; i < MasksPerDetailMask8; i++)
137 pTempMask[i]= pOriginalDetailMask[i];
138
139 return pTempMask;
140}
141
142
143/*
144 * Allocate a new grab entry, and fill in all of the fields using the
145 * specified parameters.
146 */
147
148static XtServerGrabPtr CreateGrab(
149 Widget widget,
150 Boolean ownerEvents,
151 Modifiers modifiers,
152 KeyCode keybut,
153 int pointer_mode,
154 int keyboard_mode,
155 Mask event_mask,
156 Window confine_to,
157 Cursor cursor,
158 Boolean need_ext)
159{
160 XtServerGrabPtr grab;
161
162 if (confine_to || cursor)
163 need_ext = True1;
164 grab = (XtServerGrabPtr)__XtMalloc(sizeof(XtServerGrabRec) +
165 (need_ext ? sizeof(XtServerGrabExtRec)
166 : 0));
167 grab->next = NULL((void*)0);
168 grab->widget = widget;
169 grab->ownerEvents = ownerEvents;
170 grab->pointerMode = pointer_mode;
171 grab->keyboardMode = keyboard_mode;
172 grab->eventMask = event_mask;
173 grab->hasExt = need_ext;
174 grab->confineToIsWidgetWin = (XtWindow (widget)((widget)->core.window) == confine_to);
175 grab->modifiers = modifiers;
176 grab->keybut = keybut;
177 if (need_ext) {
178 XtServerGrabExtPtr ext = GRABEXT(grab)((XtServerGrabExtPtr)((grab)+1));
179 ext->pModifiersMask = NULL((void*)0);
180 ext->pKeyButMask = NULL((void*)0);
181 ext->confineTo = confine_to;
182 ext->cursor = cursor;
183 }
184 return grab;
185}
186
187
188/*
189 * Free up the space occupied by a grab entry.
190 */
191
192static void FreeGrab(
193 XtServerGrabPtr pGrab)
194{
195 if (pGrab->hasExt) {
196 XtServerGrabExtPtr ext = GRABEXT(pGrab)((XtServerGrabExtPtr)((pGrab)+1));
197 if (ext->pModifiersMask)
198 XtFree((char *)ext->pModifiersMask);
199 if (ext->pKeyButMask)
200 XtFree((char *)ext->pKeyButMask);
201 }
202 XtFree((char *)pGrab);
203}
204
205typedef struct _DetailRec {
206 unsigned short exact;
207 Mask *pMask;
208} DetailRec, *DetailPtr;
209
210/*
211 * If the first detail is set to 'exception' and the second detail
212 * is contained in the mask of the first, then TRUE is returned.
213 */
214
215static Boolint IsInGrabMask(
216 register DetailPtr firstDetail,
217 register DetailPtr secondDetail,
218 unsigned short exception)
219{
220 if (firstDetail->exact == exception) {
221 if (!firstDetail->pMask)
222 return TRUE1;
223
224 /* (at present) never called with two non-null pMasks */
225 if (secondDetail->exact == exception)
226 return FALSE0;
227
228 if (GETBIT(firstDetail->pMask, secondDetail->exact)(firstDetail->pMask[((secondDetail->exact) >> 5)]
& (((Mask)1) << ((secondDetail->exact) & 31
)))
)
229 return TRUE1;
230 }
231
232 return FALSE0;
233}
234
235
236/*
237 * If neither of the details is set to 'exception', and they match
238 * exactly, then TRUE is returned.
239 */
240
241static Boolint IdenticalExactDetails(
242 unsigned short firstExact,
243 unsigned short secondExact,
244 unsigned short exception)
245{
246 if ((firstExact == exception) || (secondExact == exception))
247 return FALSE0;
248
249 if (firstExact == secondExact)
250 return TRUE1;
251
252 return FALSE0;
253}
254
255
256/*
257 * If the first detail is set to 'exception', and its mask has the bit
258 * enabled which corresponds to the second detail, OR if neither of the
259 * details is set to 'exception' and the details match exactly, then
260 * TRUE is returned.
261 */
262
263static Boolint DetailSupersedesSecond(
264 register DetailPtr firstDetail,
265 register DetailPtr secondDetail,
266 unsigned short exception)
267{
268 if (IsInGrabMask(firstDetail, secondDetail, exception))
269 return TRUE1;
270
271 if (IdenticalExactDetails(firstDetail->exact, secondDetail->exact,
272 exception))
273 return TRUE1;
274
275 return FALSE0;
276}
277
278
279/*
280 * If the two grab events match exactly, or if the first grab entry
281 * 'encompasses' the second grab entry, then TRUE is returned.
282 */
283
284static Boolint GrabSupersedesSecond(
285 register XtServerGrabPtr pFirstGrab,
286 register XtServerGrabPtr pSecondGrab)
287{
288 DetailRec first, second;
289
290 first.exact = pFirstGrab->modifiers;
291 if (pFirstGrab->hasExt)
292 first.pMask = GRABEXT(pFirstGrab)((XtServerGrabExtPtr)((pFirstGrab)+1))->pModifiersMask;
293 else
294 first.pMask = NULL((void*)0);
295 second.exact = pSecondGrab->modifiers;
296 if (pSecondGrab->hasExt)
297 second.pMask = GRABEXT(pSecondGrab)((XtServerGrabExtPtr)((pSecondGrab)+1))->pModifiersMask;
298 else
299 second.pMask = NULL((void*)0);
300 if (!DetailSupersedesSecond(&first, &second, (unsigned short)AnyModifier(1<<15)))
301 return FALSE0;
302
303 first.exact = pFirstGrab->keybut;
304 if (pFirstGrab->hasExt)
305 first.pMask = GRABEXT(pFirstGrab)((XtServerGrabExtPtr)((pFirstGrab)+1))->pKeyButMask;
306 else
307 first.pMask = NULL((void*)0);
308 second.exact = pSecondGrab->keybut;
309 if (pSecondGrab->hasExt)
310 second.pMask = GRABEXT(pSecondGrab)((XtServerGrabExtPtr)((pSecondGrab)+1))->pKeyButMask;
311 else
312 second.pMask = NULL((void*)0);
313 if (DetailSupersedesSecond(&first, &second, (unsigned short)AnyKey0L))
314 return TRUE1;
315
316 return FALSE0;
317}
318
319
320/*
321 * Two grabs are considered to be matching if either of the following are true:
322 *
323 * 1) The two grab entries match exactly, or the first grab entry
324 * encompasses the second grab entry.
325 * 2) The second grab entry encompasses the first grab entry.
326 * 3) The keycodes match exactly, and one entry's modifiers encompasses
327 * the others.
328 * 4) The keycode for one entry encompasses the other, and the detail
329 * for the other entry encompasses the first.
330 */
331
332static Boolint GrabMatchesSecond(
333 register XtServerGrabPtr pFirstGrab,
334 register XtServerGrabPtr pSecondGrab)
335{
336 DetailRec firstD, firstM, secondD, secondM;
337
338 if (pDisplay(pFirstGrab)(((pFirstGrab)->widget)->core.screen->display) != pDisplay(pSecondGrab)(((pSecondGrab)->widget)->core.screen->display))
339 return FALSE0;
340
341 if (GrabSupersedesSecond(pFirstGrab, pSecondGrab))
342 return TRUE1;
343
344 if (GrabSupersedesSecond(pSecondGrab, pFirstGrab))
345 return TRUE1;
346
347 firstD.exact = pFirstGrab->keybut;
348 firstM.exact = pFirstGrab->modifiers;
349 if (pFirstGrab->hasExt) {
350 firstD.pMask = GRABEXT(pFirstGrab)((XtServerGrabExtPtr)((pFirstGrab)+1))->pKeyButMask;
351 firstM.pMask = GRABEXT(pFirstGrab)((XtServerGrabExtPtr)((pFirstGrab)+1))->pModifiersMask;
352 } else {
353 firstD.pMask = NULL((void*)0);
354 firstM.pMask = NULL((void*)0);
355 }
356 secondD.exact = pSecondGrab->keybut;
357 secondM.exact = pSecondGrab->modifiers;
358 if (pSecondGrab->hasExt) {
359 secondD.pMask = GRABEXT(pSecondGrab)((XtServerGrabExtPtr)((pSecondGrab)+1))->pKeyButMask;
360 secondM.pMask = GRABEXT(pSecondGrab)((XtServerGrabExtPtr)((pSecondGrab)+1))->pModifiersMask;
361 } else {
362 secondD.pMask = NULL((void*)0);
363 secondM.pMask = NULL((void*)0);
364 }
365
366 if (DetailSupersedesSecond(&secondD, &firstD, (unsigned short)AnyKey0L) &&
367 DetailSupersedesSecond(&firstM, &secondM, (unsigned short)AnyModifier(1<<15)))
368 return TRUE1;
369
370 if (DetailSupersedesSecond(&firstD, &secondD, (unsigned short)AnyKey0L) &&
371 DetailSupersedesSecond(&secondM, &firstM, (unsigned short)AnyModifier(1<<15)))
372 return TRUE1;
373
374 return FALSE0;
375}
376
377
378/*
379 * Delete a grab combination from the passive grab list. Each entry will
380 * be checked to see if it is affected by the grab being deleted. This
381 * may result in multiple entries being modified/deleted.
382 */
383
384static void DeleteServerGrabFromList(
385 XtServerGrabPtr *passiveListPtr,
386 XtServerGrabPtr pMinuendGrab)
387{
388 register XtServerGrabPtr *next;
389 register XtServerGrabPtr grab;
390 register XtServerGrabExtPtr ext;
391
392 for (next = passiveListPtr; (grab = *next); )
393 {
394 if (GrabMatchesSecond(grab, pMinuendGrab) &&
395 (pDisplay(grab)(((grab)->widget)->core.screen->display) == pDisplay(pMinuendGrab)(((pMinuendGrab)->widget)->core.screen->display)))
396 {
397 if (GrabSupersedesSecond(pMinuendGrab, grab))
398 {
399 /*
400 * The entry being deleted encompasses the list entry,
401 * so delete the list entry.
402 */
403 *next = grab->next;
404 FreeGrab(grab);
405 continue;
406 }
407
408 if (!grab->hasExt) {
409 grab = (XtServerGrabPtr)
410 XtRealloc((char *)grab, (sizeof(XtServerGrabRec) +
411 sizeof(XtServerGrabExtRec)));
412 *next = grab;
413 grab->hasExt = True1;
414 ext = GRABEXT(grab)((XtServerGrabExtPtr)((grab)+1));
415 ext->pKeyButMask = NULL((void*)0);
416 ext->pModifiersMask = NULL((void*)0);
417 ext->confineTo = None0L;
418 ext->cursor = None0L;
419 } else
420 ext = GRABEXT(grab)((XtServerGrabExtPtr)((grab)+1));
421 if ((grab->keybut == AnyKey0L) && (grab->modifiers != AnyModifier(1<<15)))
422 {
423 /*
424 * If the list entry has the key detail of AnyKey, and
425 * a modifier detail not set to AnyModifier, then we
426 * simply need to turn off the key detail bit in the
427 * list entry's key detail mask.
428 */
429 DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
430 } else if ((grab->modifiers == AnyModifier(1<<15)) &&
431 (grab->keybut != AnyKey0L)) {
432 /*
433 * The list entry has a specific key detail, but its
434 * modifier detail is set to AnyModifier; so, we only
435 * need to turn off the specified modifier combination
436 * in the list entry's modifier mask.
437 */
438 DeleteDetailFromMask(&ext->pModifiersMask,
439 pMinuendGrab->modifiers);
440 } else if ((pMinuendGrab->keybut != AnyKey0L) &&
441 (pMinuendGrab->modifiers != AnyModifier(1<<15))) {
442 /*
443 * The list entry has a key detail of AnyKey and a
444 * modifier detail of AnyModifier; the entry being
445 * deleted has a specific key and a specific modifier
446 * combination. Therefore, we need to mask off the
447 * keycode from the list entry, and also create a
448 * new entry for this keycode, which has a modifier
449 * mask set to AnyModifier & ~(deleted modifiers).
450 */
451 XtServerGrabPtr pNewGrab;
452
453 DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
454 pNewGrab = CreateGrab(grab->widget,
455 (Boolean)grab->ownerEvents,
456 (Modifiers)AnyModifier(1<<15),
457 pMinuendGrab->keybut,
458 (int)grab->pointerMode,
459 (int)grab->keyboardMode,
460 (Mask)0, (Window)0, (Cursor)0, True1);
461 GRABEXT(pNewGrab)((XtServerGrabExtPtr)((pNewGrab)+1))->pModifiersMask =
462 CopyDetailMask(ext->pModifiersMask);
463
464 DeleteDetailFromMask(&GRABEXT(pNewGrab)((XtServerGrabExtPtr)((pNewGrab)+1))->pModifiersMask,
465 pMinuendGrab->modifiers);
466
467 pNewGrab->next = *passiveListPtr;
468 *passiveListPtr = pNewGrab;
469 } else if (pMinuendGrab->keybut == AnyKey0L) {
470 /*
471 * The list entry has keycode AnyKey and modifier
472 * AnyModifier; the entry being deleted has
473 * keycode AnyKey and specific modifiers. So we
474 * simply need to mask off the specified modifier
475 * combination.
476 */
477 DeleteDetailFromMask(&ext->pModifiersMask,
478 pMinuendGrab->modifiers);
479 } else {
480 /*
481 * The list entry has keycode AnyKey and modifier
482 * AnyModifier; the entry being deleted has a
483 * specific keycode and modifier AnyModifier. So
484 * we simply need to mask off the specified
485 * keycode.
486 */
487 DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
488 }
489 }
490 next = &(*next)->next;
491 }
492}
493
494static void DestroyPassiveList(
495 XtServerGrabPtr *passiveListPtr)
496{
497 XtServerGrabPtr next, grab;
498
499 for (next = *passiveListPtr; next; ) {
500 grab = next;
501 next = grab->next;
502
503 /* not necessary to explicitly ungrab key or button;
504 * window is being destroyed so server will take care of it.
505 */
506
507 FreeGrab(grab);
508 }
509}
510
511
512/*
513 * This function is called at widget destroy time to clean up
514 */
515/*ARGSUSED*/
516void _XtDestroyServerGrabs(
517 Widget w,
518 XtPointer closure,
519 XtPointer call_data) /* unused */
520{
521 XtPerWidgetInput pwi = (XtPerWidgetInput)closure;
522 XtPerDisplayInput pdi;
523
524 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
525 pdi = _XtGetPerDisplayInput(XtDisplay(w)(((w)->core.screen)->display));
526 _XtClearAncestorCache(w);
527 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
528
529 /* Remove the active grab, if necessary */
530 if ((pdi->keyboard.grabType != XtNoServerGrab) &&
531 (pdi->keyboard.grab.widget == w)) {
532 pdi->keyboard.grabType = XtNoServerGrab;
533 pdi->activatingKey = (KeyCode)0;
534 }
535 if ((pdi->pointer.grabType != XtNoServerGrab) &&
536 (pdi->pointer.grab.widget == w))
537 pdi->pointer.grabType = XtNoServerGrab;
538
539 DestroyPassiveList(&pwi->keyList);
540 DestroyPassiveList(&pwi->ptrList);
541
542 _XtFreePerWidgetInput(w, pwi);
543}
544
545/*
546 * If the incoming event is on the passive grab list, then activate
547 * the grab. The grab will remain in effect until the key is released.
548 */
549
550XtServerGrabPtr _XtCheckServerGrabsOnWidget (
551 XEvent *event,
552 Widget widget,
553 _XtBooleanint isKeyboard)
554{
555 register XtServerGrabPtr grab;
556 XtServerGrabRec tempGrab;
557 XtServerGrabPtr *passiveListPtr;
558 XtPerWidgetInput pwi;
559
560 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
561 pwi = _XtGetPerWidgetInput(widget, FALSE0);
562 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
563 if (!pwi)
564 return (XtServerGrabPtr)NULL((void*)0);
565 if (isKeyboard)
566 passiveListPtr = &pwi->keyList;
567 else
568 passiveListPtr = &pwi->ptrList;
569
570 /*
571 * if either there is no entry in the context manager or the entry
572 * is empty, or the keyboard is grabed, then no work to be done
573 */
574 if (!*passiveListPtr)
575 return (XtServerGrabPtr)NULL((void*)0);
576
577 /* Take only the lower thirteen bits as modifier state. The X Keyboard
578 * Extension may be representing keyboard group state in two upper bits.
579 */
580 tempGrab.widget = widget;
581 tempGrab.keybut = event->xkey.keycode; /* also xbutton.button */
582 tempGrab.modifiers = event->xkey.state & 0x1FFF; /*also xbutton.state*/
583 tempGrab.hasExt = False0;
584
585 for (grab = *passiveListPtr; grab; grab = grab->next) {
586 if (GrabMatchesSecond(&tempGrab, grab))
587 return (grab);
588 }
589 return (XtServerGrabPtr)NULL((void*)0);
590}
591
592/*
593 * This handler is needed to guarantee that we see releases on passive
594 * button grabs for widgets that haven't selected for button release.
595 */
596
597/*ARGSUSED*/
598static void ActiveHandler (
599 Widget widget,
600 XtPointer pdi,
601 XEvent *event,
602 Boolean *cont)
603{
604 /* nothing */
605}
606
607
608/*
609 * MakeGrab
610 */
611static void MakeGrab(
612 XtServerGrabPtr grab,
613 XtServerGrabPtr *passiveListPtr,
614 Boolean isKeyboard,
615 XtPerDisplayInput pdi,
616 XtPerWidgetInput pwi)
617{
618 if (!isKeyboard && !pwi->active_handler_added) {
619 XtAddEventHandler(grab->widget, ButtonReleaseMask(1L<<3), FALSE0,
620 ActiveHandler, (XtPointer)pdi);
621 pwi->active_handler_added = TRUE1;
622 }
623
624 if (isKeyboard) {
625 XGrabKey(pDisplay(grab)(((grab)->widget)->core.screen->display),
626 grab->keybut, grab->modifiers,
627 pWindow(grab)(((grab)->widget)->core.window), grab->ownerEvents,
628 grab->pointerMode, grab->keyboardMode);
629 } else {
630 Window confineTo = None0L;
631 Cursor cursor = None0L;
632
633 if (grab->hasExt) {
634 if (grab->confineToIsWidgetWin)
635 confineTo = XtWindow (grab->widget)((grab->widget)->core.window);
636 else
637 confineTo = GRABEXT(grab)((XtServerGrabExtPtr)((grab)+1))->confineTo;
638 cursor = GRABEXT(grab)((XtServerGrabExtPtr)((grab)+1))->cursor;
639 }
640 XGrabButton(pDisplay(grab)(((grab)->widget)->core.screen->display),
641 grab->keybut, grab->modifiers,
642 pWindow(grab)(((grab)->widget)->core.window), grab->ownerEvents, grab->eventMask,
643 grab->pointerMode, grab->keyboardMode,
644 confineTo, cursor);
645 }
646
647 /* Add the new grab entry to the passive key grab list */
648 grab->next = *passiveListPtr;
649 *passiveListPtr = grab;
650}
651
652static void MakeGrabs(
653 XtServerGrabPtr *passiveListPtr,
654 Boolean isKeyboard,
655 XtPerDisplayInput pdi)
656{
657 XtServerGrabPtr next = *passiveListPtr;
658 XtServerGrabPtr grab;
659 XtPerWidgetInput pwi;
660 /*
661 * make MakeGrab build a new list that has had the merge
662 * processing done on it. Start with an empty list
663 * (passiveListPtr).
664 */
665 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
666 *passiveListPtr = NULL((void*)0);
667 while (next)
668 {
669 grab = next;
670 next = grab->next;
671 pwi = _XtGetPerWidgetInput(grab->widget, FALSE0);
672 MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi);
673 }
674 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
675}
676
677/*
678 * This function is the event handler attached to the associated widget
679 * when grabs need to be added, but the widget is not yet realized. When
680 * it is first mapped, this handler will be invoked, and it will add all
681 * needed grabs.
682 */
683
684/*ARGSUSED*/
685static void RealizeHandler (
686 Widget widget,
687 XtPointer closure,
688 XEvent *event, /* unused */
689 Boolean *cont) /* unused */
690{
691 XtPerWidgetInput pwi = (XtPerWidgetInput)closure;
692 XtPerDisplayInput pdi;
693
694 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
695 pdi = _XtGetPerDisplayInput(XtDisplay(widget)(((widget)->core.screen)->display));
696 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
697 MakeGrabs(&pwi->keyList, KEYBOARD1, pdi);
698 MakeGrabs(&pwi->ptrList, POINTER0, pdi);
699
700 XtRemoveEventHandler(widget, XtAllEvents((EventMask) -1L), True1,
701 RealizeHandler, (XtPointer)pwi);
702 pwi->realize_handler_added = FALSE0;
703}
704
705/***************************************************************************/
706/**************************** Global Routines ******************************/
707/***************************************************************************/
708
709
710/*
711 * Routine used by an application to set up a passive grab for a key/modifier
712 * combination.
713 */
714
715static
716void GrabKeyOrButton (
717 Widget widget,
718 KeyCode keyOrButton,
719 Modifiers modifiers,
720 Boolean owner_events,
721 int pointer_mode,
722 int keyboard_mode,
723 Mask event_mask,
724 Window confine_to,
725 Cursor cursor,
726 Boolean isKeyboard)
727{
728 XtServerGrabPtr *passiveListPtr;
729 XtServerGrabPtr newGrab;
730 XtPerWidgetInput pwi;
731 XtPerDisplayInput pdi;
732
733
734 XtCheckSubclass(widget, coreWidgetClass, "in XtGrabKey or XtGrabButton");
735 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
736 pwi = _XtGetPerWidgetInput(widget, TRUE1);
737 if (isKeyboard)
4
Taking false branch
738 passiveListPtr = &pwi->keyList;
739 else
740 passiveListPtr = &pwi->ptrList;
741 pdi = _XtGetPerDisplayInput(XtDisplay(widget)(((widget)->core.screen)->display));
5
Within the expansion of the macro 'XtDisplay':
a
Dereference of null pointer
742 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
743 newGrab = CreateGrab(widget, owner_events, modifiers,
744 keyOrButton, pointer_mode, keyboard_mode,
745 event_mask, confine_to, cursor, False0);
746 /*
747 * if the widget is realized then process the entry into the grab
748 * list. else if the list is empty (i.e. first time) then add the
749 * event handler. then add the raw entry to the list for processing
750 * in the handler at realize time.
751 */
752 if (XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
)
753 MakeGrab(newGrab, passiveListPtr, isKeyboard, pdi, pwi);
754 else {
755 if (!pwi->realize_handler_added)
756 {
757 XtAddEventHandler(widget, StructureNotifyMask(1L<<17), FALSE0,
758 RealizeHandler,
759 (XtPointer)pwi);
760 pwi->realize_handler_added = TRUE1;
761 }
762
763 while (*passiveListPtr)
764 passiveListPtr = &(*passiveListPtr)->next;
765 *passiveListPtr = newGrab;
766 }
767}
768
769
770static
771void UngrabKeyOrButton (
772 Widget widget,
773 int keyOrButton,
774 Modifiers modifiers,
775 Boolean isKeyboard)
776{
777 XtServerGrabRec tempGrab;
778 XtPerWidgetInput pwi;
779
780 XtCheckSubclass(widget, coreWidgetClass,
781 "in XtUngrabKey or XtUngrabButton");
782
783 /* Build a temporary grab list entry */
784 tempGrab.widget = widget;
785 tempGrab.modifiers = modifiers;
786 tempGrab.keybut = keyOrButton;
787 tempGrab.hasExt = False0;
788
789 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
790 pwi = _XtGetPerWidgetInput(widget, FALSE0);
791 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
792 /*
793 * if there is no entry in the context manager then somethings wrong
794 */
795 if (!pwi)
796 {
797 XtAppWarningMsg(XtWidgetToApplicationContext(widget),
798 "invalidGrab", "ungrabKeyOrButton", XtCXtToolkitError,
799 "Attempt to remove nonexistent passive grab",
800 (String *)NULL((void*)0), (Cardinal *)NULL((void*)0));
801 return;
802 }
803
804 if (XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
)
805 {
806 if (isKeyboard)
807 XUngrabKey(widget->core.screen->display,
808 keyOrButton, (unsigned int)modifiers,
809 widget->core.window);
810 else
811 XUngrabButton(widget->core.screen->display,
812 keyOrButton, (unsigned int)modifiers,
813 widget->core.window);
814 }
815
816
817 /* Delete all entries which are encompassed by the specified grab. */
818 DeleteServerGrabFromList(isKeyboard ? &pwi->keyList : &pwi->ptrList,
819 &tempGrab);
820}
821
822void XtGrabKey (
823 Widget widget,
824 _XtKeyCodeunsigned int keycode,
825 Modifiers modifiers,
826 _XtBooleanint owner_events,
827 int pointer_mode,
828 int keyboard_mode)
829{
830 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
831
832 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
833 GrabKeyOrButton(widget, (KeyCode)keycode, modifiers, owner_events,
834 pointer_mode, keyboard_mode,
835 (Mask)0, (Window)None0L, (Cursor)None0L, KEYBOARD1);
836 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
837}
838
839void XtGrabButton(
840 Widget widget,
841 int button,
842 Modifiers modifiers,
843 _XtBooleanint owner_events,
844 unsigned int event_mask,
845 int pointer_mode,
846 int keyboard_mode,
847 Window confine_to,
848 Cursor cursor)
849{
850 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1
Within the expansion of the macro 'WIDGET_TO_APPCON':
a
Assuming pointer value is null
851
852 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
853 GrabKeyOrButton(widget, (KeyCode)button, modifiers, owner_events,
2
Passing null pointer value via 1st parameter 'widget'
3
Calling 'GrabKeyOrButton'
854 pointer_mode, keyboard_mode,
855 (Mask)event_mask, confine_to, cursor, POINTER0);
856 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
857}
858
859
860/*
861 * Routine used by an application to clear a passive grab for a key/modifier
862 * combination.
863 */
864
865void XtUngrabKey (
866 Widget widget,
867 _XtKeyCodeunsigned int keycode,
868 Modifiers modifiers)
869{
870 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
871
872 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
873 UngrabKeyOrButton(widget, (int)keycode, modifiers, KEYBOARD1);
874 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
875}
876
877void XtUngrabButton (
878 Widget widget,
879 unsigned int button,
880 Modifiers modifiers)
881{
882 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
883
884 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
885 UngrabKeyOrButton(widget, (KeyCode)button, modifiers, POINTER0);
886 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
887}
888
889/*
890 * Active grab of Device. clear any client side grabs so we dont lock
891 */
892static int GrabDevice (
893 Widget widget,
894 Boolean owner_events,
895 int pointer_mode,
896 int keyboard_mode,
897 Mask event_mask,
898 Window confine_to,
899 Cursor cursor,
900 Time time,
901 Boolean isKeyboard)
902{
903 XtPerDisplayInput pdi;
904 int returnVal;
905
906 XtCheckSubclass(widget, coreWidgetClass,
907 "in XtGrabKeyboard or XtGrabPointer");
908 if (!XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
)
909 return GrabNotViewable3;
910 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
911 pdi = _XtGetPerDisplayInput(XtDisplay(widget)(((widget)->core.screen)->display));
912 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
913 if (!isKeyboard)
914 returnVal = XGrabPointer(XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window),
915 owner_events, event_mask,
916 pointer_mode, keyboard_mode,
917 confine_to, cursor, time);
918 else
919 returnVal = XGrabKeyboard(XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window),
920 owner_events, pointer_mode,
921 keyboard_mode, time);
922
923 if (returnVal == GrabSuccess0) {
924 XtDevice device;
925
926 device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
927 /* fill in the server grab rec */
928 device->grab.widget = widget;
929 device->grab.modifiers = 0;
930 device->grab.keybut = 0;
931 device->grab.ownerEvents = owner_events;
932 device->grab.pointerMode = pointer_mode;
933 device->grab.keyboardMode = keyboard_mode;
934 device->grab.hasExt = False0;
935 device->grabType = XtActiveServerGrab;
936 pdi->activatingKey = (KeyCode)0;
937 }
938 return returnVal;
939}
940
941static void UngrabDevice(
942 Widget widget,
943 Time time,
944 Boolean isKeyboard)
945{
946 XtPerDisplayInput pdi;
947 XtDevice device;
948
949 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
950 pdi = _XtGetPerDisplayInput(XtDisplay(widget)(((widget)->core.screen)->display));
951 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
952 device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
953 XtCheckSubclass(widget, coreWidgetClass,
954 "in XtUngrabKeyboard or XtUngrabPointer");
955
956 if (device->grabType != XtNoServerGrab) {
957
958 if (device->grabType != XtPseudoPassiveServerGrab
959 && XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
) {
960 if (isKeyboard)
961 XUngrabKeyboard(XtDisplay(widget)(((widget)->core.screen)->display), time);
962 else
963 XUngrabPointer(XtDisplay(widget)(((widget)->core.screen)->display), time);
964 }
965 device->grabType = XtNoServerGrab;
966 pdi->activatingKey = (KeyCode)0;
967 }
968}
969
970
971/*
972 * Active grab of keyboard. clear any client side grabs so we dont lock
973 */
974int XtGrabKeyboard (
975 Widget widget,
976 _XtBooleanint owner_events,
977 int pointer_mode,
978 int keyboard_mode,
979 Time time)
980{
981 int retval;
982 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
983
984 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
985 retval = GrabDevice (widget, owner_events,
986 pointer_mode, keyboard_mode,
987 (Mask)0, (Window)None0L, (Cursor)None0L, time, KEYBOARD1);
988 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
989 return retval;
990}
991
992
993/*
994 * Ungrab the keyboard
995 */
996
997void XtUngrabKeyboard(
998 Widget widget,
999 Time time)
1000{
1001 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1002
1003 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1004 UngrabDevice(widget, time, KEYBOARD1);
1005 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1006}
1007
1008
1009
1010
1011/*
1012 * grab the pointer
1013 */
1014int XtGrabPointer (
1015 Widget widget,
1016 _XtBooleanint owner_events,
1017 unsigned int event_mask,
1018 int pointer_mode,
1019 int keyboard_mode,
1020 Window confine_to,
1021 Cursor cursor,
1022 Time time)
1023{
1024 int retval;
1025 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1026
1027 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1028 retval = GrabDevice (widget, owner_events,
1029 pointer_mode, keyboard_mode,
1030 (Mask)event_mask, confine_to,
1031 cursor, time, POINTER0);
1032 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1033 return retval;
1034}
1035
1036
1037/*
1038 * Ungrab the pointer
1039 */
1040
1041void XtUngrabPointer(
1042 Widget widget,
1043 Time time)
1044{
1045 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
1046
1047 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
1048 UngrabDevice(widget, time, POINTER0);
1049 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
1050}
1051
1052
1053void _XtRegisterPassiveGrabs (
1054 Widget widget)
1055{
1056 XtPerWidgetInput pwi = _XtGetPerWidgetInput (widget, FALSE0);
1057
1058 if (pwi != NULL((void*)0) && !pwi->realize_handler_added) {
1059 XtAddEventHandler(widget, StructureNotifyMask(1L<<17), FALSE0,
1060 RealizeHandler,
1061 (XtPointer)pwi);
1062 pwi->realize_handler_added = TRUE1;
1063 }
1064}