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