1 /**
2  ** xwininp.c ---- mouse and keyboard interface for X Windows
3  **
4  ** Author:     Ulrich Leodolter
5  ** E-mail:     ulrich@lab1.psy.univie.ac.at
6  ** Date:       Thu Sep 28 20:22:16 1995
7  ** Comment:    Implements the same GRX functions as dosinput.c
8  ** RCSId:      $Id: xwininput.c 1.2 1995/11/19 19:32:30 ulrich Exp $
9  **
10  ** This file is part of the GRX graphics library.
11  **
12  ** The GRX graphics library is free software; you can redistribute it
13  ** and/or modify it under some conditions; see the "copying.grx" file
14  ** for details.
15  **
16  ** This library is distributed in the hope that it will be useful,
17  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  **
20  ** Small changes by Dimitar Zhekov to work in fullscreen mode (DGA2).
21  **
22  ** Contributions by:
23  ** 070505 M.Alvarez, Using a Pixmap for BackingStore.
24  **
25  **/
26 
27 #include <stdlib.h>
28 #include <sys/time.h>   /* for select() */
29 
30 #include "libgrx.h"
31 #include "libxwin.h"
32 #include <X11/keysym.h>
33 #include "grxkeys.h"
34 #include "allocate.h"
35 #include "arith.h"
36 #include "memcopy.h"
37 #include "memfill.h"
38 #include "mouse/input.h"
39 
40 #ifdef _AIX
41 #include <sys/select.h>
42 #endif
43 
44 static int  kbd_enabled = TRUE;
45 static int  kbd_lastmod = 0;
46 static int  mou_enabled = TRUE;
47 static int  mou_buttons = 0;
48 static Time MouseMoveTime = 0;
49 static Time evt_lasttime;
50 static int  evt_lasttime_ok = FALSE;
51 
52 #if 0
53 long volatile   _XGrTickValue = -1;
54 static void     _XGrTickHandler (int signum)
55 {
56   signal (signum, _XGrTickHandler);
57   _XGrTickValue++;
58 }
59 #endif
60 
uninit(void)61 static void uninit(void)
62 {
63 	if(MOUINFO->msstatus > 1) MOUINFO->msstatus = 1;
64 }
65 
GrMouseDetect(void)66 int GrMouseDetect(void)
67 {
68 	if(MOUINFO->msstatus == 0) {
69 	  if (_XGrDisplay) MOUINFO->msstatus = 1; /* present, but not initted */
70 	}
71 	return((MOUINFO->msstatus > 0) ? TRUE : FALSE);
72 }
73 
GrMouseInitN(int queue_size)74 void GrMouseInitN(int queue_size)
75 {
76 	uninit();
77 	queue_size = umax(4,umin(256,queue_size));
78 	init_queue(queue_size);
79 	if(GrMouseDetect()) {
80 	    GrMouseSetSpeed(1,1);
81 	    GrMouseSetAccel(100,1);
82 	    GrMouseSetLimits(0,0,SCRN->gc_xmax,SCRN->gc_ymax);
83 	    GrMouseWarp((SCRN->gc_xmax >> 1),(SCRN->gc_ymax >> 1));
84 	    _GrInitMouseCursor();
85 	    MOUINFO->msstatus = 2;
86 	    mou_buttons = 0;
87 	    /*
88 	     * Define an invisible X cursor for _XGrWindow
89 	     */
90 	    if(_XGrWindowedMode) {
91 	      static char cbits[8] = { 0,0,0,0,0,0,0,0, };
92 	      Pixmap csource, cmask;
93 	      XColor cfore, cback;
94 	      Cursor curs;
95 
96 	      csource = cmask = XCreateBitmapFromData (_XGrDisplay,
97 						       _XGrWindow,
98 						       cbits,
99 						       8,
100 						       8
101 						       );
102 	      cfore.red = cfore.green = cfore.blue = 0;
103 	      cback.red = cback.green = cback.blue = 0;
104 	      curs = XCreatePixmapCursor (_XGrDisplay,
105 					  csource,
106 					  cmask,
107 					  &cfore,
108 					  &cback,
109 					  0,
110 					  0
111 					  );
112 	      XDefineCursor (_XGrDisplay, _XGrWindow, curs);
113 	    }
114 	}
115 	GrMouseEventEnable(TRUE,TRUE);
116 	evt_lasttime_ok = FALSE;
117 	MouseMoveTime = 0;
118 	MOUINFO->uninit = uninit;
119 }
120 
GrMouseSetSpeed(int spmult,int spdiv)121 void GrMouseSetSpeed(int spmult,int spdiv)
122 {
123 	MOUINFO->spmult = umin(16,umax(1,spmult));
124 	MOUINFO->spdiv  = umin(16,umax(1,spdiv));
125 }
126 
GrMouseSetAccel(int thresh,int accel)127 void GrMouseSetAccel(int thresh,int accel)
128 {
129 	MOUINFO->thresh = umin(64,umax(1,thresh));
130 	MOUINFO->accel  = umin(16,umax(1,accel));
131 }
132 
GrMouseSetLimits(int x1,int y1,int x2,int y2)133 void GrMouseSetLimits(int x1,int y1,int x2,int y2)
134 {
135 	isort(x1,x2);
136 	isort(y1,y2);
137 	MOUINFO->xmin = imax(0,imin(x1,SCRN->gc_xmax));
138 	MOUINFO->ymin = imax(0,imin(y1,SCRN->gc_ymax));
139 	MOUINFO->xmax = imax(0,imin(x2,SCRN->gc_xmax));
140 	MOUINFO->ymax = imax(0,imin(y2,SCRN->gc_ymax));
141 }
142 
GrMouseWarp(int x,int y)143 void GrMouseWarp(int x,int y)
144 {
145     MOUINFO->xpos = imax(MOUINFO->xmin,imin(MOUINFO->xmax,x));
146     MOUINFO->ypos = imax(MOUINFO->ymin,imin(MOUINFO->ymax,y));
147     if (_XGrDisplay) {
148 	GrMouseUpdateCursor();
149 	/*
150 	 * Move the X cursor only if inside _XGrWindow
151 	 */
152 	XWarpPointer (_XGrDisplay,
153 		      _XGrWindow,
154 		      _XGrWindow,
155 		      0,
156 		      0,
157 		      GrScreenX(),
158 		      GrScreenY(),
159 		      MOUINFO->xpos,
160 		      MOUINFO->ypos);
161     }
162 }
163 
GrMouseEventEnable(int enable_kb,int enable_ms)164 void GrMouseEventEnable(int enable_kb,int enable_ms)
165 {
166 	kbd_enabled = enable_kb;
167 	mou_enabled = enable_ms;
168 }
169 
170 /* Keyboard Translation Table */
171 
172 typedef struct {
173   GrKeyType key;
174   unsigned short state;
175   KeySym keysym;
176 } KeyEntry;
177 
178 static KeyEntry _KeyTable[] = {
179   { GrKey_Alt_0                , Mod1Mask, XK_0 },
180   { GrKey_Alt_1                , Mod1Mask, XK_1 },
181   { GrKey_Alt_2                , Mod1Mask, XK_2 },
182   { GrKey_Alt_3                , Mod1Mask, XK_3 },
183   { GrKey_Alt_4                , Mod1Mask, XK_4 },
184   { GrKey_Alt_5                , Mod1Mask, XK_5 },
185   { GrKey_Alt_6                , Mod1Mask, XK_6 },
186   { GrKey_Alt_7                , Mod1Mask, XK_7 },
187   { GrKey_Alt_8                , Mod1Mask, XK_8 },
188   { GrKey_Alt_9                , Mod1Mask, XK_9 },
189   { GrKey_Alt_A                , Mod1Mask, XK_a },
190   { GrKey_Alt_At               , Mod1Mask, XK_at },
191   { GrKey_Alt_B                , Mod1Mask, XK_b },
192   { GrKey_Alt_Backquote        , Mod1Mask, XK_quoteright },
193   { GrKey_Alt_Backslash        , Mod1Mask, XK_backslash },
194   { GrKey_Alt_Backspace        , Mod1Mask, XK_BackSpace },
195   { GrKey_Alt_C                , Mod1Mask, XK_c },
196 #ifdef XK_KP_Begin
197   { GrKey_Alt_Center           , Mod1Mask, XK_KP_Begin },
198 #endif
199   { GrKey_Alt_Comma            , Mod1Mask, XK_comma },
200   { GrKey_Alt_D                , Mod1Mask, XK_d },
201   { GrKey_Alt_Dash             , Mod1Mask, XK_minus },
202 #ifdef XK_KP_Delete
203   { GrKey_Alt_Delete           , Mod1Mask, XK_KP_Delete },
204 #endif
205   { GrKey_Alt_Down             , Mod1Mask, XK_Down },
206 #ifdef XK_KP_Down
207   { GrKey_Alt_Down             , Mod1Mask, XK_KP_Down },
208 #endif
209   { GrKey_Alt_E                , Mod1Mask, XK_e },
210 #ifdef XK_KP_End
211   { GrKey_Alt_End              , Mod1Mask, XK_KP_End },
212 #endif
213 #ifdef XK_KP_Enter
214   { GrKey_Alt_Enter            , Mod1Mask, XK_KP_Enter },
215 #endif
216   { GrKey_Alt_Equals           , Mod1Mask, XK_equal },
217   { GrKey_Alt_Escape           , Mod1Mask, XK_Escape },
218   { GrKey_Alt_F                , Mod1Mask, XK_f },
219   { GrKey_Alt_F1               , Mod1Mask, XK_F1 },
220   { GrKey_Alt_F2               , Mod1Mask, XK_F2 },
221   { GrKey_Alt_F3               , Mod1Mask, XK_F3 },
222   { GrKey_Alt_F4               , Mod1Mask, XK_F4 },
223   { GrKey_Alt_F5               , Mod1Mask, XK_F5 },
224   { GrKey_Alt_F6               , Mod1Mask, XK_F6 },
225   { GrKey_Alt_F7               , Mod1Mask, XK_F7 },
226   { GrKey_Alt_F8               , Mod1Mask, XK_F8 },
227   { GrKey_Alt_F9               , Mod1Mask, XK_F9 },
228   { GrKey_Alt_F10              , Mod1Mask, XK_F10 },
229   { GrKey_Alt_F11              , Mod1Mask, XK_F11 },
230   { GrKey_Alt_F12              , Mod1Mask, XK_F12 },
231   { GrKey_Alt_G                , Mod1Mask, XK_g },
232   { GrKey_Alt_H                , Mod1Mask, XK_h },
233 #ifdef XK_KP_Home
234   { GrKey_Alt_Home             , Mod1Mask, XK_KP_Home },
235 #endif
236   { GrKey_Alt_I                , Mod1Mask, XK_i },
237 #ifdef XK_KP_Insert
238   { GrKey_Alt_Insert           , Mod1Mask, XK_KP_Insert },
239 #endif
240   { GrKey_Alt_J                , Mod1Mask, XK_j },
241   { GrKey_Alt_K                , Mod1Mask, XK_k },
242 #ifdef XK_KP_Subtract
243   { GrKey_Alt_KPMinus          , Mod1Mask, XK_KP_Subtract },
244 #endif
245 #ifdef XK_KP_Add
246   { GrKey_Alt_KPPlus           , Mod1Mask, XK_KP_Add },
247 #endif
248 #ifdef XK_KP_Divide
249   { GrKey_Alt_KPSlash          , Mod1Mask, XK_KP_Divide },
250 #endif
251 #ifdef XK_KP_Multiply
252   { GrKey_Alt_KPStar           , Mod1Mask, XK_KP_Multiply },
253 #endif
254   { GrKey_Alt_KPStar           , Mod1Mask, XK_multiply },
255   { GrKey_Alt_L                , Mod1Mask, XK_l },
256   { GrKey_Alt_LAngle           , Mod1Mask, XK_less },
257   { GrKey_Alt_LBrace           , Mod1Mask, XK_braceleft },
258   { GrKey_Alt_LBracket         , Mod1Mask, XK_bracketleft },
259 #ifdef XK_KP_Left
260   { GrKey_Alt_Left             , Mod1Mask, XK_KP_Left },
261 #endif
262   { GrKey_Alt_Left             , Mod1Mask, XK_Left },
263   { GrKey_Alt_M                , Mod1Mask, XK_m },
264   { GrKey_Alt_N                , Mod1Mask, XK_n },
265   { GrKey_Alt_O                , Mod1Mask, XK_o },
266   { GrKey_Alt_P                , Mod1Mask, XK_p },
267 #ifdef XK_KP_Next
268   { GrKey_Alt_PageDown         , Mod1Mask, XK_KP_Next },
269 #endif
270 #ifdef XK_KP_Page_Down
271   { GrKey_Alt_PageDown         , Mod1Mask, XK_KP_Page_Down },
272 #endif
273 #ifdef XK_KP_Page_Up
274   { GrKey_Alt_PageUp           , Mod1Mask, XK_KP_Page_Up },
275 #endif
276 #ifdef XK_KP_Prior
277   { GrKey_Alt_PageUp           , Mod1Mask, XK_KP_Prior },
278 #endif
279   { GrKey_Alt_Period           , Mod1Mask, XK_period },
280   { GrKey_Alt_Pipe             , Mod1Mask, XK_bar },
281   { GrKey_Alt_Q                , Mod1Mask, XK_q },
282   { GrKey_Alt_Quote            , Mod1Mask, XK_quoteleft },
283   { GrKey_Alt_R                , Mod1Mask, XK_r },
284   { GrKey_Alt_RAngle           , Mod1Mask, XK_greater },
285   { GrKey_Alt_RBrace           , Mod1Mask, XK_braceright },
286   { GrKey_Alt_RBracket         , Mod1Mask, XK_bracketright },
287   { GrKey_Alt_Return           , Mod1Mask, XK_Return },
288 #ifdef XK_KP_Right
289   { GrKey_Alt_Right            , Mod1Mask, XK_KP_Right },
290 #endif
291   { GrKey_Alt_Right            , Mod1Mask, XK_Right },
292   { GrKey_Alt_S                , Mod1Mask, XK_s },
293   { GrKey_Alt_Semicolon        , Mod1Mask, XK_semicolon },
294   { GrKey_Alt_Slash            , Mod1Mask, XK_slash },
295   { GrKey_Alt_T                , Mod1Mask, XK_t },
296   { GrKey_Alt_Tab              , Mod1Mask, XK_Tab },
297   { GrKey_Alt_U                , Mod1Mask, XK_u },
298 #ifdef XK_KP_Up
299   { GrKey_Alt_Up               , Mod1Mask, XK_KP_Up },
300 #endif
301   { GrKey_Alt_Up               , Mod1Mask, XK_Up },
302   { GrKey_Alt_V                , Mod1Mask, XK_v },
303   { GrKey_Alt_W                , Mod1Mask, XK_w },
304   { GrKey_Alt_X                , Mod1Mask, XK_x },
305   { GrKey_Alt_Y                , Mod1Mask, XK_y },
306   { GrKey_Alt_Z                , Mod1Mask, XK_z },
307 #ifdef XK_ISO_Left_Tab
308   { GrKey_BackTab              , ShiftMask, XK_ISO_Left_Tab },
309 #endif
310   { GrKey_Center               , 0, XK_5 },
311 #ifdef XK_KP_Begin
312   { GrKey_Center               , 0, XK_KP_Begin },
313 #endif
314   { GrKey_Control_At           , ControlMask, XK_at },
315   { GrKey_Control_Center       , ControlMask, XK_5 },
316 #ifdef XK_KP_Begin
317   { GrKey_Control_Center       , ControlMask, XK_KP_Begin },
318 #endif
319   { GrKey_Control_Delete       , ControlMask, XK_Delete },
320 #ifdef XK_KP_Delete
321   { GrKey_Control_Delete       , ControlMask, XK_KP_Delete },
322 #endif
323   { GrKey_Control_Down         , ControlMask, XK_Down },
324 #ifdef XK_KP_Down
325   { GrKey_Control_Down         , ControlMask, XK_KP_Down },
326 #endif
327   { GrKey_Control_End          , ControlMask, XK_End },
328 #ifdef XK_KP_End
329   { GrKey_Control_End          , ControlMask, XK_KP_End },
330 #endif
331   { GrKey_Control_F1           , ControlMask, XK_F1 },
332   { GrKey_Control_F2           , ControlMask, XK_F2 },
333   { GrKey_Control_F3           , ControlMask, XK_F3 },
334   { GrKey_Control_F4           , ControlMask, XK_F4 },
335   { GrKey_Control_F5           , ControlMask, XK_F5 },
336   { GrKey_Control_F6           , ControlMask, XK_F6 },
337   { GrKey_Control_F7           , ControlMask, XK_F7 },
338   { GrKey_Control_F8           , ControlMask, XK_F8 },
339   { GrKey_Control_F9           , ControlMask, XK_F9 },
340   { GrKey_Control_F10          , ControlMask, XK_F10 },
341   { GrKey_Control_F11          , ControlMask, XK_F11 },
342   { GrKey_Control_F12          , ControlMask, XK_F12 },
343   { GrKey_Control_Home         , ControlMask, XK_Home },
344 #ifdef XK_KP_Home
345   { GrKey_Control_Home         , ControlMask, XK_KP_Home },
346 #endif
347   { GrKey_Control_Insert       , ControlMask, XK_Insert },
348 #ifdef XK_KP_Insert
349   { GrKey_Control_Insert       , ControlMask, XK_KP_Insert },
350 #endif
351 #ifdef XK_KP_Subtract
352   { GrKey_Control_KPDash       , ControlMask, XK_KP_Subtract },
353 #endif
354 #ifdef XK_KP_Add
355   { GrKey_Control_KPPlus       , ControlMask, XK_KP_Add },
356 #endif
357   { GrKey_Control_KPSlash      , ControlMask, XK_slash },
358   { GrKey_Control_KPStar       , ControlMask, XK_multiply },
359   { GrKey_Control_Left         , ControlMask, XK_Left },
360 #ifdef XK_KP_Left
361   { GrKey_Control_Left         , ControlMask, XK_KP_Left },
362 #endif
363   { GrKey_Control_PageDown     , ControlMask, XK_Next },
364 #ifdef XK_KP_Next
365   { GrKey_Control_PageDown     , ControlMask, XK_KP_Next },
366 #endif
367   { GrKey_Control_PageUp       , ControlMask, XK_Prior },
368 #ifdef XK_KP_Prior
369   { GrKey_Control_PageUp       , ControlMask, XK_KP_Prior },
370 #endif
371   { GrKey_Control_Right        , ControlMask, XK_Right },
372 #ifdef XK_KP_Right
373   { GrKey_Control_Right        , ControlMask, XK_KP_Right },
374 #endif
375   { GrKey_Control_Up           , ControlMask, XK_Up },
376 #ifdef XK_KP_Up
377   { GrKey_Control_Up           , ControlMask, XK_KP_Up },
378 #endif
379 #ifdef XK_KP_Subtract
380   { GrKey_Dash                 , 0, XK_KP_Subtract },
381 #endif
382   { GrKey_Delete               , 0, XK_Delete },
383 #ifdef XK_KP_Delete
384   { GrKey_Delete               , 0, XK_KP_Delete },
385 #endif
386   { GrKey_Down                 , 0, XK_Down },
387 #ifdef XK_KP_Down
388   { GrKey_Down                 , 0, XK_KP_Down },
389 #endif
390   { GrKey_End                  , 0, XK_End },
391 #ifdef XK_KP_End
392   { GrKey_End                  , 0, XK_KP_End },
393 #endif
394   { GrKey_F1                   , 0, XK_F1 },
395   { GrKey_F2                   , 0, XK_F2 },
396   { GrKey_F3                   , 0, XK_F3 },
397   { GrKey_F4                   , 0, XK_F4 },
398   { GrKey_F5                   , 0, XK_F5 },
399   { GrKey_F6                   , 0, XK_F6 },
400   { GrKey_F7                   , 0, XK_F7 },
401   { GrKey_F8                   , 0, XK_F8 },
402   { GrKey_F9                   , 0, XK_F9 },
403   { GrKey_F10                  , 0, XK_F10 },
404   { GrKey_F11                  , 0, XK_F11 },
405   { GrKey_F12                  , 0, XK_F12 },
406   { GrKey_Home                 , 0, XK_Home },
407 #ifdef XK_KP_Home
408   { GrKey_Home                 , 0, XK_KP_Home },
409 #endif
410   { GrKey_Insert               , 0, XK_Insert },
411 #ifdef XK_KP_Insert
412   { GrKey_Insert               , 0, XK_KP_Insert },
413 #endif
414   { GrKey_Left                 , 0, XK_Left },
415 #ifdef XK_KP_Left
416   { GrKey_Left                 , 0, XK_KP_Left },
417 #endif
418   { GrKey_PageDown             , 0, XK_Next },
419 #ifdef XK_KP_Next
420   { GrKey_PageDown             , 0, XK_KP_Next },
421 #endif
422   { GrKey_PageUp               , 0, XK_Prior },
423 #ifdef XK_KP_Prior
424   { GrKey_PageUp               , 0, XK_KP_Prior },
425 #endif
426 #ifdef XK_KP_Add
427   { GrKey_Plus                 , 0, XK_KP_Add },
428 #endif
429   { GrKey_Print                , 0, XK_Print },
430   { GrKey_Right                , 0, XK_Right },
431 #ifdef XK_KP_Right
432   { GrKey_Right                , 0, XK_KP_Right },
433 #endif
434   { GrKey_Shift_Down           , ShiftMask, XK_Down },
435   { GrKey_Shift_End            , ShiftMask, XK_End },
436   { GrKey_Shift_F1             , ShiftMask, XK_F1 },
437   { GrKey_Shift_F2             , ShiftMask, XK_F2 },
438   { GrKey_Shift_F3             , ShiftMask, XK_F3 },
439   { GrKey_Shift_F4             , ShiftMask, XK_F4 },
440   { GrKey_Shift_F5             , ShiftMask, XK_F5 },
441   { GrKey_Shift_F6             , ShiftMask, XK_F6 },
442   { GrKey_Shift_F7             , ShiftMask, XK_F7 },
443   { GrKey_Shift_F8             , ShiftMask, XK_F8 },
444   { GrKey_Shift_F9             , ShiftMask, XK_F9 },
445   { GrKey_Shift_F10            , ShiftMask, XK_F10 },
446   { GrKey_Shift_F11            , ShiftMask, XK_F11 },
447   { GrKey_Shift_F12            , ShiftMask, XK_F12 },
448   { GrKey_Shift_Home           , ShiftMask, XK_Home },
449   { GrKey_Shift_Insert         , ShiftMask, XK_Insert },
450   { GrKey_Shift_Left           , ShiftMask, XK_Left },
451   { GrKey_Shift_PageDown       , ShiftMask, XK_Next },
452   { GrKey_Shift_PageUp         , ShiftMask, XK_Prior },
453   { GrKey_Shift_Right          , ShiftMask, XK_Right },
454   { GrKey_Shift_Up             , ShiftMask, XK_Up },
455   { GrKey_Up                   , 0, XK_Up },
456 #ifdef XK_KP_Up
457   { GrKey_Up                   , 0, XK_KP_Up },
458 #endif
459 };
460 
_XKeyEventToGrKey(XKeyEvent * xkey)461 static int _XKeyEventToGrKey (XKeyEvent *xkey)
462 {
463   KeyEntry *kp;
464   unsigned int state;
465   char buffer[20];
466   KeySym keysym;
467   int count;
468 
469   state = xkey->state & (ShiftMask | ControlMask | Mod1Mask);
470   count = XLookupString (xkey,
471 			 buffer,
472 			 sizeof(buffer),
473 			 &keysym, (XComposeStatus *) NULL);
474 
475   if ((count == 1) && ((state & Mod1Mask) == 0))
476     return (unsigned char) buffer[0];
477 
478   for (kp = _KeyTable;
479        kp < &_KeyTable[sizeof(_KeyTable)/sizeof(_KeyTable[0])];
480        kp = kp + 1)
481     {
482       if (keysym == kp->keysym && state == kp->state)
483 	return kp->key;
484     }
485   /* printf("Unknown: 0x%x\n", (unsigned) keysym); */
486   return EOF;
487 }
488 
489 static INLINE
_XButtonEventToGrButton(XButtonEvent * event)490 unsigned int _XButtonEventToGrButton (XButtonEvent *event)
491 {
492   unsigned int state = event->state;
493   unsigned int mask = 0;
494 
495   switch (event->button) {
496   case Button1: mask = Button1Mask; break;
497   case Button2: mask = Button2Mask; break;
498   case Button3: mask = Button3Mask; break;
499   case Button4: mask = Button4Mask; break;
500   case Button5: mask = Button5Mask; break;
501   }
502   switch (event->type) {
503   case ButtonPress:     state |= mask; break;
504   case ButtonRelease:   state &= ~mask; break;
505   }
506   return (  ((state & Button1Mask) ? GR_M_LEFT : 0)
507 	  | ((state & Button2Mask) ? GR_M_MIDDLE : 0)
508 	  | ((state & Button3Mask) ? GR_M_RIGHT : 0)
509 	  | ((state & Button4Mask) ? GR_M_P4 : 0)
510 	  | ((state & Button5Mask) ? GR_M_P5 : 0));
511 }
512 
513 static INLINE
_XGrModifierKey(KeySym keysym,int type)514 unsigned int _XGrModifierKey (KeySym keysym, int type)
515 {
516   if (type == KeyPress) {
517     switch (keysym) {
518     case XK_Shift_L:    kbd_lastmod |= GR_KB_LEFTSHIFT; break;
519     case XK_Shift_R:    kbd_lastmod |= GR_KB_RIGHTSHIFT; break;
520     case XK_Control_L:
521     case XK_Control_R:  kbd_lastmod |= GR_KB_CTRL; break;
522     case XK_Alt_L:
523     case XK_Alt_R:
524     case XK_Meta_L:
525     case XK_Meta_R:     kbd_lastmod |= GR_KB_ALT; break;
526     case XK_Num_Lock:   kbd_lastmod |= GR_KB_NUMLOCK; break;
527     case XK_Caps_Lock:  kbd_lastmod |= GR_KB_CAPSLOCK; break;
528     case XK_Insert:     kbd_lastmod |= GR_KB_INSERT; break;
529     }
530   }
531   if (type == KeyRelease) {
532     switch (keysym) {
533     case XK_Shift_L:    kbd_lastmod &= ~GR_KB_LEFTSHIFT; break;
534     case XK_Shift_R:    kbd_lastmod &= ~GR_KB_RIGHTSHIFT; break;
535     case XK_Control_L:
536     case XK_Control_R:  kbd_lastmod &= ~GR_KB_CTRL; break;
537     case XK_Alt_L:
538     case XK_Alt_R:
539     case XK_Meta_L:
540     case XK_Meta_R:     kbd_lastmod &= ~GR_KB_ALT; break;
541     case XK_Num_Lock:   kbd_lastmod &= ~GR_KB_NUMLOCK; break;
542     case XK_Caps_Lock:  kbd_lastmod &= ~GR_KB_CAPSLOCK; break;
543     case XK_Insert:     kbd_lastmod &= ~GR_KB_INSERT; break;
544     }
545   }
546   return kbd_lastmod;
547 }
548 
_GrUpdateInputs(void)549 void _GrUpdateInputs(void)
550 {
551   int count;
552 
553 #if 0
554   if (_XGrTickValue == -1) {
555     struct itimerval it;
556 
557     _XGrTickHandler (SIGALRM);
558     it.it_interval.tv_sec = 0;
559     it.it_interval.tv_usec = MS_PER_TICK * 1000L;
560     it.it_value.tv_sec = 0;
561     it.it_value.tv_usec = MS_PER_TICK * 1000L;
562     setitimer (ITIMER_REAL, &it, NULL);
563   }
564 #endif
565 
566   if (_XGrDisplay) {
567     count = XEventsQueued (_XGrDisplay, QueuedAfterReading);
568     if (count <= 0) {
569       XFlush (_XGrDisplay);
570       return;
571     }
572     while (--count >= 0) {
573       GrMouseEvent ev;
574       XEvent xev;
575       KeySym keysym;
576       int btn;
577 
578       XNextEvent (_XGrDisplay, &xev);
579       switch (xev.type) {
580       case Expose:
581 	  _XGrCopyBStore(xev.xexpose.x, xev.xexpose.y,
582 	    xev.xexpose.width, xev.xexpose.height);
583 	  break;
584 
585       case MotionNotify:
586 	if (mou_enabled && (MOUINFO->msstatus == 2)) {
587 	  if (_XGrWindowedMode) {
588 	    MOUINFO->xpos = xev.xmotion.x;
589 	    MOUINFO->ypos = xev.xmotion.y;
590 	  }
591 	  else {
592 	    MOUINFO->xpos += xev.xmotion.x;
593 	    MOUINFO->ypos += xev.xmotion.y;
594 	  }
595 	  MOUINFO->moved  = TRUE;
596 	  MouseMoveTime   = xev.xmotion.time;
597 	}
598 	break;
599 
600       case ButtonPress:
601       case ButtonRelease:
602 	if (mou_enabled && (MOUINFO->msstatus == 2)) {
603 	  btn = _XButtonEventToGrButton (&xev.xbutton);
604 	  if(btn != mou_buttons) {
605 	    fill_mouse_ev(
606 			  ev,
607 			  mou_buttons,btn,
608 			  GR_M_LEFT,
609 			  GR_M_MIDDLE,
610 			  GR_M_RIGHT,
611 			  GR_M_P4,
612 			  GR_M_P5,
613 			  kbd_lastmod
614 			  );
615 	    if (evt_lasttime_ok)
616 	      ev.dtime = xev.xbutton.time - evt_lasttime;
617 	    else {
618 	      ev.dtime = 1;
619 	      evt_lasttime_ok = TRUE;
620 	    }
621 	    evt_lasttime = xev.xbutton.time;
622 	    enqueue_event(ev);
623 	    MOUINFO->moved = FALSE;
624 	    mou_buttons = btn;
625 	  }
626 	}
627 	break;
628 
629       case KeyPress:
630 	keysym = XKeycodeToKeysym (_XGrDisplay, xev.xkey.keycode, 0);
631 	if (IsModifierKey (keysym)) {
632 	  _XGrModifierKey (keysym, xev.type);
633 	}
634 	else if (kbd_enabled) {
635 	  fill_keybd_ev(
636 			ev,
637 			_XKeyEventToGrKey (&xev.xkey),
638 			kbd_lastmod
639 			);
640 	  if (evt_lasttime_ok)
641 	    ev.dtime = xev.xkey.time - evt_lasttime;
642 	  else {
643 	    ev.dtime = 1;
644 	    evt_lasttime_ok = TRUE;
645 	  }
646 	  evt_lasttime = xev.xkey.time;
647 	  enqueue_event(ev);
648 	  MOUINFO->moved = FALSE;
649 	}
650 	break;
651 
652       case KeyRelease:
653 	keysym = XKeycodeToKeysym (_XGrDisplay, xev.xkey.keycode, 0);
654 	if (IsModifierKey (keysym)) {
655 	  _XGrModifierKey (keysym, xev.type);
656 	}
657 	break;
658       }
659     }
660   }
661 }
662 
GrMouseGetEventT(int flags,GrMouseEvent * ev,long tout)663 void GrMouseGetEventT(int flags,GrMouseEvent *ev,long tout)
664 {
665   int  msdraw;
666   ev->flags = 0;
667   if (MOUINFO->msstatus == 0) GrMouseInit();
668   if (MOUINFO->msstatus == 0) return;
669   msdraw = !MOUINFO->displayed && !(flags & GR_M_NOPAINT);
670   if (msdraw) GrMouseDisplayCursor();
671   /* Note: avoid zero timeout for select */
672   /* I don't agree. Zero timeout is still needed when I want to display soft */
673   /* real time data while looking for some keypress at the same time (A.Pavenis) */
674   /* if (tout <= 0L) tout = 1L; */
675   if (tout < 0L) tout = 0L;
676   for( ; _XGrDisplay ; ) {
677     struct timeval tval;
678     fd_set readfds;
679     int fd;
680     /*
681      * Note: The select call with nonzero timeout avoids CPU usage
682      *       of nearly 100%
683      */
684     fd = ConnectionNumber(_XGrDisplay);
685     FD_ZERO(&readfds);
686     FD_SET(fd, &readfds);
687     tval.tv_sec = tout / 1000L;
688     tval.tv_usec = (tout % 1000) * 1000L;
689     select (fd + 1,
690 	    &readfds,
691 	    (fd_set *) 0,
692 	    (fd_set *) 0,
693 	    &tval);
694     tout = tval.tv_sec * 1000L + tval.tv_usec / 1000L;
695 
696     _GrUpdateInputs();
697     GrMouseUpdateCursor();
698     while (MOUINFO->qlength > 0) {
699       dequeue_event((*ev));
700       if (ev->flags & flags) {
701 	if (msdraw) GrMouseEraseCursor();
702 	return;
703       }
704     }
705     if ((flags & GR_M_POLL) ||
706 	(tout == 0L) ||
707 	(MOUINFO->moved && (flags & GR_M_MOTION))) {
708       fill_mouse_ev(
709 		    (*ev),
710 		    mou_buttons,mou_buttons,
711 		    GR_M_LEFT,
712 		    GR_M_MIDDLE,
713 		    GR_M_RIGHT,
714 		    GR_M_P4,
715 		    GR_M_P5,
716 		    kbd_lastmod
717 		    );
718       if ( ev->flags ) {
719 	/* something happend */
720 	if (MOUINFO->moved) {
721 	  if (evt_lasttime_ok && MouseMoveTime) {
722 	    ev->dtime = MouseMoveTime - evt_lasttime;
723 	    evt_lasttime = MouseMoveTime;
724 	  } else
725 	    ev->dtime = 1;
726 	}
727 	/* otherwise the ev->dtime is ok */
728       } else
729 	ev->dtime = -1; /* special time if nothing happend */
730       MOUINFO->moved = FALSE;
731       MouseMoveTime = 0;
732       if (msdraw) GrMouseEraseCursor();
733       return;
734     }
735     /* Make sure we don't use all the CPU */
736     /* Is this the right way, Andris? */
737     if (tout == 0L) tout = 1L;
738   }
739 }
740 
741 
_XGrKeyboardHit(void)742 int _XGrKeyboardHit (void)
743 {
744   XEvent xev;
745   KeySym keysym;
746 
747   if (_XGrDisplay) {
748     if (XEventsQueued (_XGrDisplay, QueuedAfterReading) <= 0)   {
749       XFlush (_XGrDisplay);
750       return FALSE;
751     }
752     while (XCheckMaskEvent (_XGrDisplay, KeyPressMask|KeyReleaseMask, &xev)) {
753       keysym = XKeycodeToKeysym (_XGrDisplay, xev.xkey.keycode, 0);
754       if (IsModifierKey (keysym)) {
755 	_XGrModifierKey (keysym, xev.type);
756 	continue;
757       }
758       if (xev.type == KeyPress) {
759 	XPutBackEvent (_XGrDisplay, &xev);
760 	return TRUE;
761       }
762     }
763   }
764   return FALSE;
765 }
766 
_XGrKeyboardGetKey(void)767 int _XGrKeyboardGetKey (void)
768 {
769   XEvent xev;
770   KeySym keysym;
771 
772   if (_XGrDisplay) {
773     while (XMaskEvent (_XGrDisplay, KeyPressMask|KeyReleaseMask, &xev)) {
774       keysym = XKeycodeToKeysym (_XGrDisplay, xev.xkey.keycode, 0);
775       if (IsModifierKey (keysym)) {
776 	_XGrModifierKey (keysym, xev.type);
777 	continue;
778       }
779       if (xev.type == KeyPress) {
780 	return _XKeyEventToGrKey (&xev.xkey);
781       }
782     }
783   }
784   return 0;
785 }
786 
_XGrKeyboardGetState(void)787 int _XGrKeyboardGetState (void)
788 {
789   return kbd_lastmod;
790 }
791 
792