# HG changeset patch # User Radek Brich # Date 1357603927 -3600 # Node ID 911927edbdde173780b649d0a1da1ef2d17ac6e1 # Parent 282a07d2068001e678b3133515abd7a0f8400e39 DriverSDL: Add support for timeouts. diff -r 282a07d20680 -r 911927edbdde sdlterm/cython/sdlterm.pyx --- a/sdlterm/cython/sdlterm.pyx Mon Jan 07 23:15:17 2013 +0100 +++ b/sdlterm/cython/sdlterm.pyx Tue Jan 08 01:12:07 2013 +0100 @@ -48,7 +48,7 @@ void show_cursor(int x, int y) void hide_cursor() - void get_next_event(Event event) + bool wait_event(Event event, int timeout) except + int get_width() int get_height() @@ -85,8 +85,10 @@ def hide_cursor(self): self.thisptr.hide_cursor() - def get_next_event(self): - self.thisptr.get_next_event(self.event) + def wait_event(self, timeout): + if not self.thisptr.wait_event(self.event, timeout or 0): + # timeout + return None event = self.event if event.type == event.MOUSEMOVE: return ('mousemove', event.mouse.x, event.mouse.y) diff -r 282a07d20680 -r 911927edbdde sdlterm/demo.cc --- a/sdlterm/demo.cc Mon Jan 07 23:15:17 2013 +0100 +++ b/sdlterm/demo.cc Tue Jan 08 01:12:07 2013 +0100 @@ -39,7 +39,7 @@ void Application::wait_and_process_event() { Event event; - term.get_next_event(event); + term.wait_event(event, 0); switch (event.type) { diff -r 282a07d20680 -r 911927edbdde sdlterm/src/sdlterm.cc --- a/sdlterm/src/sdlterm.cc Mon Jan 07 23:15:17 2013 +0100 +++ b/sdlterm/src/sdlterm.cc Tue Jan 08 01:12:07 2013 +0100 @@ -310,7 +310,7 @@ : _screen(), _attr(7), _cursor_x(0), _cursor_y(0), _cursor_visible(false), _mousemove_last_x(-1), _mousemove_last_y(-1) { - if (SDL_Init(SDL_INIT_VIDEO) == -1) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); throw std::exception(); @@ -341,22 +341,41 @@ } } -void Terminal::get_next_event(Event &event) + +bool Terminal::wait_event(Event &event, Uint32 timeout) { static SDL_Event sdl_event; + // use timer to simulate SDL_WaitEventTimeout, which is not available in SDL 1.2 + SDL_TimerID timer_id = NULL; + if (timeout) + { + timer_id = SDL_AddTimer(timeout, _wait_event_callback, NULL); + } + while (SDL_WaitEvent(&sdl_event)) { + if (timer_id) + { + if (sdl_event.type == SDL_USEREVENT && sdl_event.user.code == 1) + { + // timeout + return false; + } + // some event came before timeout... + SDL_RemoveTimer(timer_id); + timer_id = NULL; + } switch (sdl_event.type) { case SDL_QUIT: event.type = Event::QUIT; - return; + return true; case SDL_VIDEORESIZE: event.type = Event::RESIZE; _screen.resize(sdl_event.resize.w, sdl_event.resize.h); - return; + return true; case SDL_VIDEOEXPOSE: _screen.redraw(); @@ -380,7 +399,7 @@ if (!event.key.unicode) break; // continue loop (unknown key) } - return; + return true; } case SDL_MOUSEBUTTONDOWN: @@ -396,7 +415,7 @@ event.type = Event::MOUSEWHEEL; } _mousemove_last_x = -1; - return; + return true; case SDL_MOUSEMOTION: if (sdl_event.motion.state == 0) @@ -409,7 +428,7 @@ { _mousemove_last_x = event.mouse.x; _mousemove_last_y = event.mouse.y; - return; + return true; } break; // continue loop when mouse position did not change @@ -417,6 +436,8 @@ break; // continue loop } } + fprintf(stderr, "SDL_WaitEvent error: %s\n", SDL_GetError()); + throw std::exception(); } @@ -458,3 +479,13 @@ } } + +Uint32 Terminal::_wait_event_callback(Uint32 interval, void *param) +{ + SDL_Event event; + event.type = SDL_USEREVENT; + event.user.code = 1; + SDL_PushEvent(&event); + return 0; +} + diff -r 282a07d20680 -r 911927edbdde sdlterm/src/sdlterm.h --- a/sdlterm/src/sdlterm.h Mon Jan 07 23:15:17 2013 +0100 +++ b/sdlterm/src/sdlterm.h Tue Jan 08 01:12:07 2013 +0100 @@ -199,7 +199,12 @@ void show_cursor(int x, int y) { _cursor_x = x; _cursor_y = y; _cursor_visible = true; }; void hide_cursor() { _cursor_visible = false; }; - void get_next_event(Event &event); + /* Wait for an event. + * + * Timeout is in miliseconds, zero means wait indefinitely. + * Returns false on timeout, true on event. + */ + bool wait_event(Event &event, Uint32 timeout); int get_width() const { return _screen.get_width(); }; int get_height() const { return _screen.get_height(); }; @@ -215,5 +220,6 @@ int _mousemove_last_y; const char *_translate_keyname(SDLKey sym); + static Uint32 _wait_event_callback(Uint32 interval, void *param); }; diff -r 282a07d20680 -r 911927edbdde tuikit/application.py --- a/tuikit/application.py Mon Jan 07 23:15:17 2013 +0100 +++ b/tuikit/application.py Tue Jan 08 01:12:07 2013 +0100 @@ -42,18 +42,21 @@ def has_timeout(self): - return len(self.timeout) and True or False + return len(self.timeout) > 0 def nearest_timeout(self): + if not self.has_timeout(): + return None return min(self.timeout)[0] def process_timeout(self): + if not self.has_timeout(): + return now = time.time() lasted = now - self.timelast self.timelast = now - for to in self.timeout[:]: newt = to[0] - lasted if newt <= 0.0: @@ -104,14 +107,9 @@ self.top.draw(self.driver) self.driver.commit() - timeout = None - if self.top.has_timeout(): - timeout = int(math.ceil(self.top.nearest_timeout() * 10)) - + timeout = self.top.nearest_timeout() events = self.driver.getevents(timeout) - - if self.top.has_timeout(): - self.top.process_timeout() + self.top.process_timeout() for event in events: if event[0] == 'quit': diff -r 282a07d20680 -r 911927edbdde tuikit/driver_curses.py --- a/tuikit/driver_curses.py Mon Jan 07 23:15:17 2013 +0100 +++ b/tuikit/driver_curses.py Tue Jan 08 01:12:07 2013 +0100 @@ -2,7 +2,7 @@ import curses.wrapper import curses.ascii -import locale +import math import logging from tuikit.driver import Driver @@ -185,6 +185,11 @@ ## input ## def inputqueue_fill(self, timeout=None): + """Wait for curses input, add it to inputqueue. + + timeout -- int, tenths of second (None=infinite) + + """ if timeout is None: # wait indefinitely c = self.screen.getch() @@ -241,8 +246,15 @@ def getevents(self, timeout=None): + '''Process input, return list of events. + + timeout -- float, in seconds + + ''' # empty queue -> fill if len(self.inputqueue) == 0: + if timeout is not None: + timeout = math.ceil(timeout * 10) self.inputqueue_fill(timeout) res = [] diff -r 282a07d20680 -r 911927edbdde tuikit/driver_dummy.py --- a/tuikit/driver_dummy.py Mon Jan 07 23:15:17 2013 +0100 +++ b/tuikit/driver_dummy.py Tue Jan 08 01:12:07 2013 +0100 @@ -31,6 +31,8 @@ def getevents(self, timeout=None): '''Process input, return list of events. + timeout -- float, in seconds + This dummy implementation just returns 'q' and Escape key presses. ''' diff -r 282a07d20680 -r 911927edbdde tuikit/driver_sdl.py --- a/tuikit/driver_sdl.py Mon Jan 07 23:15:17 2013 +0100 +++ b/tuikit/driver_sdl.py Tue Jan 08 01:12:07 2013 +0100 @@ -66,8 +66,16 @@ ## input ## def getevents(self, timeout=None): - '''Process input, return list of events.''' - event = self.sdlterm.get_next_event() + '''Process input, return list of events. + + timeout -- float, in seconds + + ''' + if timeout is not None: + timeout = int(timeout*1000) + event = self.sdlterm.wait_event(timeout) + if not event: + return [] if event[0] == 'resize': self.size.w, self.size.h = self.sdlterm.width, self.sdlterm.height return [event]