]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkmain.c
Add new keysyms from X11R6.4 (including EuroSign).
[~andy/gtk] / gtk / gtkmain.c
index 5f7b354d74a2193aa909237485dc7e62f4f44394..94a5b621fa0f4a4ff04d9692d344465f5638dcd3 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include "gdkx.h"              /* For GDK_WINDOWING */
+
+#ifdef GDK_WINDOWING_X11
 #include <X11/Xlocale.h>       /* so we get the right setlocale */
+#else
+#include <locale.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <gmodule.h>
 #include "gtkbutton.h"
-#include "gtkfeatures.h"
+#include "gtkdnd.h"
+#include "gtkcompat.h"
 #include "gtkhscrollbar.h"
 #include "gtkhseparator.h"
 #include "gtkmain.h"
 #include "gtkpreview.h"
 #include "gtkrc.h"
+#include "gtkscrolledwindow.h"
 #include "gtkselection.h"
 #include "gtksignal.h"
 #include "gtktable.h"
 #include "gtkwindow.h"
 #include "gtkprivate.h"
 #include "gdk/gdki18n.h"
-#include "../config.h"
+#include "config.h"
 #include "gtkdebug.h"
-
+#include "gtkintl.h"
 
 /* Private type definitions
  */
 typedef struct _GtkInitFunction                 GtkInitFunction;
 typedef struct _GtkQuitFunction                 GtkQuitFunction;
-typedef struct _GtkTimeoutFunction      GtkTimeoutFunction;
-typedef struct _GtkIdleFunction                 GtkIdleFunction;
-typedef struct _GtkInputFunction        GtkInputFunction;
+typedef struct _GtkClosure              GtkClosure;
 typedef struct _GtkKeySnooperData       GtkKeySnooperData;
 
 struct _GtkInitFunction
@@ -67,31 +81,9 @@ struct _GtkQuitFunction
   GtkDestroyNotify destroy;
 };
 
-struct _GtkTimeoutFunction
-{
-  guint tag;
-  guint32 start;
-  guint32 interval;
-  guint32 originterval;
-  GtkFunction function;
-  GtkCallbackMarshal marshal;
-  gpointer data;
-  GtkDestroyNotify destroy;
-};
-
-struct _GtkIdleFunction
+struct _GtkClosure
 {
-  guint tag;
-  gint priority;
   GtkCallbackMarshal marshal;
-  GtkFunction function;
-  gpointer data;
-  GtkDestroyNotify destroy;
-};
-
-struct _GtkInputFunction
-{
-  GtkCallbackMarshal callback;
   gpointer data;
   GtkDestroyNotify destroy;
 };
@@ -106,34 +98,21 @@ struct _GtkKeySnooperData
 static void  gtk_exit_func              (void);
 static gint  gtk_quit_invoke_function   (GtkQuitFunction    *quitf);
 static void  gtk_quit_destroy           (GtkQuitFunction    *quitf);
-static void  gtk_timeout_insert                 (GtkTimeoutFunction *timeoutf);
-static void  gtk_handle_current_timeouts (guint32            the_time);
-static void  gtk_handle_current_idles   (void);
 static gint  gtk_invoke_key_snoopers    (GtkWidget          *grab_widget,
                                          GdkEvent           *event);
-static void  gtk_handle_timeouts        (void);
-static void  gtk_handle_idle            (void);
-static void  gtk_handle_timer           (void);
-static void  gtk_propagate_event        (GtkWidget          *widget,
-                                         GdkEvent           *event);
+
+static void     gtk_destroy_closure      (gpointer            data);
+static gboolean gtk_invoke_idle_timeout  (gpointer            data);
+static void     gtk_invoke_input         (gpointer            data,
+                                         gint                source,
+                                         GdkInputCondition   condition);
+
+#if 0
 static void  gtk_error                  (gchar              *str);
 static void  gtk_warning                (gchar              *str);
 static void  gtk_message                (gchar              *str);
 static void  gtk_print                  (gchar              *str);
-
-static gint  gtk_idle_remove_from_list    (GList               **list, 
-                                          guint                 tag, 
-                                          gpointer              data, 
-                                          gint                  remove_link);
-static gint  gtk_timeout_remove_from_list (GList               **list, 
-                                          guint                 tag, 
-                                          gint                  remove_link);
-
-static gint  gtk_idle_compare           (gconstpointer      a, 
-                                         gconstpointer      b);
-
-static gint  gtk_timeout_compare        (gconstpointer      a, 
-                                         gconstpointer      b);
+#endif
 
 const guint gtk_major_version = GTK_MAJOR_VERSION;
 const guint gtk_minor_version = GTK_MINOR_VERSION;
@@ -141,12 +120,12 @@ const guint gtk_micro_version = GTK_MICRO_VERSION;
 const guint gtk_binary_age = GTK_BINARY_AGE;
 const guint gtk_interface_age = GTK_INTERFACE_AGE;
 
-static gboolean iteration_done = FALSE;
 static guint gtk_main_loop_level = 0;
 static gint gtk_initialized = FALSE;
-static GdkEvent *next_event = NULL;
 static GList *current_events = NULL;
 
+static GSList *main_loops = NULL;      /* stack of currently executing main loops */
+
 static GSList *grabs = NULL;              /* A stack of unique grabs. The grabbing
                                            *  widget is the first one on the list.
                                            */
@@ -154,56 +133,6 @@ static GList *init_functions = NULL;          /* A list of init functions.
                                            */
 static GList *quit_functions = NULL;      /* A list of quit functions.
                                            */
-
-
-/* When handling timeouts, the algorithm is to move all of the expired
- * timeouts from timeout_functions to current_timeouts then process
- * them as a batch. If one of the timeouts recursively calls the main
- * loop, then the remainder of the timeouts in current_timeouts will
- * be processed before anything else happens.
- * 
- * Each timeout is procesed as follows:
- *
- * - The timeout is removed from current_timeouts
- * - The timeout is pushed on the running_timeouts stack
- * - The timeout is executed
- * - The timeout stack is popped
- * - If the timeout function wasn't removed from the stack while executing,
- *   and it returned TRUE, it is added back to timeout_functions, otherwise
- *   it is destroyed if necessary.
- *
- * gtk_timeout_remove() works by checking for the timeout in
- * timeout_functions current_timeouts and running_timeouts. If it is
- * found in one of the first two, it is removed and destroyed. If it
- * is found in running_timeouts, it is destroyed and ->data is set to
- * NULL for the stack entry.
- *
- * Idle functions work pretty much identically.  
- */
-
-static GList *timeout_functions = NULL;           /* A list of timeout functions sorted by
-                                           *  when the length of the time interval
-                                           *  remaining. Therefore, the first timeout
-                                           *  function to expire is at the head of
-                                           *  the list and the last to expire is at
-                                           *  the tail of the list.  */
-static GList *idle_functions = NULL;      /* A list of idle functions.
-                                           */
-
-/* The idle functions / timeouts that are currently being processed 
- *  by gtk_handle_current_(timeouts/idles) 
- */
-static GList *current_idles = NULL;
-static GList *current_timeouts = NULL;
-
-/* A stack of idle functions / timeouts that are currently being
- * being executed
- */
-static GList *running_idles = NULL;
-static GList *running_timeouts = NULL;
-
-static GMemChunk *timeout_mem_chunk = NULL;
-static GMemChunk *idle_mem_chunk = NULL;
 static GMemChunk *quit_mem_chunk = NULL;
 
 static GSList *key_snoopers = NULL;
@@ -218,27 +147,65 @@ static GdkColormap *gtk_colormap;    /* The colormap to be used in creating new
 guint gtk_debug_flags = 0;                /* Global GTK debug flag */
 
 #ifdef G_ENABLE_DEBUG
-static GDebugKey gtk_debug_keys[] = {
+static const GDebugKey gtk_debug_keys[] = {
   {"objects", GTK_DEBUG_OBJECTS},
   {"misc", GTK_DEBUG_MISC},
-  {"signals", GTK_DEBUG_SIGNALS}
+  {"signals", GTK_DEBUG_SIGNALS},
+  {"dnd", GTK_DEBUG_DND},
+  {"plugsocket", GTK_DEBUG_PLUGSOCKET}
 };
 
 static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
 
 #endif /* G_ENABLE_DEBUG */
 
-gint gtk_use_mb = -1;
+gchar*
+gtk_check_version (guint required_major,
+                  guint required_minor,
+                  guint required_micro)
+{
+  if (required_major > GTK_MAJOR_VERSION)
+    return "Gtk+ version too old (major mismatch)";
+  if (required_major < GTK_MAJOR_VERSION)
+    return "Gtk+ version too new (major mismatch)";
+  if (required_minor > GTK_MINOR_VERSION)
+    return "Gtk+ version too old (minor mismatch)";
+  if (required_minor < GTK_MINOR_VERSION)
+    return "Gtk+ version too new (minor mismatch)";
+  if (required_micro < GTK_MICRO_VERSION - GTK_BINARY_AGE)
+    return "Gtk+ version too new (micro mismatch)";
+  if (required_micro > GTK_MICRO_VERSION)
+    return "Gtk+ version too old (micro mismatch)";
+  return NULL;
+}
 
-void
-gtk_init (int   *argc,
-         char ***argv)
+#ifdef __EMX__
+static gchar *add_dll_suffix(gchar *module_name)
+{
+    gchar *suffix = strrchr(module_name, '.');
+    
+    if (!suffix || stricmp(suffix, ".dll"))
+    {
+       gchar *old = module_name;
+         
+       module_name = g_strconcat (module_name, ".dll", NULL);
+       g_free (old);
+    }
+    return (module_name);
+}
+#endif
+
+gboolean
+gtk_init_check (int     *argc,
+               char   ***argv)
 {
-  GSList *gtk_modinit_funcs = NULL;
-  gchar *current_locale;
+  extern void gtk_object_post_arg_parsing_init (void);
+  GSList *gtk_modules = NULL;
+  GSList *slist;
+  gchar *env_string = NULL;
 
   if (gtk_initialized)
-    return;
+    return TRUE;
 
 #if    0
   g_set_error_handler (gtk_error);
@@ -250,16 +217,42 @@ gtk_init (int      *argc,
   /* Initialize "gdk". We pass along the 'argc' and 'argv'
    *  parameters as they contain information that GDK uses
    */
-  gdk_init (argc, argv);
+  if (!gdk_init_check (argc, argv))
+    return FALSE;
+
+  gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
   
 #ifdef G_ENABLE_DEBUG
-  {
-    gchar *debug_string = getenv("GTK_DEBUG");
-    if (debug_string != NULL)
-      gtk_debug_flags = g_parse_debug_string (debug_string,
+  env_string = getenv ("GTK_DEBUG");
+  if (env_string != NULL)
+    {
+      gtk_debug_flags = g_parse_debug_string (env_string,
                                              gtk_debug_keys,
                                              gtk_ndebug_keys);
-  }
+      env_string = NULL;
+    }
+#endif /* G_ENABLE_DEBUG */
+
+  env_string = getenv ("GTK_MODULES");
+  if (env_string)
+    {
+      gchar **modules, **as;
+
+#ifndef __EMX__
+      modules = g_strsplit (env_string, G_SEARCHPATH_SEPARATOR_S, -1);
+#else
+      modules = g_strsplit (env_string, ";", -1);
+#endif
+      for (as = modules; *as; as++)
+       {
+         if (**as)
+           gtk_modules = g_slist_prepend (gtk_modules, *as);
+         else
+           g_free (*as);
+       }
+      g_free (modules);
+      env_string = NULL;
+    }
 
   if (argc && argv)
     {
@@ -267,11 +260,38 @@ gtk_init (int      *argc,
       
       for (i = 1; i < *argc;)
        {
-         if ((strcmp ("--gtk-debug", (*argv)[i]) == 0) ||
-             (strncmp ("--gtk-debug=", (*argv)[i], 12) == 0))
+         if (strcmp ("--gtk-module", (*argv)[i]) == 0 ||
+             strncmp ("--gtk-module=", (*argv)[i], 13) == 0)
            {
-             gchar *equal_pos = strchr ((*argv)[i], '=');
+             gchar *module_name = (*argv)[i] + 12;
+             
+             if (*module_name == '=')
+               module_name++;
+             else
+               {
+                 (*argv)[i] = NULL;
+                 i += 1;
+                 module_name = (*argv)[i];
+               }
+             (*argv)[i] = NULL;
 
+             gtk_modules = g_slist_prepend (gtk_modules, g_strdup (module_name));
+           }
+         else if (strcmp ("--g-fatal-warnings", (*argv)[i]) == 0)
+           {
+             GLogLevelFlags fatal_mask;
+             
+             fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+             fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
+              g_log_set_always_fatal (fatal_mask);
+             (*argv)[i] = NULL;
+           }
+#ifdef G_ENABLE_DEBUG
+         else if ((strcmp ("--gtk-debug", (*argv)[i]) == 0) ||
+                  (strncmp ("--gtk-debug=", (*argv)[i], 12) == 0))
+           {
+             gchar *equal_pos = strchr ((*argv)[i], '=');
+             
              if (equal_pos != NULL)
                {
                  gtk_debug_flags |= g_parse_debug_string (equal_pos+1,
@@ -292,7 +312,7 @@ gtk_init (int        *argc,
                   (strncmp ("--gtk-no-debug=", (*argv)[i], 15) == 0))
            {
              gchar *equal_pos = strchr ((*argv)[i], '=');
-
+             
              if (equal_pos != NULL)
                {
                  gtk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
@@ -309,68 +329,10 @@ gtk_init (int      *argc,
                }
              (*argv)[i] = NULL;
            }
-         else if (strcmp ("--gtk-module", (*argv)[i]) == 0 ||
-                  strncmp ("--gtk-module=", (*argv)[i], 13) == 0)
-           {
-             GModule *module = NULL;
-             GtkModuleInitFunc modinit_func = NULL;
-             gchar *module_name = (*argv)[i] + 12;
-
-             if (*module_name == '=')
-               module_name++;
-             else
-               {
-                 (*argv)[i] = NULL;
-                 i += 1;
-                 module_name = (*argv)[i];
-               }
-             if (module_name[0] == '/' ||
-                 (module_name[0] == 'l' &&
-                  module_name[1] == 'i' &&
-                  module_name[2] == 'b'))
-               module_name = g_strdup (module_name);
-             else
-               module_name = g_strconcat ("lib", module_name, ".so", NULL);
-             (*argv)[i] = NULL;
-             
-             if (g_module_supported ())
-               {
-                 module = g_module_open (module_name, G_MODULE_BIND_LAZY);
-                 if (module &&
-                     g_module_symbol (module, "gtk_module_init", (gpointer*) &modinit_func) &&
-                     modinit_func)
-                   {
-                     if (!g_slist_find (gtk_modinit_funcs, modinit_func))
-                       gtk_modinit_funcs = g_slist_prepend (gtk_modinit_funcs, modinit_func);
-                     else
-                       {
-                         g_module_close (module);
-                         module = NULL;
-                       }
-                   }
-               }
-             if (!modinit_func)
-               {
-                 g_warning ("Failed to load module \"%s\": %s",
-                            module ? g_module_name (module) : module_name,
-                            g_module_error ());
-                 if (module)
-                   g_module_close (module);
-               }
-             g_free (module_name);
-           }
-         else if (strcmp ("--g-fatal-warnings", (*argv)[i]) == 0)
-           {
-             GLogLevelFlags fatal_mask;
-
-             fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
-             fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
-              g_log_set_always_fatal (fatal_mask);
-             (*argv)[i] = NULL;
-           }
+#endif /* G_ENABLE_DEBUG */
          i += 1;
        }
-
+      
       for (i = 1; i < *argc; i++)
        {
          for (k = i; k < *argc; k++)
@@ -386,33 +348,73 @@ gtk_init (int      *argc,
            }
        }
     }
-
-#endif /* G_ENABLE_DEBUG */
-
-  /* Check if there is a good chance the mb functions will handle things
-   * correctly - set if either mblen("\xc0", MB_CUR_MAX) == 1 in the
-   * C locale, or we're using X's mb functions. (-DX_LOCALE && locale != C)
-   */
-
-  current_locale = g_strdup (setlocale (LC_CTYPE, NULL));
-
-#ifdef X_LOCALE
-  if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX")))
-    gtk_use_mb = TRUE;
-  else
-#endif
+  
+  /* load gtk modules */
+  gtk_modules = g_slist_reverse (gtk_modules);
+  for (slist = gtk_modules; slist; slist = slist->next)
     {
-      setlocale (LC_CTYPE, "C");
-      gtk_use_mb = (mblen ("\xc0", MB_CUR_MAX) == 1);
-      setlocale (LC_CTYPE, current_locale);
+      gchar *module_name;
+      GModule *module = NULL;
+      GtkModuleInitFunc modinit_func = NULL;
+      
+      module_name = slist->data;
+      slist->data = NULL;
+#ifndef __EMX__
+      if (!g_path_is_absolute (module_name))
+       {
+         gchar *old = module_name;
+         
+         module_name = g_module_build_path (NULL, module_name);
+         g_free (old);
+       }
+#else
+      module_name = add_dll_suffix(module_name);
+#endif
+      if (g_module_supported ())
+       {
+         module = g_module_open (module_name, G_MODULE_BIND_LAZY);
+         if (module &&
+             g_module_symbol (module, "gtk_module_init", (gpointer*) &modinit_func) &&
+             modinit_func)
+           {
+             if (!g_slist_find (gtk_modules, modinit_func))
+               {
+                 g_module_make_resident (module);
+                 slist->data = modinit_func;
+               }
+             else
+               {
+                 g_module_close (module);
+                 module = NULL;
+               }
+           }
+       }
+      if (!modinit_func)
+       {
+         g_warning ("Failed to load module \"%s\": %s",
+                    module ? g_module_name (module) : module_name,
+                    g_module_error ());
+         if (module)
+           g_module_close (module);
+       }
+      g_free (module_name);
     }
 
-  g_free (current_locale);
+#ifdef ENABLE_NLS
+#ifndef G_OS_WIN32
+  bindtextdomain("gtk+", GTK_LOCALEDIR);
+#else
+  {
+    /* GTk+ locale dir is %WinDir%\gtk+\locale */
+    extern char *get_gtk_sysconf_directory ();
+    bindtextdomain ("gtk+", g_strconcat (get_gtk_sysconf_directory (),
+                                        G_DIR_SEPARATOR_S,
+                                        "locale",
+                                        NULL));
+  }
+#endif
+#endif  
 
-  GTK_NOTE (MISC,
-           g_message ("%s multi-byte string functions.\n", 
-                      gtk_use_mb ? "Using" : "Not using"));
-  
   /* Initialize the default visual and colormap to be
    *  used in creating widgets. (We want to use the system
    *  defaults so as to be nice to the colormap).
@@ -421,41 +423,57 @@ gtk_init (int      *argc,
   gtk_colormap = gdk_colormap_get_system ();
 
   gtk_type_init ();
+  gtk_object_post_arg_parsing_init ();
   gtk_signal_init ();
   gtk_rc_init ();
   
   
   /* Register an exit function to make sure we are able to cleanup.
    */
-  if (ATEXIT (gtk_exit_func))
-    g_warning ("unable to register exit function");
+  g_atexit (gtk_exit_func);
   
   /* Set the 'initialized' flag.
    */
   gtk_initialized = TRUE;
 
-  /* initialize modules
+  /* initialize gtk modules
    */
-  if (gtk_modinit_funcs)
+  for (slist = gtk_modules; slist; slist = slist->next)
     {
-      GSList *slist;
-
-      slist = gtk_modinit_funcs;
-      while (slist)
+      if (slist->data)
        {
          GtkModuleInitFunc modinit;
-
+         
          modinit = slist->data;
          modinit (argc, argv);
-         slist = slist->next;
        }
-      
-      g_slist_free (gtk_modinit_funcs);
+    }
+  g_slist_free (gtk_modules);
+  
+#ifndef G_OS_WIN32
+  /* No use warning on Win32, there aren't any non-devel versions anyhow... */
+  g_warning (""              "YOU ARE USING THE DEVEL BRANCH 1.3.x OF GTK+ WHICH IS CURRENTLY\n"
+            "                UNDER HEAVY DEVELOPMENT AND FREQUENTLY INTRODUCES INSTABILITIES.\n"
+            "                if you don't know why you are getting this, you probably want to\n"
+            "                use the stable branch which can be retrived from\n"
+            "                ftp://ftp.gtk.org/pub/gtk/v1.2/ or via CVS with\n"
+            "                cvs checkout -r glib-1-2 glib; cvs checkout -r gtk-1-2 gtk+");
+#endif
+
+  return TRUE;
+}
+void
+gtk_init (int *argc, char ***argv)
+{
+  if (!gtk_init_check (argc, argv))
+    {
+      g_warning ("cannot open display: %s", gdk_get_display ());
+      exit(1);
     }
 }
 
 void
-gtk_exit (int errorcode)
+gtk_exit (gint errorcode)
 {
   /* Only if "gtk" has been initialized should we de-initialize.
    */
@@ -477,10 +495,13 @@ gtk_main (void)
   GList *tmp_list;
   GList *functions;
   GtkInitFunction *init;
-  int old_done;
-  
+  GMainLoop *loop;
+
   gtk_main_loop_level++;
   
+  loop = g_main_new (TRUE);
+  main_loops = g_slist_prepend (main_loops, loop);
+
   tmp_list = functions = init_functions;
   init_functions = NULL;
   
@@ -493,11 +514,14 @@ gtk_main (void)
       g_free (init);
     }
   g_list_free (functions);
-  
-  old_done = iteration_done;
-  while (!gtk_main_iteration ())
-    ;
-  iteration_done = old_done;
+
+  if (g_main_is_running (main_loops->data))
+    {
+      GDK_THREADS_LEAVE ();
+      g_main_run (loop);
+      GDK_THREADS_ENTER ();
+      gdk_flush ();
+    }
 
   if (quit_functions)
     {
@@ -531,8 +555,14 @@ gtk_main (void)
          work->next = quit_functions;
          quit_functions = work;
        }
+
+      gdk_flush ();
     }
              
+  main_loops = g_slist_remove (main_loops, loop);
+
+  g_main_destroy (loop);
+
   gtk_main_loop_level--;
 }
 
@@ -545,301 +575,263 @@ gtk_main_level (void)
 void
 gtk_main_quit (void)
 {
-  iteration_done = TRUE;
+  g_return_if_fail (main_loops != NULL);
+
+  g_main_quit (main_loops->data);
 }
 
 gint
 gtk_events_pending (void)
 {
-  gint result = 0;
-  
-  /* if this function is called from a timeout which will only return
-   * if gtk needs processor time, we need to take iteration_done==TRUE
-   * into account as well.
-   */
-  result = iteration_done;
-  result += next_event != NULL;
-  result += gdk_events_pending();
-
-  result += current_idles != NULL;
-  result += current_timeouts != NULL;
-
-  if (!result)
-    {
-      result += (idle_functions &&
-                (((GtkIdleFunction *)idle_functions->data)->priority <=
-                 GTK_PRIORITY_INTERNAL));
-    }
-  
-  if (!result && timeout_functions)
-    {
-      guint32 the_time;
-      GtkTimeoutFunction *timeoutf;
-      
-      the_time = gdk_time_get ();
-      
-      timeoutf = timeout_functions->data;
-      
-      result += timeoutf->interval <= (the_time - timeoutf->start);
-    }
-  
-  return result;
+  return g_main_pending();
 }
 
 gint 
 gtk_main_iteration (void)
 {
-  return gtk_main_iteration_do (TRUE);
+  g_main_iteration (TRUE);
+
+  if (main_loops)
+    return !g_main_is_running (main_loops->data);
+  else
+    return TRUE;
 }
 
-gint
+gint 
 gtk_main_iteration_do (gboolean blocking)
+{
+  g_main_iteration (blocking);
+
+  if (main_loops)
+    return !g_main_is_running (main_loops->data);
+  else
+    return TRUE;
+}
+
+void 
+gtk_main_do_event (GdkEvent *event)
 {
   GtkWidget *event_widget;
   GtkWidget *grab_widget;
-  GdkEvent *event = NULL;
+  GdkEvent *next_event;
   GList *tmp_list;
+
+  /* If there are any events pending then get the next one.
+   */
+  next_event = gdk_event_peek ();
   
-  iteration_done = FALSE;
-  
-  /* If this is a recursive call, and there are pending timeouts or
-   * idles, finish them, then return immediately to avoid blocking
-   * in gdk_event_get()
+  /* Try to compress enter/leave notify events. These event
+   *  pairs occur when the mouse is dragged quickly across
+   *  a window with many buttons (or through a menu). Instead
+   *  of highlighting and de-highlighting each widget that
+   *  is crossed it is better to simply de-highlight the widget
+   *  which contained the mouse initially and highlight the
+   *  widget which ends up containing the mouse.
    */
-  if (current_timeouts)
-    {
-      gtk_handle_current_timeouts( gdk_time_get());
-
-      if (iteration_done)
-       gdk_flush ();
+  if (next_event)
+    if (((event->type == GDK_ENTER_NOTIFY) ||
+        (event->type == GDK_LEAVE_NOTIFY)) &&
+       ((next_event->type == GDK_ENTER_NOTIFY) ||
+        (next_event->type == GDK_LEAVE_NOTIFY)) &&
+       (next_event->type != event->type) &&
+       (next_event->any.window == event->any.window))
+      {
+       /* Throw both the peeked copy and the queued copy away 
+        */
+       gdk_event_free (next_event);
+       next_event = gdk_event_get ();
+       gdk_event_free (next_event);
+       
+       return;
+      }
 
-      return iteration_done;
-    }
-  if (current_idles)
+  if (next_event)
+    gdk_event_free (next_event);
+
+  /* Find the widget which got the event. We store the widget
+   *  in the user_data field of GdkWindow's.
+   *  Ignore the event if we don't have a widget for it, except
+   *  for GDK_PROPERTY_NOTIFY events which are handled specialy.
+   *  Though this happens rarely, bogus events can occour
+   *  for e.g. destroyed GdkWindows. 
+   */
+  event_widget = gtk_get_event_widget (event);
+  if (!event_widget)
     {
-      gtk_handle_current_idles ();
-
-      if (iteration_done)
-       gdk_flush ();
-
-      return iteration_done;
+      /* To handle selection INCR transactions, we select
+       * PropertyNotify events on the requestor window and create
+       * a corresponding (fake) GdkWindow so that events get
+       * here. There won't be a widget though, so we have to handle
+          * them specially
+          */
+      if (event->type == GDK_PROPERTY_NOTIFY)
+       gtk_selection_incr_event (event->any.window,
+                                 &event->property);
+      
+      return;
     }
   
-  /* If there is a valid event in 'next_event' then move it to 'event'
+  /* Push the event onto a stack of current events for
+   * gtk_current_event_get().
    */
-  if (next_event)
-    {
-      event = next_event;
-      next_event = NULL;
-    }
+  current_events = g_list_prepend (current_events, event);
   
-  /* If we don't have an event then get one.
+  /* If there is a grab in effect...
    */
-  if (!event)
+  if (grabs)
     {
-      /* Handle setting of the "gdk" timer. If there are no
-       *  timeout functions, then the timer is turned off.
-       *  If there are timeout functions, then the timer is
-       *  set to the shortest timeout interval (which is
-       *  the first timeout function).
-       */
-      gtk_handle_timer ();
+      grab_widget = grabs->data;
       
-      if (blocking) event = gdk_event_get ();
+      /* If the grab widget is an ancestor of the event widget
+       *  then we send the event to the original event widget.
+       *  This is the key to implementing modality.
+       */
+      if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
+         gtk_widget_is_ancestor (event_widget, grab_widget))
+       grab_widget = event_widget;
     }
-  
-  /* "gdk_event_get" can return FALSE if the timer goes off
-   *  and no events are pending. Therefore, we should make
-   *  sure that we got an event before continuing.
+  else
+    {
+      grab_widget = event_widget;
+    }
+
+  /* Not all events get sent to the grabbing widget.
+   * The delete, destroy, expose, focus change and resize
+   *  events still get sent to the event widget because
+   *  1) these events have no meaning for the grabbing widget
+   *  and 2) redirecting these events to the grabbing widget
+   *  could cause the display to be messed up.
+   * 
+   * Drag events are also not redirected, since it isn't
+   *  clear what the semantics of that would be.
    */
-  if (event)
+  switch (event->type)
     {
-      /* If there are any events pending then get the next one.
-       */
-      if (gdk_events_pending () > 0)
-       next_event = gdk_event_get ();
+    case GDK_NOTHING:
+      break;
       
-      /* Try to compress enter/leave notify events. These event
-       *  pairs occur when the mouse is dragged quickly across
-       *  a window with many buttons (or through a menu). Instead
-       *  of highlighting and de-highlighting each widget that
-       *  is crossed it is better to simply de-highlight the widget
-       *  which contained the mouse initially and highlight the
-       *  widget which ends up containing the mouse.
-       */
-      if (next_event)
-       if (((event->type == GDK_ENTER_NOTIFY) ||
-            (event->type == GDK_LEAVE_NOTIFY)) &&
-           ((next_event->type == GDK_ENTER_NOTIFY) ||
-            (next_event->type == GDK_LEAVE_NOTIFY)) &&
-           (next_event->type != event->type) &&
-           (next_event->any.window == event->any.window))
-         {
-           gdk_event_free (event);
-           gdk_event_free (next_event);
-           next_event = NULL;
-           
-           goto event_handling_done;
-         }
+    case GDK_DELETE:
+      gtk_widget_ref (event_widget);
+      if (!gtk_widget_event (event_widget, event) &&
+         !GTK_OBJECT_DESTROYED (event_widget))
+       gtk_widget_destroy (event_widget);
+      gtk_widget_unref (event_widget);
+      break;
       
-      /* Find the widget which got the event. We store the widget
-       *  in the user_data field of GdkWindow's.
-       *  Ignore the event if we don't have a widget for it, except
-       *  for GDK_PROPERTY_NOTIFY events which are handled specialy.
-       *  Though this happens rarely, bogus events can occour
-       *  for e.g. destroyed GdkWindows. 
-       */
-      event_widget = gtk_get_event_widget (event);
-      if (!event_widget)
+    case GDK_DESTROY:
+      gtk_widget_ref (event_widget);
+      gtk_widget_event (event_widget, event);
+      if (!GTK_OBJECT_DESTROYED (event_widget))
+       gtk_widget_destroy (event_widget);
+      gtk_widget_unref (event_widget);
+      break;
+      
+    case GDK_PROPERTY_NOTIFY:
+    case GDK_EXPOSE:
+    case GDK_NO_EXPOSE:
+    case GDK_FOCUS_CHANGE:
+    case GDK_CONFIGURE:
+    case GDK_MAP:
+    case GDK_UNMAP:
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+    case GDK_CLIENT_EVENT:
+    case GDK_VISIBILITY_NOTIFY:
+      gtk_widget_event (event_widget, event);
+      break;
+
+    case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
+    /* We treat button 4-5 specially, assume we have
+     * a MS-style scrollwheel mouse, and try to find
+     * a plausible widget to scroll. We also trap
+     * button 4-5 double and triple clicks here, since
+     * they will be generated if the user scrolls quickly.
+     */
+      if ((grab_widget == event_widget) &&
+         (event->button.button == 4 || event->button.button == 5))
        {
-         /* To handle selection INCR transactions, we select
-          * PropertyNotify events on the requestor window and create
-          * a corresponding (fake) GdkWindow so that events get
-          * here. There won't be a widget though, so we have to handle
-          * them specially
-          */
-         if (event->type == GDK_PROPERTY_NOTIFY)
-           gtk_selection_incr_event (event->any.window,
-                                     &event->property);
+         GtkWidget *range = NULL;
+         GtkWidget *scrollwin;
          
-         gdk_event_free (event);
+         if (GTK_IS_RANGE (event_widget))
+           range = event_widget;
+         else
+           {
+             scrollwin = gtk_widget_get_ancestor (event_widget,
+                                                  GTK_TYPE_SCROLLED_WINDOW);
+             if (scrollwin)
+               range = GTK_SCROLLED_WINDOW (scrollwin)->vscrollbar;
+           }
          
-         goto event_handling_done;
+         if (range && GTK_WIDGET_VISIBLE (range))
+           {
+             if (event->type == GDK_BUTTON_PRESS)
+               {
+                 GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
+                 gfloat new_value = adj->value + ((event->button.button == 4) ? 
+                                                  -adj->page_increment / 2: 
+                                                   adj->page_increment / 2);
+                 new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
+                 gtk_adjustment_set_value (adj, new_value);
+               }
+             break;
+           }
        }
-      
-      /* Push the event onto a stack of current events for
-       * gtk_current_event_get().
-       */
-      current_events = g_list_prepend (current_events, event);
-      
-      /* If there is a grab in effect...
-       */
-      if (grabs)
+      gtk_propagate_event (grab_widget, event);
+      break;
+
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      if (key_snoopers)
        {
-         grab_widget = grabs->data;
-         
-         /* If the grab widget is an ancestor of the event widget
-          *  then we send the event to the original event widget.
-          *  This is the key to implementing modality.
-          */
-         if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
-             gtk_widget_is_ancestor (event_widget, grab_widget))
-           grab_widget = event_widget;
+         if (gtk_invoke_key_snoopers (grab_widget, event))
+           break;
        }
-      else
+      /* else fall through */
+    case GDK_MOTION_NOTIFY:
+    case GDK_BUTTON_RELEASE:
+    case GDK_PROXIMITY_IN:
+    case GDK_PROXIMITY_OUT:
+      gtk_propagate_event (grab_widget, event);
+      break;
+      
+    case GDK_ENTER_NOTIFY:
+      if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
        {
-         grab_widget = event_widget;
+         gtk_widget_event (grab_widget, event);
+         if (event_widget == grab_widget)
+           GTK_PRIVATE_SET_FLAG (event_widget, GTK_LEAVE_PENDING);
        }
-
-      /* Not all events get sent to the grabbing widget.
-       * The delete, destroy, expose, focus change and resize
-       *  events still get sent to the event widget because
-       *  1) these events have no meaning for the grabbing widget
-       *  and 2) redirecting these events to the grabbing widget
-       *  could cause the display to be messed up.
-       */
-      switch (event->type)
+      break;
+      
+    case GDK_LEAVE_NOTIFY:
+      if (GTK_WIDGET_LEAVE_PENDING (event_widget))
        {
-       case GDK_NOTHING:
-         break;
-         
-       case GDK_DELETE:
-         gtk_widget_ref (event_widget);
-         if (!gtk_widget_event (event_widget, event) &&
-             !GTK_OBJECT_DESTROYED (event_widget))
-           gtk_widget_destroy (event_widget);
-         gtk_widget_unref (event_widget);
-         break;
-         
-       case GDK_DESTROY:
-         gtk_widget_ref (event_widget);
-         gtk_widget_event (event_widget, event);
-         if (!GTK_OBJECT_DESTROYED (event_widget))
-           gtk_widget_destroy (event_widget);
-         gtk_widget_unref (event_widget);
-         break;
-         
-       case GDK_PROPERTY_NOTIFY:
-       case GDK_EXPOSE:
-       case GDK_NO_EXPOSE:
-       case GDK_FOCUS_CHANGE:
-       case GDK_CONFIGURE:
-       case GDK_MAP:
-       case GDK_UNMAP:
-       case GDK_SELECTION_CLEAR:
-       case GDK_SELECTION_REQUEST:
-       case GDK_SELECTION_NOTIFY:
-       case GDK_CLIENT_EVENT:
-       case GDK_DRAG_BEGIN:
-       case GDK_DRAG_REQUEST:
-       case GDK_DROP_ENTER:
-       case GDK_DROP_LEAVE:
-       case GDK_DROP_DATA_AVAIL:
-       case GDK_VISIBILITY_NOTIFY:
+         GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_LEAVE_PENDING);
          gtk_widget_event (event_widget, event);
-         break;
-         
-       case GDK_KEY_PRESS:
-       case GDK_KEY_RELEASE:
-         if (key_snoopers)
-           {
-             if (gtk_invoke_key_snoopers (grab_widget, event))
-               break;
-           }
-         /* else fall through */
-       case GDK_MOTION_NOTIFY:
-       case GDK_BUTTON_PRESS:
-       case GDK_2BUTTON_PRESS:
-       case GDK_3BUTTON_PRESS:
-       case GDK_BUTTON_RELEASE:
-       case GDK_PROXIMITY_IN:
-       case GDK_PROXIMITY_OUT:
-       case GDK_OTHER_EVENT:
-         gtk_propagate_event (grab_widget, event);
-         break;
-         
-       case GDK_ENTER_NOTIFY:
-         if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
-           {
-             gtk_widget_event (grab_widget, event);
-             if (event_widget == grab_widget)
-               GTK_PRIVATE_SET_FLAG (event_widget, GTK_LEAVE_PENDING);
-           }
-         break;
-         
-       case GDK_LEAVE_NOTIFY:
-         if (GTK_WIDGET_LEAVE_PENDING (event_widget))
-           {
-             GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_LEAVE_PENDING);
-             gtk_widget_event (event_widget, event);
-           }
-         else if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
-           gtk_widget_event (grab_widget, event);
-         break;
        }
+      else if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
+       gtk_widget_event (grab_widget, event);
+      break;
       
-      tmp_list = current_events;
-      current_events = g_list_remove_link (current_events, tmp_list);
-      g_list_free_1 (tmp_list);
-      
-      gdk_event_free (event);
+    case GDK_DRAG_STATUS:
+    case GDK_DROP_FINISHED:
+      gtk_drag_source_handle_event (event_widget, event);
+      break;
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DROP_START:
+      gtk_drag_dest_handle_event (event_widget, event);
+      break;
     }
-  else
-    {
-      if (gdk_events_pending() == 0)
-       gtk_handle_idle ();
-    }
-  
-event_handling_done:
-  
-  /* Handle timeout functions that may have expired.
-   */
-  gtk_handle_timeouts ();
-  
-  if (iteration_done)
-    gdk_flush ();
   
-  return iteration_done;
+  tmp_list = current_events;
+  current_events = g_list_remove_link (current_events, tmp_list);
+  g_list_free_1 (tmp_list);
 }
 
 gint
@@ -961,129 +953,6 @@ gtk_invoke_key_snoopers (GtkWidget *grab_widget,
   return return_val;
 }
 
-guint
-gtk_timeout_add_full (guint32           interval,
-                     GtkFunction        function,
-                     GtkCallbackMarshal marshal,
-                     gpointer           data,
-                     GtkDestroyNotify   destroy)
-{
-  static guint timeout_tag = 1;
-  GtkTimeoutFunction *timeoutf;
-  
-  g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
-
-  /* Create a new timeout function structure.
-   * The start time is the current time.
-   */
-  if (!timeout_mem_chunk)
-    timeout_mem_chunk = g_mem_chunk_new ("timeout mem chunk", sizeof (GtkTimeoutFunction),
-                                        1024, G_ALLOC_AND_FREE);
-  
-  timeoutf = g_chunk_new (GtkTimeoutFunction, timeout_mem_chunk);
-  
-  timeoutf->tag = timeout_tag++;
-  timeoutf->start = gdk_time_get ();
-  timeoutf->interval = interval;
-  timeoutf->originterval = interval;
-  timeoutf->function = function;
-  timeoutf->marshal = marshal;
-  timeoutf->data = data;
-  timeoutf->destroy = destroy;
-  
-  gtk_timeout_insert (timeoutf);
-  
-  return timeoutf->tag;
-}
-
-static void
-gtk_timeout_destroy (GtkTimeoutFunction *timeoutf)
-{
-  if (timeoutf->destroy)
-    (timeoutf->destroy) (timeoutf->data);
-  g_mem_chunk_free (timeout_mem_chunk, timeoutf);
-}
-
-guint
-gtk_timeout_add (guint32     interval,
-                GtkFunction function,
-                gpointer    data)
-{
-  return gtk_timeout_add_full (interval, function, FALSE, data, NULL);
-}
-
-guint
-gtk_timeout_add_interp (guint32                   interval,
-                       GtkCallbackMarshal function,
-                       gpointer           data,
-                       GtkDestroyNotify   destroy)
-{
-  return gtk_timeout_add_full (interval, NULL, function, data, destroy);
-}
-
-/* Search for the specified tag in a list of timeouts. If it
- * is found, destroy the timeout, and either remove the link
- * or set link->data to NULL depending on remove_link
- */
-static gint
-gtk_timeout_remove_from_list (GList **list, guint tag, gint remove_link)
-{
-  GList *tmp_list;
-  GtkTimeoutFunction *timeoutf;
-
-  tmp_list = *list;
-  while (tmp_list)
-    {
-      timeoutf = tmp_list->data;
-      
-      if (timeoutf->tag == tag)
-       {
-         if (remove_link)
-           {
-             *list = g_list_remove_link (*list, tmp_list);
-             g_list_free (tmp_list);
-           }
-         else
-           tmp_list->data = NULL;
-
-         gtk_timeout_destroy (timeoutf);
-         
-         return TRUE;
-       }
-      
-      tmp_list = tmp_list->next;
-    }
-  return FALSE;
-}
-
-void
-gtk_timeout_remove (guint tag)
-{
-  
-  /* Remove a timeout function.
-   * (Which, basically, involves searching the
-   *  list for the tag).
-   */
-
-  if (gtk_timeout_remove_from_list (&timeout_functions, tag, TRUE))
-    return;
-  if (gtk_timeout_remove_from_list (&current_timeouts, tag, TRUE))
-    return;
-  if (gtk_timeout_remove_from_list (&running_timeouts, tag, FALSE))
-    return;
-}
-
-/* We rely on some knowledge of how g_list_insert_sorted works to make
- * sure that we insert at the _end_ of the idles of this priority
- */
-static gint
-gtk_idle_compare (gconstpointer a, gconstpointer b)
-{
-  return (((const GtkIdleFunction *)a)->priority <
-         ((const GtkIdleFunction *)b)->priority)
-    ? -1 : 1;
-}
-
 guint
 gtk_quit_add_full (guint               main_level,
                   GtkFunction          function,
@@ -1114,59 +983,6 @@ gtk_quit_add_full (guint          main_level,
   return quitf->id;
 }
 
-guint
-gtk_idle_add_full (gint                        priority,
-                  GtkFunction          function,
-                  GtkCallbackMarshal   marshal,
-                  gpointer             data,
-                  GtkDestroyNotify     destroy)
-{
-  static guint idle_tag = 1;
-  GtkIdleFunction *idlef;
-  
-  g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
-
-  if (!idle_mem_chunk)
-    idle_mem_chunk = g_mem_chunk_new ("idle mem chunk", sizeof (GtkIdleFunction),
-                                     1024, G_ALLOC_AND_FREE);
-  
-  idlef = g_chunk_new (GtkIdleFunction, idle_mem_chunk);
-  
-  idlef->tag = idle_tag++;
-  idlef->priority = priority;
-  idlef->function = function;
-  idlef->marshal = marshal;
-  idlef->data = data;
-  idlef->destroy = destroy;
-
-  /* If we are adding the first idle function, possibly wake up
-   * the main thread out of its select().
-   */
-  if (!idle_functions)
-    gdk_threads_wake ();
-
-  idle_functions = g_list_insert_sorted (idle_functions, idlef, gtk_idle_compare);
-
-  
-  return idlef->tag;
-}
-
-guint
-gtk_idle_add_interp  (GtkCallbackMarshal   marshal,
-                     gpointer             data,
-                     GtkDestroyNotify     destroy)
-{
-  return gtk_idle_add_full (GTK_PRIORITY_DEFAULT, NULL, marshal, data, destroy);
-}
-
-static void
-gtk_idle_destroy (GtkIdleFunction *idlef)
-{
-  if (idlef->destroy)
-    idlef->destroy (idlef->data);
-  g_mem_chunk_free (idle_mem_chunk, idlef);
-}
-
 static void
 gtk_quit_destroy (GtkQuitFunction *quitf)
 {
@@ -1212,21 +1028,6 @@ gtk_quit_add (guint        main_level,
   return gtk_quit_add_full (main_level, function, NULL, data, NULL);
 }
 
-guint
-gtk_idle_add (GtkFunction function,
-             gpointer    data)
-{
-  return gtk_idle_add_full (GTK_PRIORITY_DEFAULT, function, NULL, data, NULL);
-}
-
-guint      
-gtk_idle_add_priority  (gint               priority,
-                        GtkFunction        function,
-                        gpointer           data)
-{
-  return gtk_idle_add_full (priority, function, NULL, data, NULL);
-}
-
 void
 gtk_quit_remove (guint id)
 {
@@ -1275,120 +1076,120 @@ gtk_quit_remove_by_data (gpointer data)
     }
 }
 
-/* Search for the specified tag in a list of idles. If it
- * is found, destroy the idle, and either remove the link
- * or set link->data to NULL depending on remove_link
- *
- * If tag != 0, match tag against idlef->tag, otherwise, match
- * data against idlef->data
- */
-static gint
-gtk_idle_remove_from_list (GList  **list, 
-                          guint    tag, 
-                          gpointer data, 
-                          gint     remove_link)
+guint
+gtk_timeout_add_full (guint32           interval,
+                     GtkFunction        function,
+                     GtkCallbackMarshal marshal,
+                     gpointer           data,
+                     GtkDestroyNotify   destroy)
 {
-  GtkIdleFunction *idlef;
-  GList *tmp_list;
-  
-  tmp_list = *list;
-  while (tmp_list)
+  if (marshal)
     {
-      idlef = tmp_list->data;
-      
-      if (((tag != 0) && (idlef->tag == tag)) ||
-         ((tag == 0) && (idlef->data == data)))
-       {
-         if (remove_link)
-           {
-             *list = g_list_remove_link (*list, tmp_list);
-             g_list_free (tmp_list);
-           }
-         else
-           tmp_list->data = NULL;
+      GtkClosure *closure;
 
-         gtk_idle_destroy (idlef);
-         
-         return TRUE;
-       }
-      
-      tmp_list = tmp_list->next;
+      closure = g_new (GtkClosure, 1);
+      closure->marshal = marshal;
+      closure->data = data;
+      closure->destroy = destroy;
+
+      return g_timeout_add_full (0, interval, 
+                                gtk_invoke_idle_timeout,
+                                closure,
+                                gtk_destroy_closure);
     }
-  return FALSE;
+  else
+    return g_timeout_add_full (0, interval, function, data, destroy);
 }
 
-void
-gtk_idle_remove (guint tag)
+guint
+gtk_timeout_add (guint32     interval,
+                GtkFunction function,
+                gpointer    data)
 {
-  g_return_if_fail (tag != 0);
-  
-  if (gtk_idle_remove_from_list (&idle_functions, tag, NULL, TRUE))
-    return;
-  if (gtk_idle_remove_from_list (&current_idles, tag, NULL, TRUE))
-    return;
-  if (gtk_idle_remove_from_list (&running_idles, tag, NULL, FALSE))
-    return;
+  return g_timeout_add_full (0, interval, function, data, NULL);
 }
 
 void
-gtk_idle_remove_by_data (gpointer data)
+gtk_timeout_remove (guint tag)
 {
-  if (gtk_idle_remove_from_list (&idle_functions, 0, data, TRUE))
-    return;
-  if (gtk_idle_remove_from_list (&current_idles, 0, data, TRUE))
-    return;
-  if (gtk_idle_remove_from_list (&running_idles, 0, data, FALSE))
-    return;
+  g_source_remove (tag);
 }
 
-static void
-gtk_invoke_input_function (GtkInputFunction *input,
-                          gint source,
-                          GdkInputCondition condition)
+guint
+gtk_idle_add_full (gint                        priority,
+                  GtkFunction          function,
+                  GtkCallbackMarshal   marshal,
+                  gpointer             data,
+                  GtkDestroyNotify     destroy)
 {
-  GtkArg args[3];
-  args[0].type = GTK_TYPE_INT;
-  args[0].name = NULL;
-  GTK_VALUE_INT(args[0]) = source;
-  args[1].type = GTK_TYPE_GDK_INPUT_CONDITION;
-  args[1].name = NULL;
-  GTK_VALUE_FLAGS(args[1]) = condition;
-  args[2].type = GTK_TYPE_NONE;
-  args[2].name = NULL;
+  if (marshal)
+    {
+      GtkClosure *closure;
 
-  input->callback (NULL, input->data, 2, args);
+      closure = g_new (GtkClosure, 1);
+      closure->marshal = marshal;
+      closure->data = data;
+      closure->destroy = destroy;
+
+      return g_idle_add_full (priority,
+                             gtk_invoke_idle_timeout,
+                             closure,
+                             gtk_destroy_closure);
+    }
+  else
+    return g_idle_add_full (priority, function, data, destroy);
 }
 
-static void
-gtk_destroy_input_function (GtkInputFunction *input)
+guint
+gtk_idle_add (GtkFunction function,
+             gpointer    data)
+{
+  return g_idle_add_full (GTK_PRIORITY_DEFAULT, function, data, NULL);
+}
+
+guint      
+gtk_idle_add_priority  (gint               priority,
+                        GtkFunction        function,
+                        gpointer           data)
 {
-  if (input->destroy)
-    (input->destroy) (input->data);
-  g_free (input);
+  return g_idle_add_full (priority, function, data, NULL);
+}
+
+void
+gtk_idle_remove (guint tag)
+{
+  g_source_remove (tag);
+}
+
+void
+gtk_idle_remove_by_data (gpointer data)
+{
+  if (!g_idle_remove_by_data (data))
+    g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
 }
 
 guint
-gtk_input_add_full (gint source,
-                   GdkInputCondition condition,
-                   GdkInputFunction function,
-                   GtkCallbackMarshal marshal,
-                   gpointer data,
-                   GtkDestroyNotify destroy)
+gtk_input_add_full (gint               source,
+                   GdkInputCondition   condition,
+                   GdkInputFunction    function,
+                   GtkCallbackMarshal  marshal,
+                   gpointer            data,
+                   GtkDestroyNotify    destroy)
 {
   if (marshal)
     {
-      GtkInputFunction *input;
+      GtkClosure *closure;
 
-      input = g_new (GtkInputFunction, 1);
-      input->callback = marshal;
-      input->data = data;
-      input->destroy = destroy;
+      closure = g_new (GtkClosure, 1);
+      closure->marshal = marshal;
+      closure->data = data;
+      closure->destroy = destroy;
 
       return gdk_input_add_full (source,
                                 condition,
-                                (GdkInputFunction) gtk_invoke_input_function,
-                                input,
-                                (GdkDestroyNotify) gtk_destroy_input_function);
+                                (GdkInputFunction) gtk_invoke_input,
+                                closure,
+                                (GdkDestroyNotify) gtk_destroy_closure);
     }
   else
     return gdk_input_add_full (source, condition, function, data, destroy);
@@ -1397,10 +1198,54 @@ gtk_input_add_full (gint source,
 void
 gtk_input_remove (guint tag)
 {
-  gdk_input_remove (tag);
+  g_source_remove (tag);
+}
+
+static void
+gtk_destroy_closure (gpointer data)
+{
+  GtkClosure *closure = data;
+
+  if (closure->destroy)
+    (closure->destroy) (closure->data);
+  g_free (closure);
+}
+
+static gboolean
+gtk_invoke_idle_timeout (gpointer data)
+{
+  GtkClosure *closure = data;
+
+  GtkArg args[1];
+  gint ret_val = FALSE;
+  args[0].name = NULL;
+  args[0].type = GTK_TYPE_BOOL;
+  args[0].d.pointer_data = &ret_val;
+  closure->marshal (NULL, closure->data,  0, args);
+  return ret_val;
 }
 
-GdkEvent *
+static void
+gtk_invoke_input (gpointer         data,
+                 gint              source,
+                 GdkInputCondition condition)
+{
+  GtkClosure *closure = data;
+
+  GtkArg args[3];
+  args[0].type = GTK_TYPE_INT;
+  args[0].name = NULL;
+  GTK_VALUE_INT(args[0]) = source;
+  args[1].type = GTK_TYPE_GDK_INPUT_CONDITION;
+  args[1].name = NULL;
+  GTK_VALUE_FLAGS(args[1]) = condition;
+  args[2].type = GTK_TYPE_NONE;
+  args[2].name = NULL;
+
+  closure->marshal (NULL, closure->data, 2, args);
+}
+
+GdkEvent*
 gtk_get_current_event (void)
 {
   if (current_events)
@@ -1432,132 +1277,6 @@ gtk_exit_func (void)
 }
 
 
-/* We rely on some knowledge of how g_list_insert_sorted works to make
- * sure that we insert after timeouts of equal interval
- */
-static gint
-gtk_timeout_compare (gconstpointer a, gconstpointer b)
-{
-  return (((const GtkTimeoutFunction *)a)->interval < 
-         ((const GtkTimeoutFunction *)b)->interval)
-    ? -1 : 1;
-}
-
-static void
-gtk_timeout_insert (GtkTimeoutFunction *timeoutf)
-{
-  g_assert (timeoutf != NULL);
-  
-  /* Insert the timeout function appropriately.
-   * Appropriately meaning sort it into the list
-   *  of timeout functions.
-   */
-  timeout_functions = g_list_insert_sorted (timeout_functions, timeoutf,
-                                           gtk_timeout_compare);
-}
-
-static gint
-gtk_invoke_timeout_function (GtkTimeoutFunction *timeoutf)
-{
-  if (!timeoutf->marshal)
-    return timeoutf->function (timeoutf->data);
-  else
-    {
-      GtkArg args[1];
-      gint ret_val = FALSE;
-      args[0].name = NULL;
-      args[0].type = GTK_TYPE_BOOL;
-      args[0].d.pointer_data = &ret_val;
-      timeoutf->marshal (NULL, timeoutf->data,  0, args);
-      return ret_val;
-    }
-}
-
-static void
-gtk_handle_current_timeouts (guint32 the_time)
-{
-  gint result;
-  GList *tmp_list;
-  GtkTimeoutFunction *timeoutf;
-  
-  while (current_timeouts)
-    {
-      tmp_list = current_timeouts;
-      timeoutf = tmp_list->data;
-      
-      current_timeouts = g_list_remove_link (current_timeouts, tmp_list);
-      if (running_timeouts)
-       {
-         running_timeouts->prev = tmp_list;
-         tmp_list->next = running_timeouts;
-       }
-      running_timeouts = tmp_list;
-      
-      result = gtk_invoke_timeout_function (timeoutf);
-
-      running_timeouts = g_list_remove_link (running_timeouts, tmp_list);
-      timeoutf = tmp_list->data;
-      
-      g_list_free_1 (tmp_list);
-
-      if (timeoutf)
-       {
-         if (!result)
-           {
-             gtk_timeout_destroy (timeoutf);
-           }
-         else
-           {
-             timeoutf->interval = timeoutf->originterval;
-             timeoutf->start = the_time;
-             gtk_timeout_insert (timeoutf);
-           }
-       }
-    }
-}
-
-static void
-gtk_handle_timeouts (void)
-{
-  guint32 the_time;
-  GList *tmp_list;
-  GList *tmp_list2;
-  GtkTimeoutFunction *timeoutf;
-  
-  /* Caller must already have called gtk_handle_current_timeouts if
-   * necessary */
-  g_assert (current_timeouts == NULL);
-  
-  if (timeout_functions)
-    {
-      the_time = gdk_time_get ();
-      
-      tmp_list = timeout_functions;
-      while (tmp_list)
-       {
-         timeoutf = tmp_list->data;
-         
-         if (timeoutf->interval <= (the_time - timeoutf->start))
-           {
-             tmp_list2 = tmp_list;
-             tmp_list = tmp_list->next;
-             
-             timeout_functions = g_list_remove_link (timeout_functions, tmp_list2);
-             current_timeouts = g_list_concat (current_timeouts, tmp_list2);
-           }
-         else
-           {
-             timeoutf->interval -= (the_time - timeoutf->start);
-             timeoutf->start = the_time;
-             tmp_list = tmp_list->next;
-           }
-       }
-      
-      if (current_timeouts)
-       gtk_handle_current_timeouts (the_time);
-    }
-}
-
 static gint
 gtk_quit_invoke_function (GtkQuitFunction *quitf)
 {
@@ -1578,152 +1297,14 @@ gtk_quit_invoke_function (GtkQuitFunction *quitf)
     }
 }
 
-static gint
-gtk_idle_invoke_function (GtkIdleFunction *idlef)
-{
-  if (!idlef->marshal)
-    return idlef->function (idlef->data);
-  else
-    {
-      GtkArg args[1];
-      gint ret_val = FALSE;
-
-      args[0].name = NULL;
-      args[0].type = GTK_TYPE_BOOL;
-      args[0].d.pointer_data = &ret_val;
-      ((GtkCallbackMarshal) idlef->marshal) (NULL,
-                                            idlef->data,
-                                            0, args);
-      return ret_val;
-    }
-}
-
-static void
-gtk_handle_current_idles (void)
-{
-  GList *tmp_list;
-  GList *tmp_list2;
-  GtkIdleFunction *idlef;
-  gint result;
-  
-  while (current_idles)
-    {
-      tmp_list = current_idles;
-      idlef = tmp_list->data;
-      
-      current_idles = g_list_remove_link (current_idles, tmp_list);
-      if (running_idles)
-       {
-         running_idles->prev = tmp_list;
-         tmp_list->next = running_idles;
-       }
-      running_idles = tmp_list;
-
-      result = gtk_idle_invoke_function (idlef);
-      
-      running_idles = g_list_remove_link (running_idles, tmp_list);
-      idlef = tmp_list->data;
-      
-      if (!idlef || !result)
-       {
-         g_list_free (tmp_list);
-         if (idlef)
-           gtk_idle_destroy (idlef);
-       }
-      else
-       {
-         /* Insert the idle function back into the list of idle
-          * functions at the end of the idles of this priority
-          */
-         tmp_list2 = idle_functions;
-         while (tmp_list2 &&
-                (((GtkIdleFunction *)tmp_list2->data)->priority <= idlef->priority))
-           tmp_list2 = tmp_list2->next;
-
-         if (!tmp_list2)
-           idle_functions = g_list_concat (idle_functions, tmp_list);
-         else if (tmp_list2 == idle_functions)
-           {
-             tmp_list->next = idle_functions;
-             if (idle_functions)
-               idle_functions->prev = tmp_list;
-             idle_functions = tmp_list;
-           }
-         else
-           {
-             tmp_list->prev = tmp_list2->prev;
-             tmp_list->next = tmp_list2;
-             tmp_list2->prev->next = tmp_list;
-             tmp_list2->prev = tmp_list;
-           }
-       }
-    }
-}
-
-static void
-gtk_handle_idle (void)
-{
-  /* Caller must already have called gtk_handle_current_idles if
-   * necessary
-   */
-  g_assert (current_idles == NULL);
-  
-  /* Handle only the idle functions that have the highest priority */
-  if (idle_functions)
-    {
-      GList *tmp_list;
-      gint top_priority;
-
-      tmp_list = idle_functions;
-      top_priority = ((GtkIdleFunction *)tmp_list->data)->priority;
-      while (tmp_list &&
-            (((GtkIdleFunction *)tmp_list->data)->priority == top_priority))
-       tmp_list = tmp_list->next;
-
-      current_idles = idle_functions;
-      idle_functions = tmp_list;
-
-      if (tmp_list) 
-       {
-         tmp_list->prev->next = NULL;
-         tmp_list->prev = NULL;
-       }
-      
-      gtk_handle_current_idles();
-    }
-}
-
-static void
-gtk_handle_timer (void)
-{
-  GtkTimeoutFunction *timeoutf;
-  
-  if (idle_functions)
-    {
-      gdk_timer_set (0);
-      gdk_timer_enable ();
-    }
-  else if (timeout_functions)
-    {
-      timeoutf = timeout_functions->data;
-      gdk_timer_set (timeoutf->interval);
-      gdk_timer_enable ();
-    }
-  else
-    {
-      gdk_timer_set (0);
-      gdk_timer_disable ();
-    }
-}
-
-static void
+void
 gtk_propagate_event (GtkWidget *widget,
                     GdkEvent  *event)
 {
   gint handled_event;
   
   g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_WIDGET (widget));
   g_return_if_fail (event != NULL);
   
   handled_event = FALSE;
@@ -1738,7 +1319,7 @@ gtk_propagate_event (GtkWidget *widget,
        */
       GtkWidget *window;
 
-      window = gtk_widget_get_ancestor (widget, gtk_window_get_type ());
+      window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
       if (window)
         {
          if (GTK_WIDGET_IS_SENSITIVE (window))
@@ -1764,7 +1345,7 @@ gtk_propagate_event (GtkWidget *widget,
     }
 }
 
-
+#if 0
 static void
 gtk_error (gchar *str)
 {
@@ -1820,7 +1401,7 @@ gtk_print (gchar *str)
       
       
       box2 = gtk_vbox_new (FALSE, 10);
-      gtk_container_border_width (GTK_CONTAINER (box2), 10);
+      gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
       gtk_widget_show (box2);
       
@@ -1853,7 +1434,7 @@ gtk_print (gchar *str)
       
       
       box2 = gtk_vbox_new (FALSE, 10);
-      gtk_container_border_width (GTK_CONTAINER (box2), 10);
+      gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
       gtk_widget_show (box2);
       
@@ -1875,4 +1456,4 @@ gtk_print (gchar *str)
   if (!GTK_WIDGET_VISIBLE (window))
     gtk_widget_show (window);
 }
-
+#endif