DriverSDL: Add support for timeouts.
--- 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)
--- 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)
{
--- 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;
+}
+
--- 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);
};
--- 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':
--- 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 = []
--- 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.
'''
--- 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]