1 /* Copyright (C) 1992-1998 The Geometry Center
2  * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3  *
4  * This file is part of Geomview.
5  *
6  * Geomview is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Geomview is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Geomview; see the file COPYING.  If not, write
18  * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
19  * USA, or visit http://www.gnu.org.
20  */
21 
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25 
26 #if 0
27 static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\
28 Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips";
29 #endif
30 
31 #include "../common/drawer.h"
32 #include "../common/ui.h"
33 #include "../common/comm.h"
34 #include "../common/space.h"
35 #include "../common/event.h"
36 #include "../common/motion.h"
37 #include "../common/worldio.h"
38 #include "../common/lang.h"
39 #include "clang.h"
40 
41 #include <string.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <signal.h>
45 #include <sys/types.h>
46 #include <sys/time.h>
47 
48 #include <X11/X.h>
49 #include <X11/keysym.h>
50 #include "mibload.h"
51 #include "gvui.h"
52 
53 #if D1_DEBUG
54 #define GV_RAWEVENT(dev, val, x, y, t) \
55    printf("calling gv_rawevent(dev=%3d, val=%3d, x=%4d, y=%4d, t=%1ld)\n", dev, val, x, y, t); \
56    gv_rawevent( dev, val, x, y, t)
57 #else
58 #define GV_RAWEVENT(dev, val, x, y, t) \
59    gv_rawevent( dev, val, x, y, t)
60 #endif
61 
62 
63 /* gvevent.c global vars */
64 /*****************************************************************************/
65 
66 #define ESC	'\033'
67 
68 extern Display *dpy;
69 static void perftick();
70 static struct perf {            /* Performance metering */
71     int interval;               /* Interval between auto-reports */
72     int mindt, maxdt, meandt;   /* Integer milliseconds */
73     int cycles;                 /* # cycles where we actually did something */
74     struct timeval then;
75 } perf;
76 
77 static int lastx;
78 static int lasty;
79 static int dragx;
80 static int dragy;
81 static int nseen;
82 static int dragstop, dragging, deldrag, numdrags;
83 int    justdragged;
84 
85 static Time lastt;
86 Time last_event_time;
87 static Event  gev; /* geomview event structure */
88 
89 /*****************************************************************************/
90 
91 #if D1_DEBUG
print_event(char * s,Event * e)92 void print_event(char *s, Event *e) {
93   printf("%s: event(dev=%3d, val=%3d, x=%4d, y=%4d, t=%1ld)\n",
94 	 s, e->dev, e->val, e->x, e->y, e->t);
95 }
96 #endif
97 
process_events(int queuefd)98 static void process_events(int queuefd)
99 {
100   struct timeval await;
101 #define	BRIEF	0.1
102   static struct timeval brief = { 0, 100000 };
103   float timelimit;
104   fd_set thesefds;
105   XtInputMask xim;
106 
107   if (queuefd < 0) {
108     queuefd = ConnectionNumber(dpy);
109   }
110 
111   if(drawerstate.pause) {
112     if(!dragging && !drawer_moving())
113       select(0, NULL, NULL, NULL, &brief);
114     nseen = 0;
115   } else {
116     int nwatch = 0;
117 
118     timelimit = PoolInputFDs( &thesefds, &nwatch );
119 
120     if(timelimit > 0 && drawer_moving())
121       timelimit = 0;	/* "Is anything moving?" */
122 
123     if (queuefd >= 0 )
124       FD_SET(queuefd, &thesefds);
125 
126     if(queuefd >= nwatch)
127       nwatch = queuefd+1;
128 
129     if(timelimit > BRIEF) timelimit = BRIEF;
130 
131     await.tv_sec = floor(timelimit);
132     await.tv_usec = 1000000*(timelimit - await.tv_sec);
133 
134     nseen = select(nwatch, &thesefds, NULL, NULL, &await);
135   }
136 
137   gettimeofday(&perf.then, NULL);
138 
139   if(!drawerstate.pause)
140     PoolInAll( &thesefds, &nseen );
141 
142   ui_update();
143 
144   justdragged = 0;
145   deldrag = gev.t;
146 
147 
148   while ((xim = XtAppPending(App)) != 0) {
149     XtAppProcessEvent(App, xim);
150   }
151 
152   if (dragging && !justdragged && !dragstop) {
153     D1PRINT(("gvevent at 1\n"));
154     GV_RAWEVENT( gev.dev, -1, gev.x, gev.y, gev.t);
155     dragstop = 1;
156   }
157 
158   if (dragging) {
159     deldrag = gev.t - deldrag;
160   } else {
161     deldrag = 0;
162   }
163 
164   XSync(dpy, False);
165 
166   gv_update_draw( ALLCAMS, 0.001 * (float)deldrag );
167   mg_textureclock();
168 
169   if(perf.interval > 0)
170     perftick();
171 
172   numdrags = 0;
173 }
174 
main_loop()175 void main_loop()
176 {
177   int queuefd;
178 
179   queuefd = ConnectionNumber(dpy);
180   dragging = 0;
181   dragstop = 1;
182   justdragged = 0;
183   deldrag = 0;
184   numdrags = 0;
185 
186   while (1) {
187     process_events(queuefd);
188   }
189 }
190 
191 LDEFINE(processevents, LVOID,
192 	"(process-events)\n"
193 	"Pass control back to the event loop of Geomview, then continue "
194 	"evaluating the current command-script.")
195 {
196   Lake *caller;
197 
198   LDECLARE(("process-events", LBEGIN,
199 	    LLAKE, &caller,
200 	    LEND));
201 
202   PoolDetach(POOL(caller));
203   do {
204     process_events(-1);
205   } while (PoolASleep(POOL(caller)));
206   PoolReattach(POOL(caller));
207 
208   return Lt;
209 }
210 
211 /*****************************************************************************/
212 
213 static void
perftick()214 perftick()
215 {
216     int dt;
217     struct timeval now;
218     gettimeofday(&now, NULL);
219     dt = (now.tv_sec - perf.then.tv_sec)*1000 +
220          (now.tv_usec - perf.then.tv_usec)/1000;
221     if(dt > 0) {
222         if(dt < perf.mindt) perf.mindt = dt;
223         if(dt > perf.maxdt) perf.maxdt = dt;
224         perf.meandt += dt;
225         if(++perf.cycles == perf.interval)
226             timing(perf.interval);
227     }
228 }
229 
230 /*****************************************************************************/
231 
232 void
timing(int interval)233 timing(int interval)
234 {
235     if(perf.cycles > 0) {
236         printf("%d..%d ms/cycle, mean %d ms over %d cycles\n",
237                 perf.mindt, perf.maxdt,
238                 perf.cycles ? perf.meandt/perf.cycles : 0,
239                 perf.cycles);
240         fflush(stdout);
241     }
242     perf.mindt = 9999999, perf.maxdt = -1, perf.meandt = perf.cycles = 0;
243     perf.interval = interval;
244 }
245 
246 /*****************************************************************************/
cam_input(Widget w,XtPointer data,XmDrawingAreaCallbackStruct * cbs)247 void cam_input(Widget w, XtPointer data, XmDrawingAreaCallbackStruct *cbs)
248 {
249   Boolean junk;
250 D1PRINT(("cam_input\n"));
251   panel_input(w, data, cbs->event, &junk);
252 }
253 
key_action(Widget w,XEvent * event,String * argv,Cardinal * argcp)254 void key_action(Widget w, XEvent *event, String *argv, Cardinal *argcp)
255 {
256   Boolean junk;
257 D1PRINT(("key_action\n"));
258   panel_input(w, NULL, event, &junk);
259 }
260 
panel_input(Widget w,XtPointer data,XEvent * event,Boolean * cont)261 void panel_input(Widget w, XtPointer data, XEvent *event, Boolean *cont)
262 {
263   char          str[1];
264   KeySym	keysym;
265   int		newstate, nc;
266 
267   switch (event->type)
268   {
269     case UnmapNotify:		/* Window iconified or otherwise temporarily gone */
270 D1PRINT(("panel_input: case UnmapNotify\n"));
271       gv_freeze( (int)(long)data, 1 );	/* Hard-frozen; prevent gv_redraw from working until we say so */
272       break;
273 
274     case MapNotify:
275 D1PRINT(("panel_input: case MapNotify\n"));
276       gv_freeze( (int)(long)data, 0 );	/* Permit thawing. */
277       gv_redraw( (int)(long)data );		/* Thaw it now, in case Expose arrived before MapNotify */
278       break;
279 
280     case MotionNotify:
281 D1PRINT(("panel_input: case MotionNotify\n"));
282       last_event_time = event->xmotion.time;
283       cam_mouse(w, data, &event->xmotion, cont);
284       return;
285 
286     case ButtonPress:
287     case ButtonRelease:
288 D1PRINT(("panel_input: case ButtonPress/Release\n"));
289       newstate = (event->type == ButtonPress);
290 
291       button.left = ((event->xbutton.state & Button1Mask) ? 1 : 0);
292       button.middle = ((event->xbutton.state & Button2Mask) ? 1 : 0);
293       button.right = ((event->xbutton.state & Button3Mask) ? 1 : 0);
294       button.shift = ((event->xbutton.state & ShiftMask) ? 1 : 0);
295       button.ctrl = ((event->xbutton.state & ControlMask) ? 1 : 0);
296       dragging = newstate;
297 
298       lastt = last_event_time = event->xbutton.time;
299 D1PRINT(("gvevent: at 1.5, event->xbutton.time = %1ld\n", event->xbutton.time));
300       dragx = event->xbutton.x_root;
301       dragy = YScrnSize - event->xbutton.y_root;
302 
303       if (dragstop && !newstate) {
304 D1PRINT(("gvevent at 2\n"));
305         GV_RAWEVENT( gev.dev, -1, dragx, dragy, lastt);
306       }
307 
308       switch (event->xbutton.button) {
309 	 case 1:
310            gev.dev = ELEFTMOUSE;
311            button.left = newstate;
312 	   break;
313 	 case 2:
314            gev.dev = EMIDDLEMOUSE;
315            button.middle = newstate;
316 	   break;
317 	 case 3:
318            gev.dev = ERIGHTMOUSE;
319            button.right = newstate;
320 	   break;
321       }
322 
323       if(gev.dev == ELEFTMOUSE && (event->xbutton.state & Mod1Mask)) {
324 	gev.dev = EMIDDLEMOUSE;
325 	button.middle = button.left;
326 	button.left = 0;
327       }
328 
329       gev.x = dragx; gev.y = dragy; gev.t = lastt;
330       deldrag = gev.t;
331 D1PRINT(("gvevent at 3\n"));
332       GV_RAWEVENT( gev.dev, newstate, gev.x, gev.y, gev.t);
333       dragstop = 1;
334       break;
335 
336     case KeyPress:
337 D1PRINT(("panel_input: case KeyPress\n"));
338       nc = XLookupString((XKeyEvent *) event, str, 1, &keysym, NULL);
339       last_event_time = event->xkey.time;
340 
341       if ((int)keysym == (int)'Q')
342 	str[0] = ESC;
343 
344       if (keysym == XK_Escape)
345 	str[0] = ESC;
346 
347       if (nc > 0) {
348 	  gev.dev = str[0];
349 	  gev.x = event->xkey.x_root;
350 	  gev.y = YScrnSize - event->xkey.y_root;
351 	  gev.t = event->xkey.time;
352 D1PRINT(("gvevent at 4\n"));
353           GV_RAWEVENT(str[0], 1, gev.x, gev.y, gev.t);
354       }
355 
356       break;
357 
358     default:
359       break;
360   }
361 
362 }
363 
364 /*****************************************************************************/
365 
cam_mouse(Widget w,XtPointer data,XPointerMovedEvent * event,Boolean * cont)366 void cam_mouse(Widget w, XtPointer data, XPointerMovedEvent *event,
367 	Boolean *cont)
368 {
369   static int lasthere = 0;
370   dragging = 1;
371   dragstop = 0;
372   justdragged = 1;
373 
374   numdrags++;
375   if (numdrags > 2)
376     return;
377 
378   gev.x = event->x_root; gev.y = YScrnSize - event->y_root; gev.t = event->time;
379 
380   PRINT_EVENT(("cam_mouse", &gev));
381 
382   if ((int)(gev.t - lastt) > uistate.cursor_still)
383   {
384     if (abs(gev.x - lastx) < uistate.cursor_twitch &&
385 	abs(gev.y - lasty) < uistate.cursor_twitch)
386       {
387 	gev.x = dragx;
388 	gev.y = dragy;
389       }
390     lastx = gev.x;
391     lasty = gev.y;
392     lastt = gev.t;
393   }
394   dragx = gev.x;
395   dragy = gev.y;
396   if (lasthere != (int)gev.t) {
397 D1PRINT(("cam_mouse: at 1\n"));
398     GV_RAWEVENT( gev.dev, -1, gev.x, gev.y, gev.t);
399   } else {
400 D1PRINT(("cam_mouse: at 2\n"));
401     GV_RAWEVENT( gev.dev, -1, gev.x, gev.y, gev.t+1);
402     dragstop = 1;
403   }
404 
405   lasthere = gev.t;
406 }
407 
408 /*****************************************************************************/
409 
cam_mousecross(Widget w,XtPointer data,XEnterWindowEvent * event,Boolean * cont)410 void cam_mousecross(Widget w, XtPointer data, XEnterWindowEvent *event,
411 		    Boolean *cont)
412 {
413   if (!uistate.cam_wm_focus) {
414     int id = (int)(long)data;
415 
416     gv_winenter(id);
417   }
418 }
419 
420 /*****************************************************************************/
421 
cam_focus(Widget w,XtPointer data,XFocusChangeEvent * event,Boolean * cont)422 void cam_focus(Widget w, XtPointer data, XFocusChangeEvent *event,
423 	       Boolean *cont)
424 {
425   if (uistate.cam_wm_focus && event->type == FocusIn) {
426     int id = (int)(long)data;
427 
428     gv_winenter(id);
429   }
430 }
431 
432 /*
433  * Local Variables: ***
434  * c-basic-offset: 2 ***
435  * End: ***
436  */
437