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