Blame lib/Xm/TrackLoc.c

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