# HG changeset patch # User Radek Brich # Date 1359571441 -3600 # Node ID 6e065660075485e4c81031aacff895e975428a74 # Parent cfd3445107b4d8c89c901f341692029bffbcee17 DriverSDL: Fix event dispatching. Add SDL events test. diff -r cfd3445107b4 -r 6e0656600754 .hgignore --- a/.hgignore Wed Jan 30 00:38:48 2013 +0100 +++ b/.hgignore Wed Jan 30 19:44:01 2013 +0100 @@ -6,7 +6,7 @@ ^sdlterm/build ^sdlterm/font ^sdlterm/cython/sdlterm.cpp$ -^sdlterm/demo$ +^sdlterm/test_ ^(.*/)?\.c?project$ ^(.*/)?\.pydevproject$ ^\.settings diff -r cfd3445107b4 -r 6e0656600754 sdlterm/Makefile --- a/sdlterm/Makefile Wed Jan 30 00:38:48 2013 +0100 +++ b/sdlterm/Makefile Wed Jan 30 19:44:01 2013 +0100 @@ -1,8 +1,11 @@ CXXFLAGS=`sdl-config --cflags` -g -Wall -std=c++11 -Isrc LDFLAGS=`sdl-config --libs` -lSDL_ttf -VPATH=src +VPATH=src tests -demo: demo.cc sdlterm.cc sdlterm.h +all: test_sdlterm test_sdl_events + +test_sdlterm: test_sdlterm.cc sdlterm.cc sdlterm.h +test_sdl_events: test_sdl_events.cc clean: - rm -f demo + rm -f test_sdlterm test_sdl_events diff -r cfd3445107b4 -r 6e0656600754 sdlterm/demo.cc --- a/sdlterm/demo.cc Wed Jan 30 00:38:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -#include "sdlterm.h" - - -class Application -{ -public: - Terminal term; - bool done; - - Application() : term(), done(false) {}; - - void init(); - void wait_and_process_event(); -}; - - -void Application::init() -{ - term.resize(800, 600); - term.select_font("font/DejaVuSansMono.ttf", "font/DejaVuSansMono-Bold.ttf", 12); - term.erase(); - - char hello[] = "Hello World!"; - for (int bg = 0; bg < 16; bg++) - { - for (int fg = 0; fg < 16; fg++) - { - for (char *c = hello; *c; c++) - { - term.set_attr( term.prepare_attr(fg, bg, 1) ); - term.putch(5 + 6 * bg + (c - hello), 5 + fg, *c); - } - } - } - term.commit(); -} - - -void Application::wait_and_process_event() -{ - Event event; - term.wait_event(event, 0); - - switch (event.type) - { - case Event::QUIT: - done = true; - break; - - default: - break; - } -} - - -int main(int argc, char *argv[]) -{ - Application app; - app.init(); - - while (!app.done) - { - app.wait_and_process_event(); - } - - return 0; -} - diff -r cfd3445107b4 -r 6e0656600754 sdlterm/demo.py --- a/sdlterm/demo.py Wed Jan 30 00:38:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from sdlterm import SDLTerminal - -if __name__ == '__main__': - term = SDLTerminal() - term.resize(800, 600) - term.select_font(b"font/DejaVuSansMono.ttf", b"font/DejaVuSansMono-Bold.ttf", 12) - term.erase() - term.putch(5, 5, 'W') - term.commit() - - while True: - event = term.wait_event() - print(event) - if event[0] == 'keypress' and event[1] == 'escape': - break - diff -r cfd3445107b4 -r 6e0656600754 sdlterm/src/sdlterm.cc --- a/sdlterm/src/sdlterm.cc Wed Jan 30 00:38:48 2013 +0100 +++ b/sdlterm/src/sdlterm.cc Wed Jan 30 19:44:01 2013 +0100 @@ -371,6 +371,17 @@ bool Terminal::wait_event(Event &event, Uint32 timeout) { + SDL_Event sdl_event; + bool translated; + + // any events pending? + while (SDL_PollEvent(&sdl_event)) + { + translated = _handle_event(sdl_event, event); + if (translated) + return true; + } + // use timer to simulate SDL_WaitEventTimeout, which is not available in SDL 1.2 SDL_TimerID timer_id = NULL; if (timeout) @@ -379,104 +390,25 @@ } // loop until we have something to return - SDL_Event sdl_event; bool event_ready = false; - while (SDL_WaitEvent(&sdl_event) && !event_ready) + while (!event_ready && SDL_WaitEvent(&sdl_event)) { - switch (sdl_event.type) + do { - case SDL_USEREVENT: - // timeout - if (sdl_event.user.code == 1) - { - SDL_RemoveTimer(timer_id); - return false; - } - // toggle blink - if (sdl_event.user.code == 2) - { - _screen.toggle_blink(); - } - break; // continue loop - - case SDL_QUIT: - event.type = Event::QUIT; - event_ready = true; - break; - - case SDL_VIDEORESIZE: - event.type = Event::RESIZE; - _screen.resize(sdl_event.resize.w, sdl_event.resize.h); - event_ready = true; - break; - - case SDL_VIDEOEXPOSE: - _screen.redraw(); - break; - - case SDL_KEYDOWN: + translated = _handle_event(sdl_event, event); + if (translated) { - //switch(event.key.keysym.sym) - event.type = Event::KEYPRESS; - const char *keyname = _translate_keyname(sdl_event.key.keysym.sym); - // return only keyname or unicode, never both - if (keyname) - { - strncpy(event.key.keyname, keyname, 10); - event.key.unicode = 0; - } - else - { - event.key.keyname[0] = 0; - event.key.unicode = sdl_event.key.keysym.unicode; - if (!event.key.unicode) - break; // continue loop (unknown key) - } - event.key.mod = _translate_mod(sdl_event.key.keysym.mod); event_ready = true; break; } - - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - event.type = (sdl_event.type == SDL_MOUSEBUTTONDOWN) ? Event::MOUSEDOWN : Event::MOUSEUP; - event.mouse.x = sdl_event.button.x / _screen.get_cell_width(); - event.mouse.y = sdl_event.button.y / _screen.get_cell_height(); - event.mouse.button = sdl_event.button.button; - if (sdl_event.button.button == SDL_BUTTON_WHEELUP || sdl_event.button.button == SDL_BUTTON_WHEELDOWN) - { - if (sdl_event.type == SDL_MOUSEBUTTONUP) - break; // do not report button-up events for mouse wheel - event.type = Event::MOUSEWHEEL; - } - _mousemove_last_x = -1; - event_ready = true; - break; - - case SDL_MOUSEMOTION: - if (sdl_event.motion.state == 0) - break; // continue loop, do not report move events when no button is pressed - event.type = Event::MOUSEMOVE; - event.mouse.x = sdl_event.motion.x / _screen.get_cell_width(); - event.mouse.y = sdl_event.motion.y / _screen.get_cell_height(); - if (_mousemove_last_x != event.mouse.x || - _mousemove_last_y != event.mouse.y) - { - if (_mousemove_last_x != -1) - { - event.mouse.relx = event.mouse.x - _mousemove_last_x; - event.mouse.rely = event.mouse.y - _mousemove_last_y; - event_ready = true; - } - _mousemove_last_x = event.mouse.x; - _mousemove_last_y = event.mouse.y; - break; - } - break; // continue loop when mouse position did not change - - default: - break; // continue loop + // timeout? + if (sdl_event.type == SDL_USEREVENT && sdl_event.user.code == 1) + { + SDL_RemoveTimer(timer_id); + return false; + } } + while (!event_ready && SDL_PollEvent(&sdl_event)); } // remove timer when other event came before timeout @@ -497,6 +429,104 @@ } +// return true when SDL_Event was translated to our Event +bool Terminal::_handle_event(const SDL_Event &sdl_event, Event &event) +{ + switch (sdl_event.type) + { + case SDL_USEREVENT: + // toggle blink + if (sdl_event.user.code == 2) + { + _screen.toggle_blink(); + } + return false; + + case SDL_QUIT: + event.type = Event::QUIT; + return true; + + case SDL_VIDEORESIZE: + event.type = Event::RESIZE; + _screen.resize(sdl_event.resize.w, sdl_event.resize.h); + return true; + + case SDL_VIDEOEXPOSE: + _screen.redraw(); + return false; + + case SDL_KEYDOWN: + { + //switch(event.key.keysym.sym) + event.type = Event::KEYPRESS; + const char *keyname = _translate_keyname(sdl_event.key.keysym.sym); + // return only keyname or unicode, never both + if (keyname) + { + strncpy(event.key.keyname, keyname, 10); + event.key.unicode = 0; + } + else + { + event.key.keyname[0] = 0; + event.key.unicode = sdl_event.key.keysym.unicode; + if (!event.key.unicode) + { + // unknown key + return false; + } + } + event.key.mod = _translate_mod(sdl_event.key.keysym.mod); + return true; + } + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + event.type = (sdl_event.type == SDL_MOUSEBUTTONDOWN) ? Event::MOUSEDOWN : Event::MOUSEUP; + event.mouse.x = sdl_event.button.x / _screen.get_cell_width(); + event.mouse.y = sdl_event.button.y / _screen.get_cell_height(); + event.mouse.button = sdl_event.button.button; + if (sdl_event.button.button == SDL_BUTTON_WHEELUP || sdl_event.button.button == SDL_BUTTON_WHEELDOWN) + { + if (sdl_event.type == SDL_MOUSEBUTTONUP) + { + // do not report button-up events for mouse wheel + return false; + } + event.type = Event::MOUSEWHEEL; + } + _mousemove_last_x = event.mouse.x; + _mousemove_last_y = event.mouse.y; + return true; + + case SDL_MOUSEMOTION: + if (sdl_event.motion.state == 0 || _mousemove_last_x == -1) + { + // do not report move events when no button is pressed + return false; + } + event.type = Event::MOUSEMOVE; + event.mouse.x = sdl_event.motion.x / _screen.get_cell_width(); + event.mouse.y = sdl_event.motion.y / _screen.get_cell_height(); + if (_mousemove_last_x != event.mouse.x || + _mousemove_last_y != event.mouse.y) + { + event.mouse.relx = event.mouse.x - _mousemove_last_x; + event.mouse.rely = event.mouse.y - _mousemove_last_y; + _mousemove_last_x = event.mouse.x; + _mousemove_last_y = event.mouse.y; + return true; + } + // mouse position did not change + return false; + + default: + // unknown event + return false; + } +} + + const char *Terminal::_translate_keyname(SDLKey sym) { switch (sym) diff -r cfd3445107b4 -r 6e0656600754 sdlterm/src/sdlterm.h --- a/sdlterm/src/sdlterm.h Wed Jan 30 00:38:48 2013 +0100 +++ b/sdlterm/src/sdlterm.h Wed Jan 30 19:44:01 2013 +0100 @@ -238,6 +238,7 @@ int _mousemove_last_x; int _mousemove_last_y; + bool _handle_event(const SDL_Event &sdl_event, Event &event); const char *_translate_keyname(SDLKey sym); int _translate_mod(SDLMod mod); static Uint32 _wait_event_callback(Uint32 interval, void *param); diff -r cfd3445107b4 -r 6e0656600754 sdlterm/test_sdlterm.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdlterm/test_sdlterm.py Wed Jan 30 19:44:01 2013 +0100 @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from sdlterm import SDLTerminal + +if __name__ == '__main__': + term = SDLTerminal() + term.resize(800, 600) + term.select_font(b"font/DejaVuSansMono.ttf", b"font/DejaVuSansMono-Bold.ttf", 12) + term.erase() + term.putch(5, 5, 'W') + term.commit() + + while True: + event = term.wait_event() + print(event) + if event[0] == 'keypress' and event[1] == 'escape': + break + diff -r cfd3445107b4 -r 6e0656600754 sdlterm/tests/test_sdl_events.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdlterm/tests/test_sdl_events.cc Wed Jan 30 19:44:01 2013 +0100 @@ -0,0 +1,97 @@ +#include + +Uint32 timeout_callback(Uint32 interval, void *param) +{ + SDL_Event event; + event.type = SDL_USEREVENT; + event.user.code = 1; + SDL_PushEvent(&event); + return 0; +} + +bool handle_events(Uint32 timeout) +{ + SDL_Event event; + SDL_TimerID timer_id = NULL; + bool done = false; + + if (timeout) + { + timer_id = SDL_AddTimer(timeout, timeout_callback, NULL); + } + + // wait for events and handle them + if (SDL_WaitEvent(&event)) + { + do + { + switch (event.type) + { + case SDL_USEREVENT: + // timeout + if (event.user.code == 1) + { + SDL_RemoveTimer(timer_id); + printf("timeout\n"); + } + break; // continue loop + + case SDL_QUIT: + printf("quit\n"); + done = true; + break; + + case SDL_KEYUP: + printf("keyup\n"); + if (event.key.keysym.sym == SDLK_ESCAPE) + { + done = true; + } + break; + + case SDL_MOUSEBUTTONDOWN: + printf("mouse button down\n"); + break; + + case SDL_MOUSEBUTTONUP: + printf("mouse button up\n"); + break; + } + } + while (SDL_PollEvent(&event)); + } + // remove timer when other event came before timeout + if (timeout) + { + SDL_RemoveTimer(timer_id); + } + return done; +} + +int main(int argc, char **argv) +{ + SDL_Surface* screen = NULL; + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) + { + fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); + exit(1); + } + + atexit(SDL_Quit); + + screen = SDL_SetVideoMode(800, 480, 16, SDL_SWSURFACE); + if (screen == NULL) + { + fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError()); + exit(1); + } + + bool done = false; + while (!done) + { + done = handle_events(1000); + } + + return (0); +} diff -r cfd3445107b4 -r 6e0656600754 sdlterm/tests/test_sdlterm.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdlterm/tests/test_sdlterm.cc Wed Jan 30 19:44:01 2013 +0100 @@ -0,0 +1,76 @@ +#include "sdlterm.h" + + +class Application +{ +public: + Terminal term; + bool done; + + Application() : term(), done(false) {}; + + void init(); + void wait_and_process_event(); +}; + + +void Application::init() +{ + term.resize(800, 600); + term.select_font("font/DejaVuSansMono.ttf", "font/DejaVuSansMono-Bold.ttf", 12); + term.erase(); + + char hello[] = "Hello World!"; + for (int bg = 0; bg < 16; bg++) + { + for (int fg = 0; fg < 16; fg++) + { + for (char *c = hello; *c; c++) + { + term.set_attr( term.prepare_attr(fg, bg, 1) ); + term.putch(5 + 6 * bg + (c - hello), 5 + fg, *c); + } + } + } + term.commit(); +} + + +void Application::wait_and_process_event() +{ + Event event; + term.wait_event(event, 0); + + switch (event.type) + { + case Event::QUIT: + done = true; + break; + + case Event::MOUSEDOWN: + printf("mouse button down\n"); + break; + + case Event::MOUSEUP: + printf("mouse button up\n"); + break; + + default: + break; + } +} + + +int main(int argc, char *argv[]) +{ + Application app; + app.init(); + + while (!app.done) + { + app.wait_and_process_event(); + } + + return 0; +} +