DriverSDL: Fix event dispatching. Add SDL events test.
authorRadek Brich <radek.brich@devl.cz>
Wed, 30 Jan 2013 19:44:01 +0100
changeset 72 6e0656600754
parent 71 cfd3445107b4
child 73 85a282b5e4fc
DriverSDL: Fix event dispatching. Add SDL events test.
.hgignore
sdlterm/Makefile
sdlterm/demo.cc
sdlterm/demo.py
sdlterm/src/sdlterm.cc
sdlterm/src/sdlterm.h
sdlterm/test_sdlterm.py
sdlterm/tests/test_sdl_events.cc
sdlterm/tests/test_sdlterm.cc
--- 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
--- 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
--- 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;
-}
-
--- 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
-
--- 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)
--- 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);
--- /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
+
--- /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 <SDL/SDL.h>
+
+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);
+}
--- /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;
+}
+