Index: lib/matplotlib/pyplot.py
===================================================================
--- lib/matplotlib/pyplot.py	(revision 5735)
+++ lib/matplotlib/pyplot.py	(working copy)
@@ -335,7 +335,21 @@
 if Figure.ginput.__doc__ is not None:
     ginput.__doc__ = dedent(Figure.ginput.__doc__)
 
+def waitforbuttonpress(*args, **kwargs):
+    """
+    Blocking call to interact with the figure.
 
+    This will wait for *n* key or mouse clicks from the user and
+    return a list containing True's for keyboard clicks and False's
+    for mouse clicks.
+
+    If *timeout* is negative, does not timeout.
+    """
+    return gcf().waitforbuttonpress(*args, **kwargs)
+if Figure.waitforbuttonpress.__doc__ is not None:
+    waitforbuttonpress.__doc__ = dedent(Figure.waitforbuttonpress.__doc__)
+
+
 # Putting things in figures
 
 def figtext(*args, **kwargs):
Index: lib/matplotlib/figure.py
===================================================================
--- lib/matplotlib/figure.py	(revision 5735)
+++ lib/matplotlib/figure.py	(working copy)
@@ -6,8 +6,16 @@
 :class:`SubplotParams`
     control the default spacing of the subplots
 
+:class:`BlockingInput`
+    creates a callable object to retrieve events in a blocking way for interactive sessions
+
+:class:`BlockingKeyMouseInput`
+    creates a callable object to retrieve key or mouse clicks in a blocking way for interactive sessions.  
+    Note: Subclass of BlockingInput. Used by waitforbuttonpress
+
 :class:`BlockingMouseInput`
-    creates a callable object to retrieve mouse clicks in a blocking way for interactive sessions
+    creates a callable object to retrieve mouse clicks in a blocking way for interactive sessions.  
+    Note: Subclass of BlockingInput.  Used by ginput
 
 :class:`Figure`
     top level container for all plot elements
@@ -118,24 +126,107 @@
         setattr(self, s, val)
 
 
-class BlockingMouseInput(object):
+class BlockingInput(object):
     """
-    Class that creates a callable object to retrieve mouse clicks in a
+    Class that creates a callable object to retrieve events in a
     blocking way.
     """
-    def __init__(self, fig):
+    def __init__(self, fig, eventslist=()):
         self.fig = fig
+        assert isinstance(eventslist, tuple), \
+            "Requires a tuple of event name strings"
+        self.eventslist = eventslist
 
-
-    def on_click(self, event):
+    def on_event(self, event):
         """
         Event handler that will be passed to the current figure to
-        retrieve clicks.
+        retrieve events.
         """
+        self.events.append(event)
+
+        if self.verbose:
+            print "Event %i" % len(self.events)
+
+        # This will extract info from events
+        self.post_event()
+        
+        if len(self.events) >= self.n and self.n > 0:
+            self.done = True
+
+    def post_event(self):
+        """For baseclass, do nothing but collect events"""
+        pass
+
+    def cleanup(self):
+        """Remove callbacks"""
+        for cb in self.callbacks:
+            self.fig.canvas.mpl_disconnect(cb)
+
+        self.callbacks=[]
+
+    def __call__(self, n=1, timeout=30, verbose=False ):
+        """
+        Blocking call to retrieve n events
+        """
+        
+        assert isinstance(n, int), "Requires an integer argument"
+        self.n = n
+
+        self.events = []
+        self.done = False
+        self.verbose = verbose
+        self.callbacks = []
+
+        # Ensure that the figure is shown
+        self.fig.show()
+        
+        # connect the events to the on_event function call
+        for n in self.eventslist:
+            self.callbacks.append( self.fig.canvas.mpl_connect(n, self.on_event) )
+
+        try:
+            # wait for n clicks
+            counter = 0
+            while not self.done:
+                self.fig.canvas.flush_events()
+                time.sleep(0.01)
+
+                # check for a timeout
+                counter += 1
+                if timeout > 0 and counter > timeout/0.01:
+                    print "Timeout reached";
+                    break;
+        finally: # Activated on exception like ctrl-c
+            self.cleanup()
+
+        # Disconnect the callbacks
+        self.cleanup()
+
+        # Return the events in this case
+        return self.events
+
+class BlockingMouseInput(BlockingInput):
+    """
+    Class that creates a callable object to retrieve mouse clicks in a
+    blocking way.
+    """
+    def __init__(self, fig):
+        BlockingInput.__init__(self, fig=fig, eventslist=('button_press_event',) )
+
+    def post_event(self):
+        """
+        This will be called to process events
+        """
+        assert len(self.events)>0, "No events yet"
+
+        event = self.events[-1]
+
         if event.button == 3:
             # If it's a right click, pop the last coordinates.
             if len(self.clicks) > 0:
                 self.clicks.pop()
+                del self.events[-2:] # Remove button=3 event and previous event
+
                 if self.show_clicks:
                     mark = self.marks.pop()
                     mark.remove()
@@ -153,51 +244,56 @@
                 self.marks.extend(
                     event.inaxes.plot([event.xdata,], [event.ydata,], 'r+') )
                 self.fig.canvas.draw()
-            if self.n > 0 and len(self.clicks) >= self.n:
-                self.done = True
 
+    def cleanup(self):
+        # clean the figure
+        if self.show_clicks:
+            for mark in self.marks:
+                mark.remove()
+            self.marks = []
+            self.fig.canvas.draw()
 
+        # Call base class to remove callbacks
+        BlockingInput.cleanup(self)
+        
     def __call__(self, n=1, timeout=30, verbose=False, show_clicks=True):
         """
         Blocking call to retrieve n coordinate pairs through mouse
         clicks.
         """
-        self.verbose     = verbose
-        self.done        = False
+        self.show_clicks = show_clicks
         self.clicks      = []
-        self.show_clicks = True
         self.marks       = []
+        BlockingInput.__call__(self,n=n,timeout=timeout,verbose=verbose)
 
-        assert isinstance(n, int), "Requires an integer argument"
-        self.n = n
+        return self.clicks
 
-        # Ensure that the figure is shown
-        self.fig.show()
-        # connect the click events to the on_click function call
-        self.callback = self.fig.canvas.mpl_connect('button_press_event',
-                                                    self.on_click)
-        # wait for n clicks
-        counter = 0
-        while not self.done:
-            self.fig.canvas.flush_events()
-            time.sleep(0.01)
+class BlockingKeyMouseInput(BlockingInput):
+    """
+    Class that creates a callable object to retrieve a single mouse or
+    keyboard click
+    """
+    def __init__(self, fig):
+        BlockingInput.__init__(self, fig=fig, eventslist=('button_press_event','key_press_event') )
 
-            # check for a timeout
-            counter += 1
-            if timeout > 0 and counter > timeout/0.01:
-                print "ginput timeout";
-                break;
+    def post_event(self):
+        """
+        Determines if it is a key event
+        """
+        assert len(self.events)>0, "No events yet"
 
-        # Disconnect the event, clean the figure, and return what we have
-        self.fig.canvas.mpl_disconnect(self.callback)
-        self.callback = None
-        if self.show_clicks:
-            for mark in self.marks:
-                mark.remove()
-            self.fig.canvas.draw()
-        return self.clicks
+        self.keyormouse = self.events[-1].name == 'key_press_event'
 
+    def __call__(self, timeout=30, verbose=False):
+        """
+        Blocking call to retrieve a single mouse or key click
+        Returns True if key click, False if mouse, or None if timeout
+        """
+        self.keyormouse = None
+        BlockingInput.__call__(self,n=1,timeout=timeout,verbose=verbose)
 
+        return self.keyormouse
+
 class Figure(Artist):
 
     """
@@ -1117,10 +1213,27 @@
 
         blocking_mouse_input = BlockingMouseInput(self)
         return blocking_mouse_input(n=n, timeout=timeout,
-                                          verbose=verbose, show_clicks=True)
+                                          verbose=verbose, show_clicks=show_clicks)
 
+    def waitforbuttonpress(self, timeout=-1):
+        """
+        call signature::
 
+          waitforbuttonpress(self, timeout=-1)
 
+        Blocking call to interact with the figure.
+
+        This will return True is a key was pressed, False if a mouse
+        button was pressed and None if *timeout* was reached without
+        either being pressed.
+
+        If *timeout* is negative, does not timeout.
+        """
+
+        blocking_input = BlockingKeyMouseInput(self)
+        return blocking_input(timeout=timeout)
+
+
 def figaspect(arg):
     """
     Create a figure with specified aspect ratio.  If *arg* is a number,
