File: TrackLoc.c

package info (click to toggle)
motif 2.3.8-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 36,432 kB
  • sloc: ansic: 452,643; sh: 4,613; makefile: 2,030; yacc: 1,604; lex: 352; cpp: 348
file content (248 lines) | stat: -rw-r--r-- 7,198 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/* 
 * 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 <config.h>
#endif


#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$XConsortium: TrackLoc.c /main/12 1995/10/25 20:24:41 cde-sun $"
#endif
#endif

#include <Xm/XmP.h>
#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);
}