diff --git a/gdk/quartz/gdkdrawable-quartz.c b/gdk/quartz/gdkdrawable-quartz.c
index 7e1172f..56c05c9 100644
--- a/gdk/quartz/gdkdrawable-quartz.c
+++ b/gdk/quartz/gdkdrawable-quartz.c
@@ -19,6 +19,7 @@
  */
 
 #include <config.h>
+#include <sys/time.h>
 #include <cairo-quartz.h>
 #include "gdkprivate-quartz.h"
 
@@ -770,6 +771,13 @@ gdk_quartz_drawable_release_context (GdkDrawable  *drawable,
 	{
 	  [window_impl->view unlockFocus];
 
+          /* Support drawing from outside of expose. */
+          if (window_impl->begin_paint_count == 0)
+            {
+              if (_gdk_quartz_drawable_can_flush ())
+                CGContextFlush (cg_context);
+            }
+
 	  if (window_impl->pool)
 	    {
 	      [window_impl->pool release];
@@ -794,3 +802,59 @@ _gdk_quartz_drawable_finish (GdkDrawable *drawable)
       impl->cairo_surface = NULL;
     }
 }  
+
+/* When drawing outside of expose, we must flush manually. If we flush
+ * too often, Quartz starts blocking all drawing operations until the
+ * next vertical sync happens, so we have to throttle the flushing.
+ * See http://developer.apple.com/documentation/Performance/
+ * Conceptual/Drawing/index.html.
+ */
+static guint flush_id;
+
+static gboolean
+flush_cb (gpointer data)
+{
+  CGContextRef cg_context;
+
+  cg_context = [[NSGraphicsContext currentContext] graphicsPort];
+  if (cg_context)
+    CGContextFlush (cg_context);
+
+  flush_id = 0;
+
+  return FALSE;
+}
+
+gboolean
+_gdk_quartz_drawable_can_flush (void)
+{
+  static struct timeval prev_tv;
+  struct timeval tv;
+  gint left;
+
+  gettimeofday (&tv, NULL);
+  if (tv.tv_sec - prev_tv.tv_sec > 0 ||
+      tv.tv_usec - prev_tv.tv_usec > 1000*1000/30.0)
+    {
+      prev_tv = tv;
+
+      if (flush_id)
+        {
+          g_source_remove (flush_id);
+          flush_id = 0;
+        } 
+
+     return TRUE;
+    }
+
+  if (!flush_id)
+    {
+      /* Add a timeout to flush as soon as we can without hitting the
+       * throttling limit.
+       */
+      left = 33 - (tv.tv_usec - prev_tv.tv_usec) / 1000;
+      flush_id = g_timeout_add (left, flush_cb, NULL);
+    }
+
+  return FALSE;
+}
diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h
index c3b7b0b..c3f1a1d 100644
--- a/gdk/quartz/gdkprivate-quartz.h
+++ b/gdk/quartz/gdkprivate-quartz.h
@@ -176,6 +176,7 @@ GdkEventType _gdk_quartz_keys_event_type  (NSEvent   *event);
 gboolean     _gdk_quartz_keys_is_modifier (guint      keycode);
 
 /* Drawable */
-void        _gdk_quartz_drawable_finish (GdkDrawable *drawable);
+void        _gdk_quartz_drawable_finish    (GdkDrawable *drawable);
+gboolean    _gdk_quartz_drawable_can_flush (void);
 
 #endif /* __GDK_PRIVATE_QUARTZ_H__ */
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index 63f0197..654dcc0 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -261,7 +261,8 @@ gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
 }
 
 static void
-gdk_window_quartz_process_updates_internal (GdkWindow *window)
+gdk_window_quartz_process_updates_internal (GdkWindow *window, 
+                                            gboolean   display)
 {
   GdkWindowObject *private = (GdkWindowObject *) window;
   GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *) private->impl;
@@ -282,7 +283,8 @@ gdk_window_quartz_process_updates_internal (GdkWindow *window)
 							rects[i].width, rects[i].height)];
 	}
 
-      [impl->view displayIfNeeded];
+      if (display)
+        [impl->view displayIfNeeded];
 
       g_free (rects);
     }
@@ -303,7 +305,7 @@ gdk_window_quartz_process_all_updates (void)
 
   while (tmp_list)
     {
-      gdk_window_quartz_process_updates_internal (tmp_list->data);
+      gdk_window_quartz_process_updates_internal (tmp_list->data, TRUE);
 
       g_object_unref (tmp_list->data);
       tmp_list = tmp_list->next;
@@ -365,7 +367,8 @@ gdk_window_impl_quartz_process_updates (GdkPaintable *paintable,
 
   if (private->update_area)
     {
-      gdk_window_quartz_process_updates_internal ((GdkWindow *) private);
+      gdk_window_quartz_process_updates_internal ((GdkWindow *) private, 
+                                                  _gdk_quartz_drawable_can_flush ());
       update_windows = g_slist_remove (update_windows, private);
     }
 }
