Index: owl.c
===================================================================
--- owl.c	(revision c809f5e8a3cc2745724f518c89b09279b5508b02)
+++ owl.c	(revision 4cc49bce5bdc20cd8da2b4e305f60d04ae879d4f)
@@ -442,27 +442,4 @@
 #endif /* OWL_STDERR_REDIR */
 
-static int owl_refresh_pre_select_action(owl_ps_action *a, void *data)
-{
-  owl_colorpair_mgr *cpmgr;
-
-  /* if a resize has been scheduled, deal with it */
-  owl_global_check_resize(&g);
-  /* update the terminal if we need to */
-  owl_window_redraw_scheduled();
-  /* On colorpair shortage, reset and redraw /everything/. NOTE: if
-   * the current screen uses too many colorpairs, this draws
-   * everything twice. But this is unlikely; COLOR_PAIRS is 64 with
-   * 8+1 colors, and 256^2 with 256+1 colors. (+1 for default.) */
-  cpmgr = owl_global_get_colorpair_mgr(&g);
-  if (cpmgr->overflow) {
-    owl_function_debugmsg("colorpairs: color shortage; reset pairs and redraw. COLOR_PAIRS = %d", COLOR_PAIRS);
-    owl_fmtext_reset_colorpairs(cpmgr);
-    owl_function_full_redisplay();
-    owl_window_redraw_scheduled();
-  }
-  return 0;
-}
-
-
 int main(int argc, char **argv, char **env)
 {
@@ -473,4 +450,5 @@
   const char *dir;
   owl_options opts;
+  GSource *source;
 
   if (!GLIB_CHECK_VERSION (2, 12, 0))
@@ -591,5 +569,8 @@
   owl_global_push_context(&g, OWL_CTX_INTERACTIVE|OWL_CTX_RECV, NULL, "recv", NULL);
 
-  owl_select_add_pre_select_action(owl_refresh_pre_select_action, NULL, NULL);
+  source = owl_window_redraw_source_new();
+  g_source_attach(source, NULL);
+  g_source_unref(source);
+
   owl_select_add_pre_select_action(owl_process_messages, NULL, NULL);
   owl_select_add_pre_select_action(owl_errsignal_pre_select_action, NULL, NULL);
Index: window.c
===================================================================
--- window.c	(revision b31f1c9929b526b6d90b18b7847a024ff3d0c77d)
+++ window.c	(revision 4cc49bce5bdc20cd8da2b4e305f60d04ae879d4f)
@@ -524,2 +524,52 @@
   owl_window_set_position(w, nlines, ncols, w->begin_y, w->begin_x);
 }
+
+/** Redrawing main loop hooks **/
+
+static bool _owl_window_should_redraw(void) {
+  return g.resizepending || owl_window_get_screen()->dirty_subtree;
+}
+
+static gboolean _owl_window_redraw_prepare(GSource *source, int *timeout) {
+  *timeout = -1;
+  return _owl_window_should_redraw();
+}
+
+static gboolean _owl_window_redraw_check(GSource *source) {
+  return _owl_window_should_redraw();
+}
+
+static gboolean _owl_window_redraw_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
+  owl_colorpair_mgr *cpmgr;
+
+  /* if a resize has been scheduled, deal with it */
+  owl_global_check_resize(&g);
+  /* update the terminal if we need to */
+  owl_window_redraw_scheduled();
+  /* On colorpair shortage, reset and redraw /everything/. NOTE: if
+   * the current screen uses too many colorpairs, this draws
+   * everything twice. But this is unlikely; COLOR_PAIRS is 64 with
+   * 8+1 colors, and 256^2 with 256+1 colors. (+1 for default.) */
+  cpmgr = owl_global_get_colorpair_mgr(&g);
+  if (cpmgr->overflow) {
+    owl_function_debugmsg("colorpairs: color shortage; reset pairs and redraw. COLOR_PAIRS = %d", COLOR_PAIRS);
+    owl_fmtext_reset_colorpairs(cpmgr);
+    owl_function_full_redisplay();
+    owl_window_redraw_scheduled();
+  }
+  return TRUE;
+}
+
+static GSourceFuncs redraw_funcs = {
+  _owl_window_redraw_prepare,
+  _owl_window_redraw_check,
+  _owl_window_redraw_dispatch,
+  NULL
+};
+
+GSource *owl_window_redraw_source_new(void) {
+  GSource *source;
+  source = g_source_new(&redraw_funcs, sizeof(GSource));
+  /* TODO: priority?? */
+  return source;
+}
Index: window.h
===================================================================
--- window.h	(revision 38e2250d6a6cd2691f017563d2eb56b3304d608a)
+++ window.h	(revision 4cc49bce5bdc20cd8da2b4e305f60d04ae879d4f)
@@ -72,4 +72,6 @@
 void owl_window_resize(owl_window *w, int nlines, int ncols);
 
+GSource *owl_window_redraw_source_new(void);
+
 /* Standard callback functions in windowcb.c */
 
