/* * Motif * * Copyright (c) 1987-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif #ifdef REV_INFO #ifndef lint static char rcsid[] = "$XConsortium: TrackLoc.c /main/12 1995/10/25 20:24:41 cde-sun $" #endif #endif /* * (c) Copyright 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */ #include #include "XmI.h" #include "MessagesI.h" #define GRABPTRERROR _XmMMsgCascadeB_0003 /******** Static Function Declarations ********/ static Widget _XmInputInWidget( Widget w, #if NeedWidePrototypes int x, int y) ; #else Position x, Position y) ; #endif /* NeedWidePrototypes */ /******** End Static Function Declarations ********/ /******************************************************/ /* copy from XmeGadgetAtPoint, buts works for widget too, only used in this module so far, so let it static */ static Widget _XmInputInWidget( Widget w, #if NeedWidePrototypes int x, int y) #else Position x, Position y) #endif /* NeedWidePrototypes */ { int i; Widget child; CompositeWidget cw = (CompositeWidget) w; /* loop over the child list to find if there is one at x,y */ /* well, overlapping won't really work, since I have no standard way to check visibility */ for (i = 0; i < cw->composite.num_children; i++) { child = cw->composite.children[i]; if (XtIsManaged (child)) { if (x >= child->core.x && y >= child->core.y && x < child->core.x + child->core.width && y < child->core.y + child->core.height) return (child); } } return (NULL); } /* new tracking locate function that returns the event that trigerred the return + this function uses XNextEvent instead of just XMaskEvent which was only eating some events and thus causing problem when back to the application */ Widget XmTrackingEvent( Widget widget, Cursor cursor, #if NeedWidePrototypes int confineTo, #else Boolean confineTo, #endif /* NeedWidePrototypes */ XEvent * pev) { Window w, confine_to = None; Time lastTime; Widget child; Boolean key_has_been_pressed= False; Widget target ; Position x, y ; XtAppContext app; if (widget == NULL) return(NULL); app = XtWidgetToApplicationContext(widget); _XmAppLock(app); w = XtWindowOfObject(widget); if (confineTo) confine_to = w; lastTime = XtLastTimestampProcessed(XtDisplay(widget)); XmUpdateDisplay(widget); if (XtGrabPointer(widget, True, /* The following truncation of masks is due to a bug in the Xt API.*/ (unsigned int) (ButtonPressMask | ButtonReleaseMask), GrabModeAsync, GrabModeAsync, confine_to, cursor, lastTime) != GrabSuccess) { XmeWarning(widget, GRABPTRERROR); _XmAppUnlock(app); return NULL ; } while (True) { /* eat all events, not just button's */ XNextEvent(XtDisplay(widget), pev); /* track only button1release and non first keyrelease */ if (((pev->type == ButtonRelease) && (pev->xbutton.button & Button1)) || ((pev->type == KeyRelease) && key_has_been_pressed)) { if ((!confineTo) && (pev->xbutton.window == w)) { /* this is the case where we are not confine, so the user can click outside the window, but we want to return NULL */ if ((pev->xbutton.x < 0) || (pev->xbutton.y < 0) || (pev->xbutton.x > widget->core.width) || (pev->xbutton.y > widget->core.height)) { XtUngrabPointer(widget, lastTime); _XmAppUnlock(app); return(NULL); } } target = XtWindowToWidget(pev->xbutton.display, pev->xbutton.window); /* New algorithm that solves the problem of mouse insensitive widgets: ( i.e you can't get help on Label.) When we get the Btn1Up event with the window in which the event ocurred, and convert it to a widget. If that widget is a primitive, return it. Otherwise, it is a composite or a shell, and we do the following: Walk down the child list (for gadgets AND WIDGETS), looking for one which contains the x,y. If none is found, return the manager itself, If a primitive or gadget is found, return the object found. If a manager is found, execute the above algorithm recursively with that manager. */ if (target) { /* do not change the original pev coordinates */ x = pev->xbutton.x ; y = pev->xbutton.y ; /* do not enter the loop for primitive */ while (XtIsComposite(target) || XtIsShell(target)) { if ((child = _XmInputInWidget(target, x,y)) != NULL) { target = child; /* if a gadget or a primitive is found, return */ if (!XtIsComposite(child)) break ; /* otherwise, loop */ x = x - XtX(child) ; y = y - XtY(child) ; } else break ; /* no child found at this place: return the manager */ } } break ; } else if (pev->type == KeyPress) key_has_been_pressed = True ; /* to avoid exiting on the first keyreleased coming from the keypress activatation of the function itself */ } XtUngrabPointer(widget, lastTime); _XmAppUnlock(app); return(target); } /* reimplementation of the old function using the new one and a dummy event */ Widget XmTrackingLocate( Widget widget, Cursor cursor, #if NeedWidePrototypes int confineTo ) #else Boolean confineTo ) #endif /* NeedWidePrototypes */ { XEvent ev ; return XmTrackingEvent(widget, cursor, confineTo, &ev); } /*********************************************************************** * Certain widgets, such as those in a menu, would like the application * to look non-scraged (i.e. all exposure events have been processed) * before invoking a callback which takes a long time to do its thing. * This function grabs all exposure events off the queue, and processes * them. ***********************************************************************/ void XmUpdateDisplay( Widget w ) { XEvent event; Display * display = XtDisplay(w); _XmWidgetToAppContext(w); _XmAppLock(app); XSync (display, 0); while (XCheckMaskEvent(display, ExposureMask, &event)) XtDispatchEvent(&event); _XmAppUnlock(app); }