source: libcaca/trunk/caca/event.c @ 541

Last change on this file since 541 was 541, checked in by Sam Hocevar, 14 years ago
  • Got rid of static variables in the event code.
  • Property svn:keywords set to Id
File size: 27.0 KB
Line 
1/*
2 *  libcaca       ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the Do What The Fuck You Want To
8 *  Public License, Version 2, as published by Sam Hocevar. See
9 *  http://sam.zoy.org/wtfpl/COPYING for more details.
10 */
11
12/** \file event.c
13 *  \version \$Id: event.c 541 2006-03-07 10:37:59Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
15 *  \brief Event handling
16 *
17 *  This file contains event handling functions for keyboard and mouse input.
18 */
19
20#include "config.h"
21
22#if defined(USE_SLANG)
23#   if defined(HAVE_SLANG_SLANG_H)
24#       include <slang/slang.h>
25#   else
26#       include <slang.h>
27#   endif
28#endif
29#if defined(USE_NCURSES)
30#   if defined(HAVE_NCURSES_H)
31#       include <ncurses.h>
32#   else
33#       include <curses.h>
34#   endif
35#endif
36#if defined(USE_CONIO)
37#   include <conio.h>
38#endif
39#if defined(USE_X11)
40#   include <X11/Xlib.h>
41#   include <X11/Xutil.h>
42#   include <X11/keysym.h>
43#endif
44#if defined(USE_WIN32)
45#   include <windows.h>
46#endif
47#if defined(USE_GL)
48#include <GL/gl.h>
49#include <GL/glut.h>
50#include <GL/freeglut_ext.h>
51#endif
52
53#include "cucul.h"
54#include "cucul_internals.h"
55#include "caca.h"
56#include "caca_internals.h"
57
58static unsigned int _get_next_event(caca_t *);
59static unsigned int _lowlevel_event(caca_t *);
60#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
61static void _push_event(caca_t *, unsigned int);
62static unsigned int _pop_event(caca_t *);
63#endif
64
65#if !defined(_DOXYGEN_SKIP_ME)
66/* If no new key was pressed after AUTOREPEAT_THRESHOLD usec, assume the
67 * key was released */
68#define AUTOREPEAT_THRESHOLD 200000
69/* Start repeating key after AUTOREPEAT_TRIGGER usec and send keypress
70 * events every AUTOREPEAT_RATE usec. */
71#define AUTOREPEAT_TRIGGER 300000
72#define AUTOREPEAT_RATE 100000
73#endif
74
75/** \brief Get the next mouse or keyboard input event.
76 *
77 *  This function polls the event queue for mouse or keyboard events matching
78 *  the event mask and returns the first matching event. Non-matching events
79 *  are discarded. \c event_mask must have a non-zero value. This function is
80 *  non-blocking and returns zero if no more events are pending in the queue.
81 *  See also caca_wait_event() for a blocking version of this function.
82 *
83 * \param event_mask Bitmask of requested events.
84 * \return The next matching event in the queue, or 0 if no event is pending.
85 */
86unsigned int caca_get_event(caca_t *kk, unsigned int event_mask)
87{
88    if(!event_mask)
89        return CACA_EVENT_NONE;
90
91    for( ; ; )
92    {
93        unsigned int event = _get_next_event(kk);
94
95        if(!event || event & event_mask)
96            return event;
97    }
98}
99
100/** \brief Wait for the next mouse or keyboard input event.
101 *
102 *  This function returns the first mouse or keyboard event in the queue
103 *  that matches the event mask. If no event is pending, it blocks until a
104 *  matching event is received. \c event_mask must have a non-zero value.
105 *  See also caca_get_event() for a non-blocking version of this function.
106 *
107 *  \param event_mask Bitmask of requested events.
108 *  \return The next event in the queue.
109 */
110unsigned int caca_wait_event(caca_t *kk, unsigned int event_mask)
111{
112    if(!event_mask)
113        return CACA_EVENT_NONE;
114
115    for( ; ; )
116    {
117        unsigned int event = _get_next_event(kk);
118
119        if(event & event_mask)
120            return event;
121
122        _caca_sleep(10000);
123    }
124}
125
126/** \brief Return the X mouse coordinate.
127 *
128 *  This function returns the X coordinate of the mouse position last time
129 *  it was detected. This function is not reliable if the ncurses or S-Lang
130 *  drivers are being used, because mouse position is only detected when
131 *  the mouse is clicked. Other drivers such as X11 work well.
132 *
133 *  \return The X mouse coordinate.
134 */
135unsigned int caca_get_mouse_x(caca_t *kk)
136{
137    if(kk->mouse_x >= kk->qq->width)
138        kk->mouse_x = kk->qq->width - 1;
139
140    return kk->mouse_x;
141}
142
143/** \brief Return the Y mouse coordinate.
144 *
145 *  This function returns the Y coordinate of the mouse position last time
146 *  it was detected. This function is not reliable if the ncurses or S-Lang
147 *  drivers are being used, because mouse position is only detected when
148 *  the mouse is clicked. Other drivers such as X11 work well.
149 *
150 *  \return The Y mouse coordinate.
151 */
152unsigned int caca_get_mouse_y(caca_t *kk)
153{
154    if(kk->mouse_y >= kk->qq->height)
155        kk->mouse_y = kk->qq->height - 1;
156
157    return kk->mouse_y;
158}
159
160/*
161 * XXX: The following functions are local.
162 */
163
164static unsigned int _get_next_event(caca_t *kk)
165{
166#if defined(USE_SLANG) || defined(USE_NCURSES)
167    unsigned int ticks;
168#endif
169    unsigned int event;
170
171    event = _lowlevel_event(kk);
172
173#if defined(USE_SLANG)
174    if(kk->driver.driver != CACA_DRIVER_SLANG)
175#endif
176#if defined(USE_NCURSES)
177    if(kk->driver.driver != CACA_DRIVER_NCURSES)
178#endif
179    return event;
180
181#if defined(USE_SLANG) || defined(USE_NCURSES)
182    /* Simulate long keypresses using autorepeat features */
183    ticks = _caca_getticks(&kk->events.key_timer);
184    kk->events.last_key_ticks += ticks;
185    kk->events.autorepeat_ticks += ticks;
186
187    /* Handle autorepeat */
188    if(kk->events.last_key
189           && kk->events.autorepeat_ticks > AUTOREPEAT_TRIGGER
190           && kk->events.autorepeat_ticks > AUTOREPEAT_THRESHOLD
191           && kk->events.autorepeat_ticks > AUTOREPEAT_RATE)
192    {
193        _push_event(kk, event);
194        kk->events.autorepeat_ticks -= AUTOREPEAT_RATE;
195        return CACA_EVENT_KEY_PRESS | kk->events.last_key;
196    }
197
198    /* We are in autorepeat mode and the same key was just pressed, ignore
199     * this event and return the next one by calling ourselves. */
200    if(event == (CACA_EVENT_KEY_PRESS | kk->events.last_key))
201    {
202        kk->events.last_key_ticks = 0;
203        return _get_next_event(kk);
204    }
205
206    /* We are in autorepeat mode, but key has expired or a new key was
207     * pressed - store our event and return a key release event first */
208    if(kk->events.last_key
209          && (kk->events.last_key_ticks > AUTOREPEAT_THRESHOLD
210               || (event & CACA_EVENT_KEY_PRESS)))
211    {
212        _push_event(kk, event);
213        event = CACA_EVENT_KEY_RELEASE | kk->events.last_key;
214        kk->events.last_key = 0;
215        return event;
216    }
217
218    /* A new key was pressed, enter autorepeat mode */
219    if(event & CACA_EVENT_KEY_PRESS)
220    {
221        kk->events.last_key_ticks = 0;
222        kk->events.autorepeat_ticks = 0;
223        kk->events.last_key = event & 0x00ffffff;
224    }
225
226    return event;
227#endif
228}
229
230static unsigned int _lowlevel_event(caca_t *kk)
231{
232    unsigned int event;
233
234#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
235    event = _pop_event(kk);
236
237    if(event)
238        return event;
239#endif
240
241#if defined(USE_X11)
242    /* The X11 event check routine */
243    if(kk->driver.driver == CACA_DRIVER_X11)
244    {
245        XEvent xevent;
246        char key;
247
248        while(XCheckWindowEvent(kk->x11.dpy, kk->x11.window, kk->x11.event_mask, &xevent)
249               == True)
250        {
251            KeySym keysym;
252
253            /* Expose event */
254            if(xevent.type == Expose)
255            {
256                XCopyArea(kk->x11.dpy, kk->x11.pixmap,
257                          kk->x11.window, kk->x11.gc, 0, 0,
258                          kk->qq->width * kk->x11.font_width,
259                          kk->qq->height * kk->x11.font_height, 0, 0);
260                continue;
261            }
262
263            /* Resize event */
264            if(xevent.type == ConfigureNotify)
265            {
266                unsigned int w, h;
267
268                w = (xevent.xconfigure.width + kk->x11.font_width / 3)
269                      / kk->x11.font_width;
270                h = (xevent.xconfigure.height + kk->x11.font_height / 3)
271                      / kk->x11.font_height;
272
273                if(!w || !h || (w == kk->qq->width && h == kk->qq->height))
274                    continue;
275
276                kk->x11.new_width = w;
277                kk->x11.new_height = h;
278
279                /* If we are already resizing, ignore the new signal */
280                if(kk->resize)
281                    continue;
282
283                kk->resize = 1;
284
285                return CACA_EVENT_RESIZE;
286            }
287
288            /* Check for mouse motion events */
289            if(xevent.type == MotionNotify)
290            {
291                unsigned int newx = xevent.xmotion.x / kk->x11.font_width;
292                unsigned int newy = xevent.xmotion.y / kk->x11.font_height;
293
294                if(newx >= kk->qq->width)
295                    newx = kk->qq->width - 1;
296                if(newy >= kk->qq->height)
297                    newy = kk->qq->height - 1;
298
299                if(kk->mouse_x == newx && kk->mouse_y == newy)
300                    continue;
301
302                kk->mouse_x = newx;
303                kk->mouse_y = newy;
304
305                return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y;
306            }
307
308            /* Check for mouse press and release events */
309            if(xevent.type == ButtonPress)
310                return CACA_EVENT_MOUSE_PRESS
311                        | ((XButtonEvent *)&xevent)->button;
312
313            if(xevent.type == ButtonRelease)
314                return CACA_EVENT_MOUSE_RELEASE
315                        | ((XButtonEvent *)&xevent)->button;
316
317            /* Check for key press and release events */
318            if(xevent.type == KeyPress)
319                event |= CACA_EVENT_KEY_PRESS;
320            else if(xevent.type == KeyRelease)
321                event |= CACA_EVENT_KEY_RELEASE;
322            else
323                continue;
324
325            if(XLookupString(&xevent.xkey, &key, 1, NULL, NULL))
326                return event | key;
327
328            keysym = XKeycodeToKeysym(kk->x11.dpy, xevent.xkey.keycode, 0);
329            switch(keysym)
330            {
331            case XK_F1:    return event | CACA_KEY_F1;
332            case XK_F2:    return event | CACA_KEY_F2;
333            case XK_F3:    return event | CACA_KEY_F3;
334            case XK_F4:    return event | CACA_KEY_F4;
335            case XK_F5:    return event | CACA_KEY_F5;
336            case XK_F6:    return event | CACA_KEY_F6;
337            case XK_F7:    return event | CACA_KEY_F7;
338            case XK_F8:    return event | CACA_KEY_F8;
339            case XK_F9:    return event | CACA_KEY_F9;
340            case XK_F10:   return event | CACA_KEY_F10;
341            case XK_F11:   return event | CACA_KEY_F11;
342            case XK_F12:   return event | CACA_KEY_F12;
343            case XK_F13:   return event | CACA_KEY_F13;
344            case XK_F14:   return event | CACA_KEY_F14;
345            case XK_F15:   return event | CACA_KEY_F15;
346            case XK_Left:  return event | CACA_KEY_LEFT;
347            case XK_Right: return event | CACA_KEY_RIGHT;
348            case XK_Up:    return event | CACA_KEY_UP;
349            case XK_Down:  return event | CACA_KEY_DOWN;
350            default:       return CACA_EVENT_NONE;
351            }
352        }
353
354        return CACA_EVENT_NONE;
355    }
356    else
357#endif
358#if defined(USE_NCURSES)
359    if(kk->driver.driver == CACA_DRIVER_NCURSES)
360    {
361        int intkey;
362
363        if(kk->resize_event)
364        {
365            kk->resize_event = 0;
366            kk->resize = 1;
367            return CACA_EVENT_RESIZE;
368        }
369
370        intkey = getch();
371        if(intkey == ERR)
372            return CACA_EVENT_NONE;
373
374        if(intkey < 0x100)
375        {
376            return CACA_EVENT_KEY_PRESS | intkey;
377        }
378
379        if(intkey == KEY_MOUSE)
380        {
381            MEVENT mevent;
382            getmouse(&mevent);
383
384            switch(mevent.bstate)
385            {
386                case BUTTON1_PRESSED:
387                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1);
388                    break;
389                case BUTTON1_RELEASED:
390                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1);
391                    break;
392                case BUTTON1_CLICKED:
393                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1);
394                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1);
395                    break;
396                case BUTTON1_DOUBLE_CLICKED:
397                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1);
398                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1);
399                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1);
400                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1);
401                    break;
402                case BUTTON1_TRIPLE_CLICKED:
403                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1);
404                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1);
405                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1);
406                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1);
407                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1);
408                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1);
409                    break;
410                case BUTTON1_RESERVED_EVENT:
411                    break;
412
413                case BUTTON2_PRESSED:
414                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2);
415                    break;
416                case BUTTON2_RELEASED:
417                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2);
418                    break;
419                case BUTTON2_CLICKED:
420                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2);
421                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2);
422                    break;
423                case BUTTON2_DOUBLE_CLICKED:
424                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2);
425                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2);
426                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2);
427                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2);
428                    break;
429                case BUTTON2_TRIPLE_CLICKED:
430                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2);
431                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2);
432                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2);
433                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2);
434                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2);
435                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2);
436                    break;
437                case BUTTON2_RESERVED_EVENT:
438                    break;
439
440                case BUTTON3_PRESSED:
441                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3);
442                    break;
443                case BUTTON3_RELEASED:
444                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3);
445                    break;
446                case BUTTON3_CLICKED:
447                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3);
448                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3);
449                    break;
450                case BUTTON3_DOUBLE_CLICKED:
451                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3);
452                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3);
453                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3);
454                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3);
455                    break;
456                case BUTTON3_TRIPLE_CLICKED:
457                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3);
458                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3);
459                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3);
460                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3);
461                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3);
462                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3);
463                    break;
464                case BUTTON3_RESERVED_EVENT:
465                    break;
466
467                case BUTTON4_PRESSED:
468                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4);
469                    break;
470                case BUTTON4_RELEASED:
471                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4);
472                    break;
473                case BUTTON4_CLICKED:
474                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4);
475                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4);
476                    break;
477                case BUTTON4_DOUBLE_CLICKED:
478                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4);
479                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4);
480                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4);
481                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4);
482                    break;
483                case BUTTON4_TRIPLE_CLICKED:
484                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4);
485                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4);
486                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4);
487                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4);
488                    _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4);
489                    _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4);
490                    break;
491                case BUTTON4_RESERVED_EVENT:
492                    break;
493
494                default:
495                    break;
496            }
497
498            if(kk->mouse_x == (unsigned int)mevent.x &&
499               kk->mouse_y == (unsigned int)mevent.y)
500                return _pop_event(kk);
501
502            kk->mouse_x = mevent.x;
503            kk->mouse_y = mevent.y;
504
505            return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y;
506        }
507
508        event = CACA_EVENT_KEY_PRESS;
509
510        switch(intkey)
511        {
512            case KEY_UP: return event | CACA_KEY_UP;
513            case KEY_DOWN: return event | CACA_KEY_DOWN;
514            case KEY_LEFT: return event | CACA_KEY_LEFT;
515            case KEY_RIGHT: return event | CACA_KEY_RIGHT;
516
517            case KEY_IC: return event | CACA_KEY_INSERT;
518            case KEY_DC: return event | CACA_KEY_DELETE;
519            case KEY_HOME: return event | CACA_KEY_HOME;
520            case KEY_END: return event | CACA_KEY_END;
521            case KEY_PPAGE: return event | CACA_KEY_PAGEUP;
522            case KEY_NPAGE: return event | CACA_KEY_PAGEDOWN;
523
524            case KEY_F(1): return event | CACA_KEY_F1;
525            case KEY_F(2): return event | CACA_KEY_F2;
526            case KEY_F(3): return event | CACA_KEY_F3;
527            case KEY_F(4): return event | CACA_KEY_F4;
528            case KEY_F(5): return event | CACA_KEY_F5;
529            case KEY_F(6): return event | CACA_KEY_F6;
530            case KEY_F(7): return event | CACA_KEY_F7;
531            case KEY_F(8): return event | CACA_KEY_F8;
532            case KEY_F(9): return event | CACA_KEY_F9;
533            case KEY_F(10): return event | CACA_KEY_F10;
534            case KEY_F(11): return event | CACA_KEY_F11;
535            case KEY_F(12): return event | CACA_KEY_F12;
536        }
537
538        return CACA_EVENT_NONE;
539    }
540    else
541#endif
542#if defined(USE_SLANG)
543    if(kk->driver.driver == CACA_DRIVER_SLANG)
544    {
545        int intkey;
546
547        if(kk->resize_event)
548        {
549            kk->resize_event = 0;
550            kk->resize = 1;
551            return CACA_EVENT_RESIZE;
552        }
553
554        if(!SLang_input_pending(0))
555            return CACA_EVENT_NONE;
556
557        /* We first use SLang_getkey() to see whether Esc was pressed
558         * alone, then (if it wasn't) we unget the key and use SLkp_getkey()
559         * instead, so that escape sequences are interpreted. */
560        intkey = SLang_getkey();
561
562        if(intkey != 0x1b /* Esc */ || SLang_input_pending(0))
563        {
564            SLang_ungetkey(intkey);
565            intkey = SLkp_getkey();
566        }
567
568        /* If the key was ASCII, return it immediately */
569        if(intkey < 0x100)
570        {
571            return CACA_EVENT_KEY_PRESS | intkey;
572        }
573
574        if(intkey == 0x3e9)
575        {
576            int button = (SLang_getkey() - ' ' + 1) & 0xf;
577            unsigned int x = SLang_getkey() - '!';
578            unsigned int y = SLang_getkey() - '!';
579            _push_event(kk, CACA_EVENT_MOUSE_PRESS | button);
580            _push_event(kk, CACA_EVENT_MOUSE_RELEASE | button);
581
582            if(kk->mouse_x == x && kk->mouse_y == y)
583                return _pop_event(kk);
584
585            kk->mouse_x = x;
586            kk->mouse_y = y;
587
588            return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y;
589        }
590
591        event = CACA_EVENT_KEY_PRESS;
592
593        switch(intkey)
594        {
595            case SL_KEY_UP: return event | CACA_KEY_UP;
596            case SL_KEY_DOWN: return event | CACA_KEY_DOWN;
597            case SL_KEY_LEFT: return event | CACA_KEY_LEFT;
598            case SL_KEY_RIGHT: return event | CACA_KEY_RIGHT;
599
600            case SL_KEY_IC: return event | CACA_KEY_INSERT;
601            case SL_KEY_DELETE: return event | CACA_KEY_DELETE;
602            case SL_KEY_HOME: return event | CACA_KEY_HOME;
603            case SL_KEY_END: return event | CACA_KEY_END;
604            case SL_KEY_PPAGE: return event | CACA_KEY_PAGEUP;
605            case SL_KEY_NPAGE: return event | CACA_KEY_PAGEDOWN;
606
607            case SL_KEY_F(1): return event | CACA_KEY_F1;
608            case SL_KEY_F(2): return event | CACA_KEY_F2;
609            case SL_KEY_F(3): return event | CACA_KEY_F3;
610            case SL_KEY_F(4): return event | CACA_KEY_F4;
611            case SL_KEY_F(5): return event | CACA_KEY_F5;
612            case SL_KEY_F(6): return event | CACA_KEY_F6;
613            case SL_KEY_F(7): return event | CACA_KEY_F7;
614            case SL_KEY_F(8): return event | CACA_KEY_F8;
615            case SL_KEY_F(9): return event | CACA_KEY_F9;
616            case SL_KEY_F(10): return event | CACA_KEY_F10;
617            case SL_KEY_F(11): return event | CACA_KEY_F11;
618            case SL_KEY_F(12): return event | CACA_KEY_F12;
619        }
620
621        return CACA_EVENT_NONE;
622    }
623    else
624#endif
625#if defined(USE_CONIO)
626    if(kk->driver.driver == CACA_DRIVER_CONIO)
627    {
628        if(!_conio_kbhit())
629            return CACA_EVENT_NONE;
630
631        event = getch();
632        _push_event(kk, CACA_EVENT_KEY_RELEASE | event);
633        return CACA_EVENT_KEY_PRESS | event;
634    }
635    else
636#endif
637#if defined(USE_WIN32)
638    if(kk->driver.driver == CACA_DRIVER_WIN32)
639    {
640        INPUT_RECORD rec;
641        DWORD num;
642
643        for( ; ; )
644        {
645            GetNumberOfConsoleInputEvents(kk->win32.hin, &num);
646            if(num == 0)
647                break;
648
649            ReadConsoleInput(kk->win32.hin, &rec, 1, &num);
650            if(rec.EventType == KEY_EVENT)
651            {
652                if(rec.Event.KeyEvent.bKeyDown)
653                    event = CACA_EVENT_KEY_PRESS;
654                else
655                    event = CACA_EVENT_KEY_RELEASE;
656
657                if(rec.Event.KeyEvent.uChar.AsciiChar)
658                    return event | rec.Event.KeyEvent.uChar.AsciiChar;
659            }
660
661            if(rec.EventType == MOUSE_EVENT)
662            {
663                if(rec.Event.MouseEvent.dwEventFlags == 0)
664                {
665                    if(rec.Event.MouseEvent.dwButtonState & 0x01)
666                        return CACA_EVENT_MOUSE_PRESS | 0x000001;
667
668                    if(rec.Event.MouseEvent.dwButtonState & 0x02)
669                        return CACA_EVENT_MOUSE_PRESS | 0x000002;
670                }
671                else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
672                {
673                    COORD pos = rec.Event.MouseEvent.dwMousePosition;
674
675                    if(kk->mouse_x == (unsigned int)pos.X &&
676                       kk->mouse_y == (unsigned int)pos.Y)
677                        continue;
678
679                    kk->mouse_x = pos.X;
680                    kk->mouse_y = pos.Y;
681
682                    return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y;
683                }
684#if 0
685                else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
686                {
687                    cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
688                            rec.Event.MouseEvent.dwMousePosition.Y << "  " << flush;
689                }
690                else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
691                {
692                    SetConsoleCursorPosition(hOut,
693                                             WheelWhere);
694                    if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
695                        cout << "Down" << flush;
696                    else
697                        cout << "Up  " << flush;
698                }
699#endif
700            }
701
702            /* Unknown event */
703            return CACA_EVENT_NONE;
704        }
705
706        /* No event */
707        return CACA_EVENT_NONE;
708    }
709    else
710#endif
711#if defined(USE_GL)
712    if(kk->driver.driver == CACA_DRIVER_GL)
713    {
714        glutMainLoopEvent();
715
716        if(kk->gl.resized && !kk->resize)
717        {
718            kk->resize = 1;
719            kk->gl.resized = 0;
720            return CACA_EVENT_RESIZE;
721        }
722
723        if(kk->gl.mouse_changed)
724        {
725            if(kk->gl.mouse_clicked)
726            {
727                event|= CACA_EVENT_MOUSE_PRESS | kk->gl.mouse_button;
728                kk->gl.mouse_clicked=0;
729            }
730            kk->mouse_x = kk->gl.mouse_x;
731            kk->mouse_y = kk->gl.mouse_y;
732            event |= CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y;
733            kk->gl.mouse_changed = 0;
734        }
735
736        if(kk->gl.key != 0)
737        {
738            event |= CACA_EVENT_KEY_PRESS;
739            event |= kk->gl.key;
740            kk->gl.key = 0;
741            return event;
742        }
743
744        if(kk->gl.special_key != 0)
745        {
746            event |= CACA_EVENT_KEY_PRESS;
747     
748            switch(kk->gl.special_key)
749            {
750                case GLUT_KEY_F1 : kk->gl.special_key = 0; return event | CACA_KEY_F1;
751                case GLUT_KEY_F2 : kk->gl.special_key = 0; return event | CACA_KEY_F2;
752                case GLUT_KEY_F3 : kk->gl.special_key = 0; return event | CACA_KEY_F3;
753                case GLUT_KEY_F4 : kk->gl.special_key = 0; return event | CACA_KEY_F4;
754                case GLUT_KEY_F5 : kk->gl.special_key = 0; return event | CACA_KEY_F5;
755                case GLUT_KEY_F6 : kk->gl.special_key = 0; return event | CACA_KEY_F6;
756                case GLUT_KEY_F7 : kk->gl.special_key = 0; return event | CACA_KEY_F7;
757                case GLUT_KEY_F8 : kk->gl.special_key = 0; return event | CACA_KEY_F8;
758                case GLUT_KEY_F9 : kk->gl.special_key = 0; return event | CACA_KEY_F9;
759                case GLUT_KEY_F10: kk->gl.special_key = 0; return event | CACA_KEY_F10;
760                case GLUT_KEY_F11: kk->gl.special_key = 0; return event | CACA_KEY_F11;
761                case GLUT_KEY_F12: kk->gl.special_key = 0; return event | CACA_KEY_F12;
762                case GLUT_KEY_LEFT : kk->gl.special_key = 0; return event | CACA_KEY_LEFT;
763                case GLUT_KEY_RIGHT: kk->gl.special_key = 0; return event | CACA_KEY_RIGHT;
764                case GLUT_KEY_UP   : kk->gl.special_key = 0; return event | CACA_KEY_UP;
765                case GLUT_KEY_DOWN : kk->gl.special_key = 0; return event | CACA_KEY_DOWN;
766                default: return CACA_EVENT_NONE;
767            }
768        }
769        return CACA_EVENT_NONE;
770    }
771    else
772#endif
773    {
774        /* Dummy */
775    }
776
777    return CACA_EVENT_NONE;
778}
779
780#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO)
781static void _push_event(caca_t *kk, unsigned int event)
782{
783    if(!event || kk->events.queue == EVENTBUF_LEN)
784        return;
785    kk->events.buf[kk->events.queue] = event;
786    kk->events.queue++;
787}
788
789static unsigned int _pop_event(caca_t *kk)
790{
791    int i;
792    unsigned int event;
793
794    if(kk->events.queue == 0)
795        return CACA_EVENT_NONE;
796
797    event = kk->events.buf[0];
798    for(i = 1; i < kk->events.queue; i++)
799        kk->events.buf[i - 1] = kk->events.buf[i];
800    kk->events.queue--;
801
802    return event;
803}
804#endif
805
Note: See TracBrowser for help on using the repository browser.