diff --git a/caca/caca_internals.h b/caca/caca_internals.h index ee2c455..9c197b8 100644 --- a/caca/caca_internals.h +++ b/caca/caca_internals.h @@ -119,6 +119,7 @@ struct caca_context unsigned int (* get_window_height) (caca_t *); void (* display) (caca_t *); void (* handle_resize) (caca_t *, unsigned int *, unsigned int *); + unsigned int (* get_event) (caca_t *); } driver; //unsigned int width, height; diff --git a/caca/driver_conio.c b/caca/driver_conio.c index 17cce3a..8a134fa 100644 --- a/caca/driver_conio.c +++ b/caca/driver_conio.c @@ -120,6 +120,18 @@ static void conio_handle_resize(caca_t *kk, unsigned int *new_width, *new_height = kk->qq->height; } +static unsigned int conio_get_event(caca_t *kk) +{ + unsigned int event; + + if(!_conio_kbhit()) + return CACA_EVENT_NONE; + + event = getch(); + _push_event(kk, CACA_EVENT_KEY_RELEASE | event); + return CACA_EVENT_KEY_PRESS | event; +} + /* * Driver initialisation */ @@ -135,6 +147,7 @@ void conio_init_driver(caca_t *kk) kk->driver.get_window_height = conio_get_window_height; kk->driver.display = conio_display; kk->driver.handle_resize = conio_handle_resize; + kk->driver.get_event = conio_get_event; } #endif /* USE_CONIO */ diff --git a/caca/driver_gl.c b/caca/driver_gl.c index 15bf24f..de429a2 100644 --- a/caca/driver_gl.c +++ b/caca/driver_gl.c @@ -292,6 +292,68 @@ static void gl_handle_resize(caca_t *kk, unsigned int *new_width, glMatrixMode(GL_MODELVIEW); } +static unsigned int gl_get_event(caca_t *kk) +{ + unsigned int event = 0; + + glutMainLoopEvent(); + + if(kk->gl.resized && !kk->resize) + { + kk->resize = 1; + kk->gl.resized = 0; + return CACA_EVENT_RESIZE; + } + + if(kk->gl.mouse_changed) + { + if(kk->gl.mouse_clicked) + { + event |= CACA_EVENT_MOUSE_PRESS | kk->gl.mouse_button; + kk->gl.mouse_clicked = 0; + } + kk->mouse_x = kk->gl.mouse_x; + kk->mouse_y = kk->gl.mouse_y; + event |= CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; + kk->gl.mouse_changed = 0; + } + + if(kk->gl.key != 0) + { + event |= CACA_EVENT_KEY_PRESS; + event |= kk->gl.key; + kk->gl.key = 0; + return event; + } + + if(kk->gl.special_key != 0) + { + event |= CACA_EVENT_KEY_PRESS; + + switch(kk->gl.special_key) + { + case GLUT_KEY_F1 : kk->gl.special_key = 0; return event | CACA_KEY_F1; + case GLUT_KEY_F2 : kk->gl.special_key = 0; return event | CACA_KEY_F2; + case GLUT_KEY_F3 : kk->gl.special_key = 0; return event | CACA_KEY_F3; + case GLUT_KEY_F4 : kk->gl.special_key = 0; return event | CACA_KEY_F4; + case GLUT_KEY_F5 : kk->gl.special_key = 0; return event | CACA_KEY_F5; + case GLUT_KEY_F6 : kk->gl.special_key = 0; return event | CACA_KEY_F6; + case GLUT_KEY_F7 : kk->gl.special_key = 0; return event | CACA_KEY_F7; + case GLUT_KEY_F8 : kk->gl.special_key = 0; return event | CACA_KEY_F8; + case GLUT_KEY_F9 : kk->gl.special_key = 0; return event | CACA_KEY_F9; + case GLUT_KEY_F10: kk->gl.special_key = 0; return event | CACA_KEY_F10; + case GLUT_KEY_F11: kk->gl.special_key = 0; return event | CACA_KEY_F11; + case GLUT_KEY_F12: kk->gl.special_key = 0; return event | CACA_KEY_F12; + case GLUT_KEY_LEFT : kk->gl.special_key = 0; return event | CACA_KEY_LEFT; + case GLUT_KEY_RIGHT: kk->gl.special_key = 0; return event | CACA_KEY_RIGHT; + case GLUT_KEY_UP : kk->gl.special_key = 0; return event | CACA_KEY_UP; + case GLUT_KEY_DOWN : kk->gl.special_key = 0; return event | CACA_KEY_DOWN; + default: return CACA_EVENT_NONE; + } + } + return CACA_EVENT_NONE; +} + /* * XXX: following functions are local */ @@ -361,6 +423,7 @@ void gl_init_driver(caca_t *kk) kk->driver.get_window_height = gl_get_window_height; kk->driver.display = gl_display; kk->driver.handle_resize = gl_handle_resize; + kk->driver.get_event = gl_get_event; } #endif /* USE_GL */ diff --git a/caca/driver_ncurses.c b/caca/driver_ncurses.c index 500220e..86a08d7 100644 --- a/caca/driver_ncurses.c +++ b/caca/driver_ncurses.c @@ -208,6 +208,189 @@ static void ncurses_handle_resize(caca_t *kk, unsigned int *new_width, } } +static unsigned int ncurses_get_event(caca_t *kk) +{ + unsigned int event; + int intkey; + + if(kk->resize_event) + { + kk->resize_event = 0; + kk->resize = 1; + return CACA_EVENT_RESIZE; + } + + intkey = getch(); + if(intkey == ERR) + return CACA_EVENT_NONE; + + if(intkey < 0x100) + { + return CACA_EVENT_KEY_PRESS | intkey; + } + + if(intkey == KEY_MOUSE) + { + MEVENT mevent; + getmouse(&mevent); + + switch(mevent.bstate) + { + case BUTTON1_PRESSED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); + break; + case BUTTON1_RELEASED: + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); + break; + case BUTTON1_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); + break; + case BUTTON1_DOUBLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); + break; + case BUTTON1_TRIPLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); + break; + case BUTTON1_RESERVED_EVENT: + break; + + case BUTTON2_PRESSED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); + break; + case BUTTON2_RELEASED: + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); + break; + case BUTTON2_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); + break; + case BUTTON2_DOUBLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); + break; + case BUTTON2_TRIPLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); + break; + case BUTTON2_RESERVED_EVENT: + break; + + case BUTTON3_PRESSED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); + break; + case BUTTON3_RELEASED: + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); + break; + case BUTTON3_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); + break; + case BUTTON3_DOUBLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); + break; + case BUTTON3_TRIPLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); + break; + case BUTTON3_RESERVED_EVENT: + break; + + case BUTTON4_PRESSED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); + break; + case BUTTON4_RELEASED: + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); + break; + case BUTTON4_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); + break; + case BUTTON4_DOUBLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); + break; + case BUTTON4_TRIPLE_CLICKED: + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); + _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); + break; + case BUTTON4_RESERVED_EVENT: + break; + + default: + break; + } + + if(kk->mouse_x == (unsigned int)mevent.x && + kk->mouse_y == (unsigned int)mevent.y) + return _pop_event(kk); + + kk->mouse_x = mevent.x; + kk->mouse_y = mevent.y; + + return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; + } + + event = CACA_EVENT_KEY_PRESS; + + switch(intkey) + { + case KEY_UP: return event | CACA_KEY_UP; + case KEY_DOWN: return event | CACA_KEY_DOWN; + case KEY_LEFT: return event | CACA_KEY_LEFT; + case KEY_RIGHT: return event | CACA_KEY_RIGHT; + + case KEY_IC: return event | CACA_KEY_INSERT; + case KEY_DC: return event | CACA_KEY_DELETE; + case KEY_HOME: return event | CACA_KEY_HOME; + case KEY_END: return event | CACA_KEY_END; + case KEY_PPAGE: return event | CACA_KEY_PAGEUP; + case KEY_NPAGE: return event | CACA_KEY_PAGEDOWN; + + case KEY_F(1): return event | CACA_KEY_F1; + case KEY_F(2): return event | CACA_KEY_F2; + case KEY_F(3): return event | CACA_KEY_F3; + case KEY_F(4): return event | CACA_KEY_F4; + case KEY_F(5): return event | CACA_KEY_F5; + case KEY_F(6): return event | CACA_KEY_F6; + case KEY_F(7): return event | CACA_KEY_F7; + case KEY_F(8): return event | CACA_KEY_F8; + case KEY_F(9): return event | CACA_KEY_F9; + case KEY_F(10): return event | CACA_KEY_F10; + case KEY_F(11): return event | CACA_KEY_F11; + case KEY_F(12): return event | CACA_KEY_F12; + } + + return CACA_EVENT_NONE; +} + /* * XXX: following functions are local */ @@ -236,6 +419,7 @@ void ncurses_init_driver(caca_t *kk) kk->driver.get_window_height = ncurses_get_window_height; kk->driver.display = ncurses_display; kk->driver.handle_resize = ncurses_handle_resize; + kk->driver.get_event = ncurses_get_event; } #endif /* USE_NCURSES */ diff --git a/caca/driver_slang.c b/caca/driver_slang.c index 10b70de..f5d9494 100644 --- a/caca/driver_slang.c +++ b/caca/driver_slang.c @@ -245,6 +245,88 @@ static void slang_handle_resize(caca_t *kk, unsigned int *new_width, SLsmg_reinit_smg(); } +static unsigned int slang_get_event(caca_t *kk) +{ + unsigned int event; + int intkey; + + if(kk->resize_event) + { + kk->resize_event = 0; + kk->resize = 1; + return CACA_EVENT_RESIZE; + } + + if(!SLang_input_pending(0)) + return CACA_EVENT_NONE; + + /* We first use SLang_getkey() to see whether Esc was pressed + * alone, then (if it wasn't) we unget the key and use SLkp_getkey() + * instead, so that escape sequences are interpreted. */ + intkey = SLang_getkey(); + + if(intkey != 0x1b /* Esc */ || SLang_input_pending(0)) + { + SLang_ungetkey(intkey); + intkey = SLkp_getkey(); + } + + /* If the key was ASCII, return it immediately */ + if(intkey < 0x100) + { + return CACA_EVENT_KEY_PRESS | intkey; + } + + if(intkey == 0x3e9) + { + int button = (SLang_getkey() - ' ' + 1) & 0xf; + unsigned int x = SLang_getkey() - '!'; + unsigned int y = SLang_getkey() - '!'; + _push_event(kk, CACA_EVENT_MOUSE_PRESS | button); + _push_event(kk, CACA_EVENT_MOUSE_RELEASE | button); + + if(kk->mouse_x == x && kk->mouse_y == y) + return _pop_event(kk); + + kk->mouse_x = x; + kk->mouse_y = y; + + return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; + } + + event = CACA_EVENT_KEY_PRESS; + + switch(intkey) + { + case SL_KEY_UP: return event | CACA_KEY_UP; + case SL_KEY_DOWN: return event | CACA_KEY_DOWN; + case SL_KEY_LEFT: return event | CACA_KEY_LEFT; + case SL_KEY_RIGHT: return event | CACA_KEY_RIGHT; + + case SL_KEY_IC: return event | CACA_KEY_INSERT; + case SL_KEY_DELETE: return event | CACA_KEY_DELETE; + case SL_KEY_HOME: return event | CACA_KEY_HOME; + case SL_KEY_END: return event | CACA_KEY_END; + case SL_KEY_PPAGE: return event | CACA_KEY_PAGEUP; + case SL_KEY_NPAGE: return event | CACA_KEY_PAGEDOWN; + + case SL_KEY_F(1): return event | CACA_KEY_F1; + case SL_KEY_F(2): return event | CACA_KEY_F2; + case SL_KEY_F(3): return event | CACA_KEY_F3; + case SL_KEY_F(4): return event | CACA_KEY_F4; + case SL_KEY_F(5): return event | CACA_KEY_F5; + case SL_KEY_F(6): return event | CACA_KEY_F6; + case SL_KEY_F(7): return event | CACA_KEY_F7; + case SL_KEY_F(8): return event | CACA_KEY_F8; + case SL_KEY_F(9): return event | CACA_KEY_F9; + case SL_KEY_F(10): return event | CACA_KEY_F10; + case SL_KEY_F(11): return event | CACA_KEY_F11; + case SL_KEY_F(12): return event | CACA_KEY_F12; + } + + return CACA_EVENT_NONE; +} + /* * XXX: following functions are local */ @@ -316,6 +398,7 @@ void slang_init_driver(caca_t *kk) kk->driver.get_window_height = slang_get_window_height; kk->driver.display = slang_display; kk->driver.handle_resize = slang_handle_resize; + kk->driver.get_event = slang_get_event; } #endif /* USE_SLANG */ diff --git a/caca/driver_win32.c b/caca/driver_win32.c index 2e6ceb3..44225fa 100644 --- a/caca/driver_win32.c +++ b/caca/driver_win32.c @@ -216,6 +216,80 @@ static void win32_handle_resize(caca_t *kk, unsigned int *new_width, *new_height = kk->qq->height; } +static unsigned int win32_get_event(caca_t *kk) +{ + INPUT_RECORD rec; + DWORD num; + + for( ; ; ) + { + GetNumberOfConsoleInputEvents(kk->win32.hin, &num); + if(num == 0) + break; + + ReadConsoleInput(kk->win32.hin, &rec, 1, &num); + if(rec.EventType == KEY_EVENT) + { + unsigned int event; + + if(rec.Event.KeyEvent.bKeyDown) + event = CACA_EVENT_KEY_PRESS; + else + event = CACA_EVENT_KEY_RELEASE; + + if(rec.Event.KeyEvent.uChar.AsciiChar) + return event | rec.Event.KeyEvent.uChar.AsciiChar; + } + + if(rec.EventType == MOUSE_EVENT) + { + if(rec.Event.MouseEvent.dwEventFlags == 0) + { + if(rec.Event.MouseEvent.dwButtonState & 0x01) + return CACA_EVENT_MOUSE_PRESS | 0x000001; + + if(rec.Event.MouseEvent.dwButtonState & 0x02) + return CACA_EVENT_MOUSE_PRESS | 0x000002; + } + else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED) + { + COORD pos = rec.Event.MouseEvent.dwMousePosition; + + if(kk->mouse_x == (unsigned int)pos.X && + kk->mouse_y == (unsigned int)pos.Y) + continue; + + kk->mouse_x = pos.X; + kk->mouse_y = pos.Y; + + return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; + } +#if 0 + else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) + { + cout << rec.Event.MouseEvent.dwMousePosition.X << "," << + rec.Event.MouseEvent.dwMousePosition.Y << " " << flush; + } + else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED) + { + SetConsoleCursorPosition(hOut, + WheelWhere); + if(rec.Event.MouseEvent.dwButtonState & 0xFF000000) + cout << "Down" << flush; + else + cout << "Up " << flush; + } +#endif + } + + /* Unknown event */ + return CACA_EVENT_NONE; + } + + /* No event */ + return CACA_EVENT_NONE; +} + /* * Driver initialisation */ @@ -231,6 +305,7 @@ void win32_init_driver(caca_t *kk) kk->driver.get_window_height = win32_get_window_height; kk->driver.display = win32_display; kk->driver.handle_resize = win32_handle_resize; + kk->driver.get_event = win32_get_event; } #endif /* USE_WIN32 */ diff --git a/caca/driver_x11.c b/caca/driver_x11.c index 2be2b62..8084e5b 100644 --- a/caca/driver_x11.c +++ b/caca/driver_x11.c @@ -22,6 +22,8 @@ #if defined(USE_X11) #include +#include +#include #if defined(HAVE_X11_XKBLIB_H) # include #endif @@ -162,9 +164,9 @@ static int x11_init_graphics(caca_t *kk) for(;;) { - XEvent event; - XNextEvent(kk->x11.dpy, &event); - if (event.type == MapNotify) + XEvent xevent; + XNextEvent(kk->x11.dpy, &xevent); + if (xevent.type == MapNotify) break; } @@ -311,11 +313,126 @@ static void x11_handle_resize(caca_t *kk, unsigned int *new_width, kk->x11.pixmap = new_pixmap; } +static unsigned int x11_get_event(caca_t *kk) +{ + unsigned int event = 0; + XEvent xevent; + char key; + + while(XCheckWindowEvent(kk->x11.dpy, kk->x11.window, + kk->x11.event_mask, &xevent) == True) + { + KeySym keysym; + + /* Expose event */ + if(xevent.type == Expose) + { + XCopyArea(kk->x11.dpy, kk->x11.pixmap, + kk->x11.window, kk->x11.gc, 0, 0, + kk->qq->width * kk->x11.font_width, + kk->qq->height * kk->x11.font_height, 0, 0); + continue; + } + + /* Resize event */ + if(xevent.type == ConfigureNotify) + { + unsigned int w, h; + + w = (xevent.xconfigure.width + kk->x11.font_width / 3) + / kk->x11.font_width; + h = (xevent.xconfigure.height + kk->x11.font_height / 3) + / kk->x11.font_height; + + if(!w || !h || (w == kk->qq->width && h == kk->qq->height)) + continue; + + kk->x11.new_width = w; + kk->x11.new_height = h; + + /* If we are already resizing, ignore the new signal */ + if(kk->resize) + continue; + + kk->resize = 1; + + return CACA_EVENT_RESIZE; + } + + /* Check for mouse motion events */ + if(xevent.type == MotionNotify) + { + unsigned int newx = xevent.xmotion.x / kk->x11.font_width; + unsigned int newy = xevent.xmotion.y / kk->x11.font_height; + + if(newx >= kk->qq->width) + newx = kk->qq->width - 1; + if(newy >= kk->qq->height) + newy = kk->qq->height - 1; + + if(kk->mouse_x == newx && kk->mouse_y == newy) + continue; + + kk->mouse_x = newx; + kk->mouse_y = newy; + + return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; + } + + /* Check for mouse press and release events */ + if(xevent.type == ButtonPress) + return CACA_EVENT_MOUSE_PRESS + | ((XButtonEvent *)&xevent)->button; + + if(xevent.type == ButtonRelease) + return CACA_EVENT_MOUSE_RELEASE + | ((XButtonEvent *)&xevent)->button; + + /* Check for key press and release events */ + if(xevent.type == KeyPress) + event |= CACA_EVENT_KEY_PRESS; + else if(xevent.type == KeyRelease) + event |= CACA_EVENT_KEY_RELEASE; + else + continue; + + if(XLookupString(&xevent.xkey, &key, 1, NULL, NULL)) + return event | key; + + keysym = XKeycodeToKeysym(kk->x11.dpy, xevent.xkey.keycode, 0); + switch(keysym) + { + case XK_F1: return event | CACA_KEY_F1; + case XK_F2: return event | CACA_KEY_F2; + case XK_F3: return event | CACA_KEY_F3; + case XK_F4: return event | CACA_KEY_F4; + case XK_F5: return event | CACA_KEY_F5; + case XK_F6: return event | CACA_KEY_F6; + case XK_F7: return event | CACA_KEY_F7; + case XK_F8: return event | CACA_KEY_F8; + case XK_F9: return event | CACA_KEY_F9; + case XK_F10: return event | CACA_KEY_F10; + case XK_F11: return event | CACA_KEY_F11; + case XK_F12: return event | CACA_KEY_F12; + case XK_F13: return event | CACA_KEY_F13; + case XK_F14: return event | CACA_KEY_F14; + case XK_F15: return event | CACA_KEY_F15; + case XK_Left: return event | CACA_KEY_LEFT; + case XK_Right: return event | CACA_KEY_RIGHT; + case XK_Up: return event | CACA_KEY_UP; + case XK_Down: return event | CACA_KEY_DOWN; + default: return CACA_EVENT_NONE; + } + } + + return CACA_EVENT_NONE; +} + /* * XXX: following functions are local */ -static int x11_error_handler(Display *dpy, XErrorEvent *event) +static int x11_error_handler(Display *dpy, XErrorEvent *xevent) { /* Ignore the error */ return 0; @@ -336,6 +453,7 @@ void x11_init_driver(caca_t *kk) kk->driver.get_window_height = x11_get_window_height; kk->driver.display = x11_display; kk->driver.handle_resize = x11_handle_resize; + kk->driver.get_event = x11_get_event; } #endif /* USE_X11 */ diff --git a/caca/event.c b/caca/event.c index 35be182..ea5820e 100644 --- a/caca/event.c +++ b/caca/event.c @@ -19,37 +19,6 @@ #include "config.h" -#if defined(USE_SLANG) -# if defined(HAVE_SLANG_SLANG_H) -# include -# else -# include -# endif -#endif -#if defined(USE_NCURSES) -# if defined(HAVE_NCURSES_H) -# include -# else -# include -# endif -#endif -#if defined(USE_CONIO) -# include -#endif -#if defined(USE_X11) -# include -# include -# include -#endif -#if defined(USE_WIN32) -# include -#endif -#if defined(USE_GL) -#include -#include -#include -#endif - #include "cucul.h" #include "cucul_internals.h" #include "caca.h" @@ -58,8 +27,8 @@ static unsigned int _get_next_event(caca_t *); static unsigned int _lowlevel_event(caca_t *); #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) -static void _push_event(caca_t *, unsigned int); -static unsigned int _pop_event(caca_t *); +void _push_event(caca_t *, unsigned int); +unsigned int _pop_event(caca_t *); #endif #if !defined(_DOXYGEN_SKIP_ME) @@ -229,556 +198,18 @@ static unsigned int _get_next_event(caca_t *kk) static unsigned int _lowlevel_event(caca_t *kk) { - unsigned int event; - #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) - event = _pop_event(kk); + unsigned int event = _pop_event(kk); if(event) return event; #endif -#if defined(USE_X11) - /* The X11 event check routine */ - if(kk->driver.driver == CACA_DRIVER_X11) - { - XEvent xevent; - char key; - - while(XCheckWindowEvent(kk->x11.dpy, kk->x11.window, kk->x11.event_mask, &xevent) - == True) - { - KeySym keysym; - - /* Expose event */ - if(xevent.type == Expose) - { - XCopyArea(kk->x11.dpy, kk->x11.pixmap, - kk->x11.window, kk->x11.gc, 0, 0, - kk->qq->width * kk->x11.font_width, - kk->qq->height * kk->x11.font_height, 0, 0); - continue; - } - - /* Resize event */ - if(xevent.type == ConfigureNotify) - { - unsigned int w, h; - - w = (xevent.xconfigure.width + kk->x11.font_width / 3) - / kk->x11.font_width; - h = (xevent.xconfigure.height + kk->x11.font_height / 3) - / kk->x11.font_height; - - if(!w || !h || (w == kk->qq->width && h == kk->qq->height)) - continue; - - kk->x11.new_width = w; - kk->x11.new_height = h; - - /* If we are already resizing, ignore the new signal */ - if(kk->resize) - continue; - - kk->resize = 1; - - return CACA_EVENT_RESIZE; - } - - /* Check for mouse motion events */ - if(xevent.type == MotionNotify) - { - unsigned int newx = xevent.xmotion.x / kk->x11.font_width; - unsigned int newy = xevent.xmotion.y / kk->x11.font_height; - - if(newx >= kk->qq->width) - newx = kk->qq->width - 1; - if(newy >= kk->qq->height) - newy = kk->qq->height - 1; - - if(kk->mouse_x == newx && kk->mouse_y == newy) - continue; - - kk->mouse_x = newx; - kk->mouse_y = newy; - - return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; - } - - /* Check for mouse press and release events */ - if(xevent.type == ButtonPress) - return CACA_EVENT_MOUSE_PRESS - | ((XButtonEvent *)&xevent)->button; - - if(xevent.type == ButtonRelease) - return CACA_EVENT_MOUSE_RELEASE - | ((XButtonEvent *)&xevent)->button; - - /* Check for key press and release events */ - if(xevent.type == KeyPress) - event |= CACA_EVENT_KEY_PRESS; - else if(xevent.type == KeyRelease) - event |= CACA_EVENT_KEY_RELEASE; - else - continue; - - if(XLookupString(&xevent.xkey, &key, 1, NULL, NULL)) - return event | key; - - keysym = XKeycodeToKeysym(kk->x11.dpy, xevent.xkey.keycode, 0); - switch(keysym) - { - case XK_F1: return event | CACA_KEY_F1; - case XK_F2: return event | CACA_KEY_F2; - case XK_F3: return event | CACA_KEY_F3; - case XK_F4: return event | CACA_KEY_F4; - case XK_F5: return event | CACA_KEY_F5; - case XK_F6: return event | CACA_KEY_F6; - case XK_F7: return event | CACA_KEY_F7; - case XK_F8: return event | CACA_KEY_F8; - case XK_F9: return event | CACA_KEY_F9; - case XK_F10: return event | CACA_KEY_F10; - case XK_F11: return event | CACA_KEY_F11; - case XK_F12: return event | CACA_KEY_F12; - case XK_F13: return event | CACA_KEY_F13; - case XK_F14: return event | CACA_KEY_F14; - case XK_F15: return event | CACA_KEY_F15; - case XK_Left: return event | CACA_KEY_LEFT; - case XK_Right: return event | CACA_KEY_RIGHT; - case XK_Up: return event | CACA_KEY_UP; - case XK_Down: return event | CACA_KEY_DOWN; - default: return CACA_EVENT_NONE; - } - } - - return CACA_EVENT_NONE; - } - else -#endif -#if defined(USE_NCURSES) - if(kk->driver.driver == CACA_DRIVER_NCURSES) - { - int intkey; - - if(kk->resize_event) - { - kk->resize_event = 0; - kk->resize = 1; - return CACA_EVENT_RESIZE; - } - - intkey = getch(); - if(intkey == ERR) - return CACA_EVENT_NONE; - - if(intkey < 0x100) - { - return CACA_EVENT_KEY_PRESS | intkey; - } - - if(intkey == KEY_MOUSE) - { - MEVENT mevent; - getmouse(&mevent); - - switch(mevent.bstate) - { - case BUTTON1_PRESSED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); - break; - case BUTTON1_RELEASED: - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); - break; - case BUTTON1_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); - break; - case BUTTON1_DOUBLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); - break; - case BUTTON1_TRIPLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 1); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 1); - break; - case BUTTON1_RESERVED_EVENT: - break; - - case BUTTON2_PRESSED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); - break; - case BUTTON2_RELEASED: - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); - break; - case BUTTON2_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); - break; - case BUTTON2_DOUBLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); - break; - case BUTTON2_TRIPLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 2); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 2); - break; - case BUTTON2_RESERVED_EVENT: - break; - - case BUTTON3_PRESSED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); - break; - case BUTTON3_RELEASED: - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); - break; - case BUTTON3_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); - break; - case BUTTON3_DOUBLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); - break; - case BUTTON3_TRIPLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 3); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 3); - break; - case BUTTON3_RESERVED_EVENT: - break; - - case BUTTON4_PRESSED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); - break; - case BUTTON4_RELEASED: - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); - break; - case BUTTON4_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); - break; - case BUTTON4_DOUBLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); - break; - case BUTTON4_TRIPLE_CLICKED: - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); - _push_event(kk, CACA_EVENT_MOUSE_PRESS | 4); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | 4); - break; - case BUTTON4_RESERVED_EVENT: - break; - - default: - break; - } - - if(kk->mouse_x == (unsigned int)mevent.x && - kk->mouse_y == (unsigned int)mevent.y) - return _pop_event(kk); - - kk->mouse_x = mevent.x; - kk->mouse_y = mevent.y; - - return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; - } - - event = CACA_EVENT_KEY_PRESS; - - switch(intkey) - { - case KEY_UP: return event | CACA_KEY_UP; - case KEY_DOWN: return event | CACA_KEY_DOWN; - case KEY_LEFT: return event | CACA_KEY_LEFT; - case KEY_RIGHT: return event | CACA_KEY_RIGHT; - - case KEY_IC: return event | CACA_KEY_INSERT; - case KEY_DC: return event | CACA_KEY_DELETE; - case KEY_HOME: return event | CACA_KEY_HOME; - case KEY_END: return event | CACA_KEY_END; - case KEY_PPAGE: return event | CACA_KEY_PAGEUP; - case KEY_NPAGE: return event | CACA_KEY_PAGEDOWN; - - case KEY_F(1): return event | CACA_KEY_F1; - case KEY_F(2): return event | CACA_KEY_F2; - case KEY_F(3): return event | CACA_KEY_F3; - case KEY_F(4): return event | CACA_KEY_F4; - case KEY_F(5): return event | CACA_KEY_F5; - case KEY_F(6): return event | CACA_KEY_F6; - case KEY_F(7): return event | CACA_KEY_F7; - case KEY_F(8): return event | CACA_KEY_F8; - case KEY_F(9): return event | CACA_KEY_F9; - case KEY_F(10): return event | CACA_KEY_F10; - case KEY_F(11): return event | CACA_KEY_F11; - case KEY_F(12): return event | CACA_KEY_F12; - } - - return CACA_EVENT_NONE; - } - else -#endif -#if defined(USE_SLANG) - if(kk->driver.driver == CACA_DRIVER_SLANG) - { - int intkey; - - if(kk->resize_event) - { - kk->resize_event = 0; - kk->resize = 1; - return CACA_EVENT_RESIZE; - } - - if(!SLang_input_pending(0)) - return CACA_EVENT_NONE; - - /* We first use SLang_getkey() to see whether Esc was pressed - * alone, then (if it wasn't) we unget the key and use SLkp_getkey() - * instead, so that escape sequences are interpreted. */ - intkey = SLang_getkey(); - - if(intkey != 0x1b /* Esc */ || SLang_input_pending(0)) - { - SLang_ungetkey(intkey); - intkey = SLkp_getkey(); - } - - /* If the key was ASCII, return it immediately */ - if(intkey < 0x100) - { - return CACA_EVENT_KEY_PRESS | intkey; - } - - if(intkey == 0x3e9) - { - int button = (SLang_getkey() - ' ' + 1) & 0xf; - unsigned int x = SLang_getkey() - '!'; - unsigned int y = SLang_getkey() - '!'; - _push_event(kk, CACA_EVENT_MOUSE_PRESS | button); - _push_event(kk, CACA_EVENT_MOUSE_RELEASE | button); - - if(kk->mouse_x == x && kk->mouse_y == y) - return _pop_event(kk); - - kk->mouse_x = x; - kk->mouse_y = y; - - return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; - } - - event = CACA_EVENT_KEY_PRESS; - - switch(intkey) - { - case SL_KEY_UP: return event | CACA_KEY_UP; - case SL_KEY_DOWN: return event | CACA_KEY_DOWN; - case SL_KEY_LEFT: return event | CACA_KEY_LEFT; - case SL_KEY_RIGHT: return event | CACA_KEY_RIGHT; - - case SL_KEY_IC: return event | CACA_KEY_INSERT; - case SL_KEY_DELETE: return event | CACA_KEY_DELETE; - case SL_KEY_HOME: return event | CACA_KEY_HOME; - case SL_KEY_END: return event | CACA_KEY_END; - case SL_KEY_PPAGE: return event | CACA_KEY_PAGEUP; - case SL_KEY_NPAGE: return event | CACA_KEY_PAGEDOWN; - - case SL_KEY_F(1): return event | CACA_KEY_F1; - case SL_KEY_F(2): return event | CACA_KEY_F2; - case SL_KEY_F(3): return event | CACA_KEY_F3; - case SL_KEY_F(4): return event | CACA_KEY_F4; - case SL_KEY_F(5): return event | CACA_KEY_F5; - case SL_KEY_F(6): return event | CACA_KEY_F6; - case SL_KEY_F(7): return event | CACA_KEY_F7; - case SL_KEY_F(8): return event | CACA_KEY_F8; - case SL_KEY_F(9): return event | CACA_KEY_F9; - case SL_KEY_F(10): return event | CACA_KEY_F10; - case SL_KEY_F(11): return event | CACA_KEY_F11; - case SL_KEY_F(12): return event | CACA_KEY_F12; - } - - return CACA_EVENT_NONE; - } - else -#endif -#if defined(USE_CONIO) - if(kk->driver.driver == CACA_DRIVER_CONIO) - { - if(!_conio_kbhit()) - return CACA_EVENT_NONE; - - event = getch(); - _push_event(kk, CACA_EVENT_KEY_RELEASE | event); - return CACA_EVENT_KEY_PRESS | event; - } - else -#endif -#if defined(USE_WIN32) - if(kk->driver.driver == CACA_DRIVER_WIN32) - { - INPUT_RECORD rec; - DWORD num; - - for( ; ; ) - { - GetNumberOfConsoleInputEvents(kk->win32.hin, &num); - if(num == 0) - break; - - ReadConsoleInput(kk->win32.hin, &rec, 1, &num); - if(rec.EventType == KEY_EVENT) - { - if(rec.Event.KeyEvent.bKeyDown) - event = CACA_EVENT_KEY_PRESS; - else - event = CACA_EVENT_KEY_RELEASE; - - if(rec.Event.KeyEvent.uChar.AsciiChar) - return event | rec.Event.KeyEvent.uChar.AsciiChar; - } - - if(rec.EventType == MOUSE_EVENT) - { - if(rec.Event.MouseEvent.dwEventFlags == 0) - { - if(rec.Event.MouseEvent.dwButtonState & 0x01) - return CACA_EVENT_MOUSE_PRESS | 0x000001; - - if(rec.Event.MouseEvent.dwButtonState & 0x02) - return CACA_EVENT_MOUSE_PRESS | 0x000002; - } - else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED) - { - COORD pos = rec.Event.MouseEvent.dwMousePosition; - - if(kk->mouse_x == (unsigned int)pos.X && - kk->mouse_y == (unsigned int)pos.Y) - continue; - - kk->mouse_x = pos.X; - kk->mouse_y = pos.Y; - - return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; - } -#if 0 - else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) - { - cout << rec.Event.MouseEvent.dwMousePosition.X << "," << - rec.Event.MouseEvent.dwMousePosition.Y << " " << flush; - } - else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED) - { - SetConsoleCursorPosition(hOut, - WheelWhere); - if(rec.Event.MouseEvent.dwButtonState & 0xFF000000) - cout << "Down" << flush; - else - cout << "Up " << flush; - } -#endif - } - - /* Unknown event */ - return CACA_EVENT_NONE; - } - - /* No event */ - return CACA_EVENT_NONE; - } - else -#endif -#if defined(USE_GL) - if(kk->driver.driver == CACA_DRIVER_GL) - { - glutMainLoopEvent(); - - if(kk->gl.resized && !kk->resize) - { - kk->resize = 1; - kk->gl.resized = 0; - return CACA_EVENT_RESIZE; - } - - if(kk->gl.mouse_changed) - { - if(kk->gl.mouse_clicked) - { - event|= CACA_EVENT_MOUSE_PRESS | kk->gl.mouse_button; - kk->gl.mouse_clicked=0; - } - kk->mouse_x = kk->gl.mouse_x; - kk->mouse_y = kk->gl.mouse_y; - event |= CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y; - kk->gl.mouse_changed = 0; - } - - if(kk->gl.key != 0) - { - event |= CACA_EVENT_KEY_PRESS; - event |= kk->gl.key; - kk->gl.key = 0; - return event; - } - - if(kk->gl.special_key != 0) - { - event |= CACA_EVENT_KEY_PRESS; - - switch(kk->gl.special_key) - { - case GLUT_KEY_F1 : kk->gl.special_key = 0; return event | CACA_KEY_F1; - case GLUT_KEY_F2 : kk->gl.special_key = 0; return event | CACA_KEY_F2; - case GLUT_KEY_F3 : kk->gl.special_key = 0; return event | CACA_KEY_F3; - case GLUT_KEY_F4 : kk->gl.special_key = 0; return event | CACA_KEY_F4; - case GLUT_KEY_F5 : kk->gl.special_key = 0; return event | CACA_KEY_F5; - case GLUT_KEY_F6 : kk->gl.special_key = 0; return event | CACA_KEY_F6; - case GLUT_KEY_F7 : kk->gl.special_key = 0; return event | CACA_KEY_F7; - case GLUT_KEY_F8 : kk->gl.special_key = 0; return event | CACA_KEY_F8; - case GLUT_KEY_F9 : kk->gl.special_key = 0; return event | CACA_KEY_F9; - case GLUT_KEY_F10: kk->gl.special_key = 0; return event | CACA_KEY_F10; - case GLUT_KEY_F11: kk->gl.special_key = 0; return event | CACA_KEY_F11; - case GLUT_KEY_F12: kk->gl.special_key = 0; return event | CACA_KEY_F12; - case GLUT_KEY_LEFT : kk->gl.special_key = 0; return event | CACA_KEY_LEFT; - case GLUT_KEY_RIGHT: kk->gl.special_key = 0; return event | CACA_KEY_RIGHT; - case GLUT_KEY_UP : kk->gl.special_key = 0; return event | CACA_KEY_UP; - case GLUT_KEY_DOWN : kk->gl.special_key = 0; return event | CACA_KEY_DOWN; - default: return CACA_EVENT_NONE; - } - } - return CACA_EVENT_NONE; - } - else -#endif - { - /* Dummy */ - } - - return CACA_EVENT_NONE; + return kk->driver.get_event(kk); } #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) -static void _push_event(caca_t *kk, unsigned int event) +void _push_event(caca_t *kk, unsigned int event) { if(!event || kk->events.queue == EVENTBUF_LEN) return; @@ -786,7 +217,7 @@ static void _push_event(caca_t *kk, unsigned int event) kk->events.queue++; } -static unsigned int _pop_event(caca_t *kk) +unsigned int _pop_event(caca_t *kk) { int i; unsigned int event;