|
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 |
}
|