ginput: blocking call for mouse input

Having played with both "flush_until" and "start/stop" I have to say I
prefer the start/stop interface. It removes the need for users to share
a 'done' variable between the callback and the caller and the need to
create a dummy lambda:done function. Also, it is a better match to
the semantics of wx/gtk/qt (see below).

I don't like the names start_event_loop/stop_event_loop, but couldn't
think of anything better. How about: gui_wait/end_wait?

    - Paul

···

On Fri, Feb 08, 2008 at 08:15:20AM +0100, Gael Varoquaux wrote:

On Thu, Feb 07, 2008 at 11:31:11AM -0500, Paul Kienzle wrote:
> There are two ways to do this in wx.

> One is to use eventloop.Dispatch() which waits until the next available
> event:

> [...]

> The other is to trigger a loop.Exit() from the click callback.

> [...]

Very nice. I am impressed. We need to find a way of doing the same in
other toolkits. Way can however change the function call flush_event to
give it an "until" callback (and maybe rename it to
"wait_interactively"), and move the busy waiting code in the
backend-dependant part of the code. That way we can remove it backend
after backend.

-----

Proposed generic implementation based on flush_event and sleep, to be
put into CanvasBase:

    def gui_wait(self, timeout=0):
        """Run the event loop."""
        if timeout == 0: timeout = npy.inf
        timestep = 0.01
        counter = 0
        self._waiting = True
        while self._waiting and counter*timestep < timeout:
            self.flush_events()
            time.sleep(timestep)
            counter += 1

    def end_wait(self):
        """Stop the event loop."""
        self._waiting = False

Suggested implementation for backend_gtk (untested!!!):

    def gui_wait(self, timeout=0):
        """Run the gtk event loop."""
        # TODO: call self.end_wait() on window close
        self._waiting = True
        if timeout > 0:
            timer = gtk.gobject.timeout_add(timeout,self._onTimer)
        gtk.main()
        self._waiting = False
        gobject.source_remove(timer)

    def _onTimer(self):
        self.end_wait()
        return False

    def end_wait(self):
        """Stop the gtk event loop."""
        if self._waiting: gtk.main_quit()