Bug Summary

File:Keyboard.c
Location:line 769, 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 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, 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
80#include "PassivGraI.h"
81#include "EventI.h"
82
83#define _GetWindowedAncestor(w)((((Object)(w))->object.widget_class->core_class.class_inited
& 0x04) ? w : _XtWindowedAncestor(w))
(XtIsWidget(w)(((Object)(w))->object.widget_class->core_class.class_inited
& 0x04)
? w : _XtWindowedAncestor(w))
84
85/* InActiveSubtree cache of the current focus source and its ancestors */
86static Widget *pathTrace = NULL((void*)0);
87static int pathTraceDepth = 0;
88static int pathTraceMax = 0;
89
90/* FindKeyDestination cache of focus destination and ancestors up to source */
91static Widget *pseudoTrace = NULL((void*)0);
92static int pseudoTraceDepth = 0;
93static int pseudoTraceMax = 0;
94
95void _XtClearAncestorCache(Widget widget)
96{
97 /* the caller must lock the process lock */
98 if (pathTraceDepth && pathTrace[0] == widget)
99 pathTraceDepth = 0;
100}
101
102static XtServerGrabPtr CheckServerGrabs(
103 XEvent *event,
104 Widget *trace,
105 Cardinal traceDepth)
106{
107 XtServerGrabPtr grab;
108 Cardinal i;
109
110 for (i = traceDepth; i > 0; i--)
111 {
112 if ((grab = _XtCheckServerGrabsOnWidget(event, trace[i-1], KEYBOARD1)))
113 return (grab);
114 }
115 return (XtServerGrabPtr)0;
116}
117
118static Boolean IsParent(Widget a, Widget b)
119{
120 for (b = XtParent(b)((b)->core.parent); b; b = XtParent(b)((b)->core.parent)) {
121 if (b == a) return TRUE1;
122 if (XtIsShell(b)(((Object)(b))->object.widget_class->core_class.class_inited
& 0x20)
) return FALSE0;
123 }
124 return FALSE0;
125}
126
127#define RelRtn(lca, type) {*relTypeRtn = type; return lca;}
128
129static Widget CommonAncestor(
130 register Widget a,
131 register Widget b,
132 XtGeneology * relTypeRtn)
133{
134 if (a == b)
135 {
136 RelRtn(a, XtMySelf3)
137 }
138 else if (IsParent(a, b))
139 {
140 RelRtn(a, XtMyAncestor0)
141 }
142 else if (IsParent(b, a))
143 {
144 RelRtn(b, XtMyDescendant1)
145 }
146 else
147 for (b = XtParent(b)((b)->core.parent);
148 b && !XtIsShell(b)(((Object)(b))->object.widget_class->core_class.class_inited
& 0x20)
;
149 b = XtParent(b)((b)->core.parent))
150 if (IsParent(b, a))
151 {
152 RelRtn(b, XtMyCousin2)
153 }
154 RelRtn(NULL((void*)0), XtUnrelated4)
155}
156#undef RelRtn
157
158
159
160
161
162static Widget _FindFocusWidget(
163 Widget widget,
164 Widget *trace,
165 int traceDepth,
166 Boolean activeCheck,
167 Boolean *isTarget)
168{
169 int src;
170 Widget dst;
171 XtPerWidgetInput pwi = NULL((void*)0);
172
173 /* For each ancestor, starting at the top, see if it's forwarded */
174
175
176 /* first check the trace list till done or we go to branch */
177 for (src = traceDepth-1, dst = widget; src > 0;)
178 {
179 if ((pwi = _XtGetPerWidgetInput(trace[src], FALSE0)))
180 {
181 if (pwi->focusKid)
182 {
183 dst = pwi->focusKid;
184 for (src--; src > 0 && trace[src] != dst; src--) {}
185 }
186 else dst = trace[--src];
187 }
188 else dst = trace[--src];
189 }
190
191 if (isTarget) {
192 if (pwi && pwi->focusKid == widget)
193 *isTarget = TRUE1;
194 else
195 *isTarget = FALSE0;
196 }
197
198 if (!activeCheck)
199 while (XtIsWidget(dst)(((Object)(dst))->object.widget_class->core_class.class_inited
& 0x04)
200 && (pwi = _XtGetPerWidgetInput(dst, FALSE0))
201 && pwi->focusKid)
202 dst = pwi->focusKid;
203
204 return dst;
205}
206
207
208static Widget FindFocusWidget(
209 Widget widget,
210 XtPerDisplayInput pdi)
211{
212 if (pdi->focusWidget)
213 return pdi->focusWidget;
214 else
215 return _FindFocusWidget(widget, pdi->trace, pdi->traceDepth, FALSE0, NULL((void*)0));
216}
217
218Widget XtGetKeyboardFocusWidget(Widget widget)
219{
220 XtPerDisplayInput pdi;
221 Widget retval;
222 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
223
224 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
225 pdi = _XtGetPerDisplayInput(XtDisplay(widget)(((widget)->core.screen)->display));
226 retval = FindFocusWidget(widget, pdi);
227 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
228 return retval;
229}
230
231static Boolean IsOutside(
232 XKeyEvent *e,
233 Widget w)
234{
235 Position left, right, top, bottom;
236
237 /*
238 * if the pointer is outside the shell or inside
239 * the window try to see if it would recieve the
240 * focus
241 */
242 XtTranslateCoords(w, 0, 0, &left, &top);
243 /* We need to take borders into consideration */
244 left = left - w->core.border_width;
245 top = top - w->core.border_width;
246 right = left + w->core.width + w->core.border_width;
247 bottom = top + w->core.height + w->core.border_width;
248
249 if (
250 (e->x_root < left) || (e->y_root < top) ||
251 (e->x_root > right) || (e->y_root > bottom))
252 return TRUE1;
253 else
254 return FALSE0;
255}
256
257static Widget FindKeyDestination(
258 Widget widget,
259 XKeyEvent *event,
260 XtServerGrabPtr prevGrab,
261 XtServerGrabType prevGrabType,
262 XtServerGrabPtr devGrab,
263 XtServerGrabType devGrabType,
264 XtPerDisplayInput pdi)
265{
266
267 Widget dspWidget;
268 Widget focusWidget;
269
270 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
271 dspWidget =
272 focusWidget =
273 pdi->focusWidget =
274 _GetWindowedAncestor(FindFocusWidget(widget, pdi))((((Object)(FindFocusWidget(widget, pdi)))->object.widget_class
->core_class.class_inited & 0x04) ? FindFocusWidget(widget
, pdi) : _XtWindowedAncestor(FindFocusWidget(widget, pdi)))
;
275
276
277 /*
278 * If a grab is active from a previous activation then dispatch
279 * based on owner_events ala protocol but with focus being
280 * determined by XtSetKeyboardFocus.
281 */
282 if (IsAnyGrab(prevGrabType)((prevGrabType == XtPassiveServerGrab) || (prevGrabType == XtActiveServerGrab
) || (prevGrabType == XtPseudoPassiveServerGrab))
)
283 {
284 if (prevGrab->ownerEvents)
285 dspWidget = focusWidget;
286 else
287 dspWidget = prevGrab->widget;
288 }
289 else
290 {
291 /*
292 * If the focus widget is the event widget or a descendant
293 * then we can avoid the rest of this. Else ugh...
294 */
295 if (focusWidget != widget)
296 {
297 XtGeneology ewRelFw; /* relationship of event widget to
298 focusWidget */
299 Widget lca;
300
301 lca = CommonAncestor(widget, focusWidget, &ewRelFw);
302
303 /*
304 * if the event widget is an ancestor of focus due to the pointer
305 * and/or the grab being in an ancestor and it's a passive grab
306 * send to grab widget.
307 * we are also dispatching to widget if ownerEvents and the event
308 * is outside the client
309 */
310 if ((ewRelFw == XtMyAncestor0) &&
311 (devGrabType == XtPassiveServerGrab))
312 {
313 if (IsOutside(event, widget) ||
314 event->type ==KeyPress2
315 )
316 dspWidget = devGrab->widget;
317 }
318 else
319 {
320 /*
321 * if the grab widget is not an ancestor of the focus
322 * release the grab in order to avoid locking. There
323 * is a possible case in that ownerEvents true will fall
324 * through and if synch is set and the event widget
325 * could turn it off we'll lock. check for it ? why not
326 */
327 if ((ewRelFw != XtMyAncestor0)
328 && (devGrabType == XtPassiveServerGrab)
329 && (!IsAnyGrab(prevGrabType)((prevGrabType == XtPassiveServerGrab) || (prevGrabType == XtActiveServerGrab
) || (prevGrabType == XtPseudoPassiveServerGrab))
)
330 )
331 {
332 XtUngrabKeyboard(devGrab->widget,
333 event->time);
334 devGrabType = XtNoServerGrab;
335 }
336 /*
337 * if there isn't a grab with then check
338 * for a logical grab that would have been activated
339 * if the server was using Xt focus instead of server
340 * focus
341 */
342 if (
343 (event->type != KeyPress2) ||
344 (event->keycode == 0) /* Xlib XIM composed input */
345 )
346 dspWidget = focusWidget;
347 else
348 {
349 XtServerGrabPtr grab;
350
351 if (!pseudoTraceDepth ||
352 !(focusWidget == pseudoTrace[0]) ||
353 !(lca == pseudoTrace[pseudoTraceDepth]))
354 {
355 /*
356 * fill ancestor list from lca
357 * (non-inclusive)to focusWidget by
358 * passing in lca as breakWidget
359 */
360 _XtFillAncestorList(&pseudoTrace,
361 &pseudoTraceMax,
362 &pseudoTraceDepth,
363 focusWidget,
364 lca);
365 /* ignore lca */
366 pseudoTraceDepth--;
367 }
368 if ((grab = CheckServerGrabs((XEvent*)event,
369 pseudoTrace,
370 pseudoTraceDepth)))
371 {
372 XtDevice device = &pdi->keyboard;
373
374 device->grabType = XtPseudoPassiveServerGrab;
375 pdi->activatingKey = event->keycode;
376 device->grab = *grab;
377
378 if (grab
379 )
380 dspWidget = grab->widget;
381 else
382 dspWidget = focusWidget;
383 }
384 }
385 }
386 }
387 }
388 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
389 return dspWidget;
390}
391
392Widget _XtProcessKeyboardEvent(
393 XKeyEvent *event,
394 Widget widget,
395 XtPerDisplayInput pdi)
396{
397 XtDevice device = &pdi->keyboard;
398 XtServerGrabPtr newGrab, devGrab = &device->grab;
399 XtServerGrabRec prevGrabRec;
400 XtServerGrabType prevGrabType = device->grabType;
401 Widget dspWidget = NULL((void*)0);
402 Boolean deactivateGrab = FALSE0;
403
404 prevGrabRec = *devGrab;
405
406 switch (event->type)
407 {
408 case KeyPress2:
409 {
410 if (event->keycode != 0 && /* Xlib XIM composed input */
411 !IsServerGrab(device->grabType)((device->grabType == XtPassiveServerGrab) || (device->
grabType == XtActiveServerGrab))
&&
412 (newGrab = CheckServerGrabs((XEvent*)event,
413 pdi->trace,
414 pdi->traceDepth)))
415 {
416 /*
417 * honor pseudo-grab from prior event by X
418 * unlocking keyboard. Not Xt Unlock !
419 */
420 if (IsPseudoGrab(prevGrabType)((prevGrabType == XtPseudoPassiveServerGrab)))
421 XUngrabKeyboard(XtDisplay(newGrab->widget)(((newGrab->widget)->core.screen)->display),
422 event->time);
423 else
424 {
425 /* Activate the grab */
426 device->grab = *newGrab;
427 pdi->activatingKey = event->keycode;
428 device->grabType = XtPassiveServerGrab;
429 }
430 }
431 }
432 break;
433
434 case KeyRelease3:
435 {
436 if (IsEitherPassiveGrab(device->grabType)((device->grabType == XtPassiveServerGrab) || (device->
grabType == XtPseudoPassiveServerGrab))
&&
437 (event->keycode == pdi->activatingKey))
438 deactivateGrab = TRUE1;
439 }
440 break;
441 }
442 dspWidget = FindKeyDestination(widget, event,
443 &prevGrabRec, prevGrabType,
444 devGrab, device->grabType,
445 pdi);
446 if (deactivateGrab)
447 {
448 /* Deactivate the grab */
449 device->grabType = XtNoServerGrab;
450 pdi->activatingKey = 0;
451 }
452 return dspWidget;
453}
454
455static Widget GetShell(Widget widget)
456{
457 Widget shell;
458
459 for (shell = widget;
460 shell && !XtIsShell(shell)(((Object)(shell))->object.widget_class->core_class.class_inited
& 0x20)
;
461 shell = XtParent(shell)((shell)->core.parent)){}
462 return shell;
463}
464
465
466/*
467 * Check that widget really has Xt focus due to it having recieved an
468 * event
469 */
470typedef enum {NotActive = 0, IsActive, IsTarget} ActiveType;
471static ActiveType InActiveSubtree(Widget widget)
472{
473 Boolean isTarget;
474 ActiveType retval;
475
476 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
477 if (!pathTraceDepth || widget != pathTrace[0]) {
478 _XtFillAncestorList(&pathTrace,
479 &pathTraceMax,
480 &pathTraceDepth,
481 widget,
482 NULL((void*)0));
483 }
484 if (widget == _FindFocusWidget(widget,
485 pathTrace,
486 pathTraceDepth,
487 TRUE1,
488 &isTarget))
489 retval = (isTarget ? IsTarget : IsActive);
490 else
491 retval = NotActive;
492 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
493 return retval;
494}
495
496
497
498
499/* ARGSUSED */
500void _XtHandleFocus(
501 Widget widget,
502 XtPointer client_data, /* child who wants focus */
503 XEvent *event,
504 Boolean *cont) /* unused */
505{
506 XtPerDisplayInput pdi = _XtGetPerDisplayInput(XtDisplay(widget)(((widget)->core.screen)->display));
507 XtPerWidgetInput pwi = (XtPerWidgetInput)client_data;
508 XtGeneology oldFocalPoint = pwi->focalPoint;
509 XtGeneology newFocalPoint = pwi->focalPoint;
510
511 switch( event->type ) {
512
513 case KeyPress2:
514 case KeyRelease3:
515 /*
516 * We're getting the keyevents used to guarantee propagating
517 * child interest ala ForwardEvent in R3
518 */
519 return;
520
521 case EnterNotify7:
522 case LeaveNotify8:
523
524 /*
525 * If operating in a focus driven model, then enter and
526 * leave events do not affect the keyboard focus.
527 */
528 if ((event->xcrossing.detail != NotifyInferior2)
529 && (event->xcrossing.focus))
530 {
531 switch (oldFocalPoint)
532 {
533 case XtMyAncestor0:
534 if (event->type == LeaveNotify8)
535 newFocalPoint = XtUnrelated4;
536 break;
537 case XtUnrelated4:
538 if (event->type == EnterNotify7)
539 newFocalPoint = XtMyAncestor0;
540 break;
541 case XtMySelf3:
542 break;
543 case XtMyDescendant1:
544 break;
545
546 }
547 }
548 break;
549 case FocusIn9:
550 switch (event->xfocus.detail)
551 {
552 case NotifyNonlinear3:
553 case NotifyAncestor0:
554 case NotifyInferior2:
555 newFocalPoint = XtMySelf3;
556 break;
557 case NotifyNonlinearVirtual4:
558 case NotifyVirtual1:
559 newFocalPoint = XtMyDescendant1;
560 break;
561 case NotifyPointer5:
562 newFocalPoint = XtMyAncestor0;
563 break;
564 }
565 break;
566 case FocusOut10:
567 switch (event->xfocus.detail)
568 {
569 case NotifyPointer5:
570 case NotifyNonlinear3:
571 case NotifyAncestor0:
572 case NotifyNonlinearVirtual4:
573 case NotifyVirtual1:
574 newFocalPoint = XtUnrelated4;
575 break;
576 case NotifyInferior2:
577 newFocalPoint = XtMyDescendant1;
578 return;
579 break;
580 }
581 break;
582 }
583
584 if (newFocalPoint != oldFocalPoint)
585 {
586 Boolean add;
587 Widget descendant = pwi->focusKid;
588
589 pwi->focalPoint = newFocalPoint;
590
591 if ((oldFocalPoint == XtUnrelated4) &&
592 InActiveSubtree(widget) != NotActive)
593 {
594 pdi->focusWidget = NULL((void*)0); /* invalidate the cache */
595 pwi->haveFocus = TRUE1;
596 add = TRUE1;
597 }
598 else if (newFocalPoint == XtUnrelated4)
599 {
600 pdi->focusWidget = NULL((void*)0); /* invalidate the cache */
601 pwi->haveFocus = FALSE0;
602 add = FALSE0;
603 }
604 else
605 return;
606
607 if (descendant)
608 {
609 if (add)
610 {
611 _XtSendFocusEvent(descendant, FocusIn9);
612 }
613 else
614 {
615 _XtSendFocusEvent(descendant, FocusOut10);
616 }
617 }
618 }
619}
620
621
622static void AddFocusHandler(
623 Widget widget,
624 Widget descendant,
625 XtPerWidgetInput pwi,
626 XtPerWidgetInput psi,
627 XtPerDisplayInput pdi,
628 EventMask oldEventMask)
629{
630 EventMask eventMask, targetEventMask;
631 Widget target;
632
633 /*
634 * widget must now select for key events if the descendant is
635 * interested in them.
636 *
637 * shell borders are not occluded by the child, they're occluded
638 * by reparenting window managers. !!!
639 */
640 target = descendant ? _GetWindowedAncestor(descendant)((((Object)(descendant))->object.widget_class->core_class
.class_inited & 0x04) ? descendant : _XtWindowedAncestor(
descendant))
: NULL((void*)0);
641 targetEventMask = XtBuildEventMask(target);
642 eventMask = targetEventMask & (KeyPressMask(1L<<0) | KeyReleaseMask(1L<<1));
643 eventMask |= FocusChangeMask(1L<<21) | EnterWindowMask(1L<<4) | LeaveWindowMask(1L<<5);
644
645 if (oldEventMask) {
646 oldEventMask &= KeyPressMask(1L<<0) | KeyReleaseMask(1L<<1);
647 oldEventMask |= FocusChangeMask(1L<<21) | EnterWindowMask(1L<<4) | LeaveWindowMask(1L<<5);
648
649 if (oldEventMask != eventMask)
650 XtRemoveEventHandler(widget, (oldEventMask & ~eventMask),
651 False0, _XtHandleFocus, (XtPointer)pwi);
652 }
653
654 if (oldEventMask != eventMask)
655 XtAddEventHandler(widget, eventMask, False0,
656 _XtHandleFocus, (XtPointer)pwi);
657
658 /* What follows is too much grief to go through if the
659 * target doesn't actually care about focus change events,
660 * so just invalidate the focus cache & refill it when
661 * the next input event actually arrives.
662 */
663
664 if (!(targetEventMask & FocusChangeMask(1L<<21))) {
665 pdi->focusWidget = NULL((void*)0);
666 return;
667 }
668
669 if (XtIsRealized(widget)((((((Object)(widget))->object.widget_class->core_class
.class_inited & 0x04) ? (widget) : _XtWindowedAncestor(widget
)) ->core.window) != 0L)
&& !pwi->haveFocus) {
670 if (psi->haveFocus) {
671 Window root, child;
672 int root_x, root_y, win_x, win_y;
673 int left, right, top, bottom;
674 unsigned int modMask;
675 ActiveType act;
676
677 /*
678 * If the shell has the focus but the source widget
679 * doesn't, it may only be because the source widget
680 * wasn't previously tracking focus or crossing events.
681 * If the target wants focus events, we have to
682 * now determine whether the source has the focus.
683 */
684
685 if ((act = InActiveSubtree(widget)) == IsTarget)
686 pwi->haveFocus = TRUE1;
687 else if (act == IsActive) {
688 /*
689 * An ancestor contains the focus, so if source
690 * contains the pointer, then source has the focus.
691 */
692
693 if (XQueryPointer(XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window),
694 &root, &child,
695 &root_x, &root_y, &win_x, &win_y, &modMask))
696 {
697 /* We need to take borders into consideration */
698 left = top = -((int) widget->core.border_width);
699 right = (int) (widget->core.width + (widget->core.border_width << 1));
700 bottom = (int) (widget->core.height + (widget->core.border_width << 1));
701
702 if (win_x >= left && win_x < right &&
703 win_y >= top && win_y < bottom)
704 pwi->haveFocus = TRUE1;
705 }
706 }
707 }
708 }
709 if (pwi->haveFocus) {
710 pdi->focusWidget = NULL((void*)0); /* invalidate the cache */
711 _XtSendFocusEvent(target, FocusIn9);
712 }
713}
714
715
716/* ARGSUSED */
717static void QueryEventMask(
718 Widget widget, /* child who gets focus */
719 XtPointer client_data, /* ancestor giving it */
720 XEvent *event,
721 Boolean *cont) /* unused */
722{
723 /* widget was once the target of an XtSetKeyboardFocus but
724 * was unrealized at the time. Make sure ancestor still wants
725 * focus set here then install the handler now that we know the
726 * complete event mask.
727 */
728 Widget ancestor = (Widget)client_data;
729 XtPerWidgetInput pwi = _XtGetPerWidgetInput(ancestor, FALSE0);
730
731 if (pwi) {
732 Widget target = pwi->queryEventDescendant;
733
734 /* use of 'target' is non-standard hackery;
735 allows focus to non-widget */
736 if ( pwi->focusKid == target ) {
737 AddFocusHandler(ancestor, target, pwi,
738 _XtGetPerWidgetInput(GetShell(ancestor), TRUE1),
739 _XtGetPerDisplayInput(XtDisplay(ancestor)(((ancestor)->core.screen)->display)),
740 (EventMask)0);
741 }
742 XtRemoveEventHandler(widget, XtAllEvents((EventMask) -1L), True1,
743 QueryEventMask, client_data);
744 pwi->map_handler_added = FALSE0;
745 }
746}
747
748
749/* ARGSUSED */
750static void FocusDestroyCallback(
751 Widget widget,
752 XtPointer closure, /* Widget */
753 XtPointer call_data)
754{
755 XtSetKeyboardFocus((Widget)closure, NULL((void*)0));
756}
757
758void XtSetKeyboardFocus(
759 Widget widget,
760 Widget descendant)
761{
762 XtPerDisplayInput pdi;
763 XtPerWidgetInput pwi;
764 Widget oldDesc, oldTarget, target, hookobj;
765 WIDGET_TO_APPCON(widget)XtAppContext app = (widget && _XtProcessLock ? XtWidgetToApplicationContext
(widget) : ((void*)0))
;
766
767 LOCK_APP(app)if(app && app->lock)(*app->lock)(app);
768 LOCK_PROCESSif(_XtProcessLock)(*_XtProcessLock)();
1
Within the expansion of the macro 'LOCK_PROCESS':
a
Assuming '_XtProcessLock' is null
769 pdi = _XtGetPerDisplayInput(XtDisplay(widget)(((widget)->core.screen)->display));
2
Within the expansion of the macro 'XtDisplay':
a
Dereference of null pointer
770 pwi = _XtGetPerWidgetInput(widget, TRUE1);
771 oldDesc = pwi->focusKid;
772
773 if (descendant == widget) descendant = (Widget)None0L;
774
775 target = descendant ? _GetWindowedAncestor(descendant)((((Object)(descendant))->object.widget_class->core_class
.class_inited & 0x04) ? descendant : _XtWindowedAncestor(
descendant))
: NULL((void*)0);
776 oldTarget = oldDesc ? _GetWindowedAncestor(oldDesc)((((Object)(oldDesc))->object.widget_class->core_class.
class_inited & 0x04) ? oldDesc : _XtWindowedAncestor(oldDesc
))
: NULL((void*)0);
777
778 if (descendant != oldDesc) {
779
780 /* update the forward path */
781 pwi->focusKid = descendant;
782
783
784 /* all the rest handles focus ins and focus outs and misc gunk */
785
786 if (oldDesc) {
787 /* invalidate FindKeyDestination's ancestor list */
788 if (pseudoTraceDepth && oldTarget == pseudoTrace[0])
789 pseudoTraceDepth = 0;
790
791 XtRemoveCallback(oldDesc, XtNdestroyCallback((char*)&XtStrings[169]),
792 FocusDestroyCallback, (XtPointer)widget);
793
794 if (!oldTarget->core.being_destroyed) {
795 if (pwi->map_handler_added) {
796 XtRemoveEventHandler(oldTarget, XtAllEvents((EventMask) -1L), True1,
797 QueryEventMask, (XtPointer)widget);
798 pwi->map_handler_added = FALSE0;
799 }
800 if (pwi->haveFocus) {
801 _XtSendFocusEvent( oldTarget, FocusOut10);
802 }
803 }
804 else if (pwi->map_handler_added) {
805 pwi->map_handler_added = FALSE0;
806 }
807
808 if (pwi->haveFocus)
809 pdi->focusWidget = NULL((void*)0); /* invalidate cache */
810
811 /*
812 * If there was a forward path then remove the handler if
813 * the path is being set to null and it isn't a shell.
814 * shells always have a handler for tracking focus for the
815 * hierarchy.
816 *
817 * Keep the pwi record on the assumption that the client
818 * will continue to dynamically assign focus for this widget.
819 */
820 if (!XtIsShell(widget)(((Object)(widget))->object.widget_class->core_class.class_inited
& 0x20)
&& !descendant) {
821 XtRemoveEventHandler(widget, XtAllEvents((EventMask) -1L), True1,
822 _XtHandleFocus, (XtPointer)pwi);
823 pwi->haveFocus = FALSE0;
824 }
825 }
826
827 if (descendant) {
828 Widget shell = GetShell(widget);
829 XtPerWidgetInput psi = _XtGetPerWidgetInput(shell, TRUE1);
830 XtAddCallback (descendant, XtNdestroyCallback((char*)&XtStrings[169]),
831 FocusDestroyCallback, (XtPointer) widget);
832
833 AddFocusHandler(widget, descendant, pwi, psi, pdi,
834 oldTarget ? XtBuildEventMask(oldTarget) : 0);
835
836 if (widget != shell)
837 XtAddEventHandler(
838 shell,
839 FocusChangeMask(1L<<21) | EnterWindowMask(1L<<4) | LeaveWindowMask(1L<<5),
840 False0,
841 _XtHandleFocus,
842 (XtPointer)psi
843 );
844
845 if (! XtIsRealized(target)((((((Object)(target))->object.widget_class->core_class
.class_inited & 0x04) ? (target) : _XtWindowedAncestor(target
)) ->core.window) != 0L)
) {
846 XtAddEventHandler(target, (EventMask)StructureNotifyMask(1L<<17),
847 False0, QueryEventMask, (XtPointer)widget);
848 pwi->map_handler_added = TRUE1;
849 pwi->queryEventDescendant = descendant;
850 }
851 }
852 }
853 hookobj = XtHooksOfDisplay(XtDisplay(widget)(((widget)->core.screen)->display));
854 if (XtHasCallbacks(hookobj, XtNchangeHook((char*)&XtStrings[2061])) == XtCallbackHasSome) {
855 XtChangeHookDataRec call_data;
856
857 call_data.type = XtHsetKeyboardFocus((char*)&XtStrings[2469]);
858 call_data.widget = widget;
859 call_data.event_data = (XtPointer) descendant;
860 XtCallCallbackList(hookobj,
861 ((HookObject)hookobj)->hooks.changehook_callbacks,
862 (XtPointer)&call_data);
863 }
864 UNLOCK_PROCESSif(_XtProcessUnlock)(*_XtProcessUnlock)();
865 UNLOCK_APP(app)if(app && app->unlock)(*app->unlock)(app);
866}