X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkmain.c;h=fa558da93a7656d68e4c5ea5cf18209d86fcabad;hb=1c84483f3ee8559179b49a200d3cc6854e81b873;hp=e31c2c90ccf333d14be04cd0b3bef98176f7c178;hpb=11f79ebe181fcb26a651385cd0d1dd7066f68bcd;p=~andy%2Fgtk diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index e31c2c90c..fa558da93 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -12,18 +12,38 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * License along with this library; if not, write to the + * 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 */ + +#if GDK_WINDOWING == GDK_WINDOWING_X11 #include /* so we get the right setlocale */ +#else +#include +#endif #include #include +#include +#include #include "gtkbutton.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" @@ -34,17 +54,15 @@ #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 @@ -63,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; }; @@ -102,37 +98,34 @@ 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_compare (gpointer a, - gpointer b); - -static gint gtk_timeout_compare (gpointer a, - gpointer b); +#endif const guint gtk_major_version = GTK_MAJOR_VERSION; const guint gtk_minor_version = GTK_MINOR_VERSION; 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 main_level = 0; -static gint initialized = FALSE; -static GdkEvent *next_event = NULL; +static guint gtk_main_loop_level = 0; +static gint gtk_initialized = FALSE; 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. */ @@ -140,20 +133,6 @@ static GList *init_functions = NULL; /* A list of init functions. */ static GList *quit_functions = NULL; /* A list of quit functions. */ -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. - */ - -static GList *current_idles = NULL; -static GList *current_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; @@ -168,44 +147,112 @@ 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} + {"misc", GTK_DEBUG_MISC}, + {"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 *current_locale; - - if (0) + gchar *suffix = strrchr(module_name, '.'); + + if (!suffix || stricmp(suffix, ".dll")) { - g_set_error_handler (gtk_error); - g_set_warning_handler (gtk_warning); - g_set_message_handler (gtk_message); - g_set_print_handler (gtk_print); + 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) +{ + extern void gtk_object_post_arg_parsing_init (void); + GSList *gtk_modules = NULL; + GSList *slist; + gchar *env_string = NULL; + + if (gtk_initialized) + return TRUE; + +#if 0 + g_set_error_handler (gtk_error); + g_set_warning_handler (gtk_warning); + g_set_message_handler (gtk_message); + g_set_print_handler (gtk_print); +#endif /* 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) { @@ -213,35 +260,79 @@ gtk_init (int *argc, for (i = 1; i < *argc;) { - if (strcmp ("--gtk-debug", (*argv)[i]) == 0) + if (strcmp ("--gtk-module", (*argv)[i]) == 0 || + strncmp ("--gtk-module=", (*argv)[i], 13) == 0) { + gchar *module_name = (*argv)[i] + 12; + + if (*module_name == '=') + module_name++; + else + { + (*argv)[i] = NULL; + i += 1; + module_name = (*argv)[i]; + } (*argv)[i] = NULL; - if ((i + 1) < *argc && (*argv)[i + 1]) + 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, + gtk_debug_keys, + gtk_ndebug_keys); + } + else if ((i + 1) < *argc && (*argv)[i + 1]) { gtk_debug_flags |= g_parse_debug_string ((*argv)[i+1], gtk_debug_keys, gtk_ndebug_keys); - (*argv)[i + 1] = NULL; + (*argv)[i] = NULL; i += 1; } + (*argv)[i] = NULL; } - else if (strcmp ("--gtk-no-debug", (*argv)[i]) == 0) + else if ((strcmp ("--gtk-no-debug", (*argv)[i]) == 0) || + (strncmp ("--gtk-no-debug=", (*argv)[i], 15) == 0)) { - (*argv)[i] = NULL; - - if ((i + 1) < *argc && (*argv)[i + 1]) + gchar *equal_pos = strchr ((*argv)[i], '='); + + if (equal_pos != NULL) + { + gtk_debug_flags &= ~g_parse_debug_string (equal_pos+1, + gtk_debug_keys, + gtk_ndebug_keys); + } + else if ((i + 1) < *argc && (*argv)[i + 1]) { gtk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1], gtk_debug_keys, gtk_ndebug_keys); - (*argv)[i + 1] = NULL; + (*argv)[i] = NULL; i += 1; } + (*argv)[i] = NULL; } +#endif /* G_ENABLE_DEBUG */ i += 1; } - + for (i = 1; i < *argc; i++) { for (k = i; k < *argc; k++) @@ -257,31 +348,61 @@ 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 were 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); - - GTK_NOTE(MISC, g_print("%s multi-byte string functions.\n", - gtk_use_mb ? "Using" : "Not using")); +#ifdef ENABLE_NLS + bindtextdomain("gtk+", GTK_LOCALEDIR); +#endif /* Initialize the default visual and colormap to be * used in creating widgets. (We want to use the system @@ -289,18 +410,55 @@ gtk_init (int *argc, */ gtk_visual = gdk_visual_get_system (); gtk_colormap = gdk_colormap_get_system (); + + gtk_type_init (); + gtk_object_post_arg_parsing_init (); + gtk_signal_init (); gtk_rc_init (); - gtk_type_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. */ - initialized = TRUE; + gtk_initialized = TRUE; + + /* initialize gtk modules + */ + for (slist = gtk_modules; slist; slist = slist->next) + { + if (slist->data) + { + GtkModuleInitFunc modinit; + + modinit = slist->data; + modinit (argc, argv); + } + } + g_slist_free (gtk_modules); + +#ifndef NATIVE_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 @@ -315,21 +473,24 @@ gtk_exit (int errorcode) } gchar* -gtk_set_locale () +gtk_set_locale (void) { return gdk_set_locale (); } void -gtk_main () +gtk_main (void) { GList *tmp_list; GList *functions; GtkInitFunction *init; - int old_done; - - main_level++; + 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; @@ -342,11 +503,14 @@ gtk_main () 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) { @@ -359,7 +523,7 @@ gtk_main () quit_functions = g_list_remove_link (quit_functions, quit_functions); - if ((quitf->main_level && quitf->main_level != main_level) || + if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) || gtk_quit_invoke_function (quitf)) { reinvoke_list = g_list_prepend (reinvoke_list, quitf); @@ -372,287 +536,291 @@ gtk_main () } if (reinvoke_list) { - GList *tmp_list; + GList *work; - tmp_list = g_list_last (reinvoke_list); + work = g_list_last (reinvoke_list); if (quit_functions) - quit_functions->prev = tmp_list; - tmp_list->next = quit_functions; - quit_functions = tmp_list; + quit_functions->prev = work; + work->next = quit_functions; + quit_functions = work; } + + gdk_flush (); } - main_level--; + main_loops = g_slist_remove (main_loops, loop); + + g_main_destroy (loop); + + gtk_main_loop_level--; } guint gtk_main_level (void) { - return main_level; + return gtk_main_loop_level; } void -gtk_main_quit () +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 = gdk_events_pending() + ((next_event != NULL) ? 1 : 0); + return g_main_pending(); +} - if (idle_functions && - (((GtkIdleFunction *)idle_functions->data)->priority >= - GTK_PRIORITY_INTERNAL)) - result += 1; +gint +gtk_main_iteration (void) +{ + g_main_iteration (TRUE); - return result; + if (main_loops) + return !g_main_is_running (main_loops->data); + else + return TRUE; } gint -gtk_main_iteration () +gtk_main_iteration_do (gboolean blocking) { - return gtk_main_iteration_do (TRUE); + g_main_iteration (blocking); + + if (main_loops) + return !g_main_is_running (main_loops->data); + else + return TRUE; } -gint -gtk_main_iteration_do (gboolean blocking) +void +gtk_main_do_event (GdkEvent *event) { GtkWidget *event_widget; GtkWidget *grab_widget; - GdkEvent *event = NULL; + GdkEvent *next_event; GList *tmp_list; - - 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() + + /* If there are any events pending then get the next one. */ - if (current_timeouts) - { - gtk_handle_current_timeouts( gdk_time_get()); - return iteration_done; - } - if (current_idles) - { - gtk_handle_current_idles (); - return iteration_done; - } + next_event = gdk_event_peek (); - /* If there is a valid event in 'next_event' then move it to 'event' + /* 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)) + { + /* 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; + } + + 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) { - event = next_event; - next_event = NULL; + /* 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 we don't have an event then get one. + /* 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 (!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); - } - else - { - if (gdk_events_pending() == 0) - gtk_handle_idle (); + 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; } -event_handling_done: - - /* Handle timeout functions that may have expired. - */ - gtk_handle_timeouts (); - - return iteration_done; + tmp_list = current_events; + current_events = g_list_remove_link (current_events, tmp_list); + g_list_free_1 (tmp_list); } gint @@ -775,206 +943,45 @@ gtk_invoke_key_snoopers (GtkWidget *grab_widget, } guint -gtk_timeout_add_full (guint32 interval, - GtkFunction function, - GtkCallbackMarshal marshal, - gpointer data, - GtkDestroyNotify destroy) +gtk_quit_add_full (guint main_level, + GtkFunction function, + GtkCallbackMarshal marshal, + gpointer data, + GtkDestroyNotify destroy) { - static guint timeout_tag = 1; - GtkTimeoutFunction *timeoutf; + static guint quit_id = 1; + GtkQuitFunction *quitf; 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); + if (!quit_mem_chunk) + quit_mem_chunk = g_mem_chunk_new ("quit mem chunk", sizeof (GtkQuitFunction), + 512, G_ALLOC_AND_FREE); - 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; + quitf = g_chunk_new (GtkQuitFunction, quit_mem_chunk); - gtk_timeout_insert (timeoutf); + quitf->id = quit_id++; + quitf->main_level = main_level; + quitf->function = function; + quitf->marshal = marshal; + quitf->data = data; + quitf->destroy = destroy; + + quit_functions = g_list_prepend (quit_functions, quitf); - return timeoutf->tag; + return quitf->id; } static void -gtk_timeout_destroy (GtkTimeoutFunction *timeoutf) +gtk_quit_destroy (GtkQuitFunction *quitf) { - if (timeoutf->destroy) - (timeoutf->destroy) (timeoutf->data); - g_mem_chunk_free (timeout_mem_chunk, timeoutf); + if (quitf->destroy) + quitf->destroy (quitf->data); + g_mem_chunk_free (quit_mem_chunk, quitf); } -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); -} - -void -gtk_timeout_remove (guint tag) -{ - GtkTimeoutFunction *timeoutf; - GList *tmp_list; - - /* Remove a timeout function. - * (Which, basically, involves searching the - * list for the tag). - */ - tmp_list = timeout_functions; - while (tmp_list) - { - timeoutf = tmp_list->data; - - if (timeoutf->tag == tag) - { - timeout_functions = g_list_remove_link (timeout_functions, tmp_list); - g_list_free (tmp_list); - gtk_timeout_destroy (timeoutf); - - return; - } - - tmp_list = tmp_list->next; - } - - tmp_list = current_timeouts; - while (tmp_list) - { - timeoutf = tmp_list->data; - - if (timeoutf->tag == tag) - { - current_timeouts = g_list_remove_link (current_timeouts, tmp_list); - g_list_free (tmp_list); - gtk_timeout_destroy (timeoutf); - - return; - } - - tmp_list = tmp_list->next; - } -} - -/* 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 (gpointer a, gpointer b) -{ - return (((GtkIdleFunction *)a)->priority < ((GtkIdleFunction *)b)->priority) - ? -1 : 1; -} - -guint -gtk_quit_add_full (guint main_level, - GtkFunction function, - GtkCallbackMarshal marshal, - gpointer data, - GtkDestroyNotify destroy) -{ - static guint quit_id = 1; - GtkQuitFunction *quitf; - - g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0); - - if (!quit_mem_chunk) - quit_mem_chunk = g_mem_chunk_new ("quit mem chunk", sizeof (GtkQuitFunction), - 512, G_ALLOC_AND_FREE); - - quitf = g_chunk_new (GtkQuitFunction, quit_mem_chunk); - - quitf->id = quit_id++; - quitf->main_level = main_level; - quitf->function = function; - quitf->marshal = marshal; - quitf->data = data; - quitf->destroy = destroy; - - quit_functions = g_list_prepend (quit_functions, quitf); - - 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; - - 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) -{ - if (quitf->destroy) - quitf->destroy (quitf->data); - g_mem_chunk_free (quit_mem_chunk, quitf); -} - -static gint -gtk_quit_destructor (GtkObject **object_p) +static gint +gtk_quit_destructor (GtkObject **object_p) { if (*object_p) gtk_object_destroy (*object_p); @@ -1010,21 +1017,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) { @@ -1073,299 +1065,207 @@ gtk_quit_remove_by_data (gpointer data) } } -void -gtk_idle_remove (guint tag) +guint +gtk_timeout_add_full (guint32 interval, + GtkFunction function, + GtkCallbackMarshal marshal, + gpointer data, + GtkDestroyNotify destroy) { - GtkIdleFunction *idlef; - GList *tmp_list; - - tmp_list = idle_functions; - while (tmp_list) - { - idlef = tmp_list->data; - - if (idlef->tag == tag) - { - idle_functions = g_list_remove_link (idle_functions, tmp_list); - g_list_free (tmp_list); - gtk_idle_destroy (idlef); - - return; - } - - tmp_list = tmp_list->next; - } - - tmp_list = current_idles; - while (tmp_list) + if (marshal) { - idlef = tmp_list->data; - - if (idlef->tag == tag) - { - current_idles = g_list_remove_link (current_idles, tmp_list); - g_list_free (tmp_list); - gtk_idle_destroy (idlef); - - return; - } - - tmp_list = tmp_list->next; + GtkClosure *closure; + + 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); } + else + return g_timeout_add_full (0, interval, function, data, destroy); +} + +guint +gtk_timeout_add (guint32 interval, + GtkFunction function, + gpointer data) +{ + return g_timeout_add_full (0, interval, function, data, NULL); } void -gtk_idle_remove_by_data (gpointer data) +gtk_timeout_remove (guint tag) { - GtkIdleFunction *idlef; - GList *tmp_list; - - tmp_list = idle_functions; - while (tmp_list) - { - idlef = tmp_list->data; - - if (idlef->data == data) - { - idle_functions = g_list_remove_link (idle_functions, tmp_list); - g_list_free (tmp_list); - gtk_idle_destroy (idlef); - - return; - } - - tmp_list = tmp_list->next; - } - - tmp_list = current_idles; - while (tmp_list) + g_source_remove (tag); +} + +guint +gtk_idle_add_full (gint priority, + GtkFunction function, + GtkCallbackMarshal marshal, + gpointer data, + GtkDestroyNotify destroy) +{ + if (marshal) { - idlef = tmp_list->data; - - if (idlef->data == data) - { - current_idles = g_list_remove_link (current_idles, tmp_list); - g_list_free (tmp_list); - gtk_idle_destroy (idlef); - - return; - } - - tmp_list = tmp_list->next; + GtkClosure *closure; + + 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_invoke_input_function (GtkInputFunction *input, - gint source, - GdkInputCondition condition) +guint +gtk_idle_add (GtkFunction function, + gpointer 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; + return g_idle_add_full (GTK_PRIORITY_DEFAULT, function, data, NULL); +} - input->callback (NULL, input->data, 2, args); +guint +gtk_idle_add_priority (gint priority, + GtkFunction function, + gpointer data) +{ + return g_idle_add_full (priority, function, data, NULL); } -static void -gtk_destroy_input_function (GtkInputFunction *input) +void +gtk_idle_remove (guint tag) { - if (input->destroy) - (input->destroy) (input->data); - g_free (input); + 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); } -guint -gtk_input_add_interp (gint source, - GdkInputCondition condition, - GtkCallbackMarshal callback, - gpointer data, - GtkDestroyNotify destroy) -{ - return gtk_input_add_full (source, condition, NULL, callback, data, destroy); -} - void gtk_input_remove (guint tag) { - gdk_input_remove (tag); + g_source_remove (tag); } -GdkEvent * -gtk_get_current_event () +static void +gtk_destroy_closure (gpointer data) { - if (current_events) - return gdk_event_copy ((GdkEvent *) current_events->data); - else - return NULL; + GtkClosure *closure = data; + + if (closure->destroy) + (closure->destroy) (closure->data); + g_free (closure); } -GtkWidget* -gtk_get_event_widget (GdkEvent *event) +static gboolean +gtk_invoke_idle_timeout (gpointer data) { - GtkWidget *widget; + GtkClosure *closure = data; - widget = NULL; - if (event->any.window) - gdk_window_get_user_data (event->any.window, (void**) &widget); - - return widget; + 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; } static void -gtk_exit_func () +gtk_invoke_input (gpointer data, + gint source, + GdkInputCondition condition) { - if (initialized) - { - initialized = FALSE; - gtk_preview_uninit (); - } -} + 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; -/* 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 (gpointer a, gpointer b) -{ - return (((GtkTimeoutFunction *)a)->interval < - ((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); + closure->marshal (NULL, closure->data, 2, args); } -static gint -gtk_invoke_timeout_function (GtkTimeoutFunction *timeoutf) +GdkEvent* +gtk_get_current_event (void) { - if (!timeoutf->marshal) - return timeoutf->function (timeoutf->data); + if (current_events) + return gdk_event_copy ((GdkEvent *) current_events->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; - } + return NULL; } -static void -gtk_handle_current_timeouts (guint32 the_time) +GtkWidget* +gtk_get_event_widget (GdkEvent *event) { - GList *tmp_list; - GtkTimeoutFunction *timeoutf; + GtkWidget *widget; + + widget = NULL; + if (event && event->any.window) + gdk_window_get_user_data (event->any.window, (void**) &widget); - while (current_timeouts) - { - tmp_list = current_timeouts; - timeoutf = tmp_list->data; - - current_timeouts = g_list_remove_link (current_timeouts, tmp_list); - g_list_free (tmp_list); - - if (gtk_invoke_timeout_function (timeoutf) == FALSE) - { - gtk_timeout_destroy (timeoutf); - } - else - { - timeoutf->interval = timeoutf->originterval; - timeoutf->start = the_time; - gtk_timeout_insert (timeoutf); - } - } + return widget; } static void -gtk_handle_timeouts () +gtk_exit_func (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) + if (gtk_initialized) { - 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); + gtk_initialized = FALSE; + gtk_preview_uninit (); } } + static gint gtk_quit_invoke_function (GtkQuitFunction *quitf) { @@ -1386,175 +1286,55 @@ 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 () -{ - GList *tmp_list; - GList *tmp_list2; - GtkIdleFunction *idlef; - - while (current_idles) - { - tmp_list = current_idles; - idlef = tmp_list->data; - - current_idles = g_list_remove_link (current_idles, tmp_list); - - if (gtk_idle_invoke_function (idlef) == FALSE) - { - g_list_free (tmp_list); - 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 () -{ - /* 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 () -{ - 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; + if ((event->type == GDK_KEY_PRESS) || (event->type == GDK_KEY_RELEASE)) { - /* Only send key events to window widgets. - * The window widget will in turn pass the + /* Only send key events within Window widgets to the Window + * The Window widget will in turn pass the * key event on to the currently focused widget * for that window. */ + GtkWidget *window; - widget = gtk_widget_get_ancestor (widget, gtk_window_get_type ()); - if (widget && GTK_WIDGET_IS_SENSITIVE (widget)) - gtk_widget_event (widget, event); + window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); + if (window) + { + if (GTK_WIDGET_IS_SENSITIVE (window)) + gtk_widget_event (window, event); + + handled_event = TRUE; /* don't send to widget */ + } } - else + + /* Other events get propagated up the widget tree + * so that parents can see the button and motion + * events of the children. + */ + while (!handled_event && widget) { - gint handled_event; - - /* Other events get propagated up the widget tree - * so that parents can see the button and motion - * events of the children. - */ - - handled_event = FALSE; - while (!handled_event && widget) - { - GtkWidget *tmp; + GtkWidget *tmp; - gtk_widget_ref (widget); - handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event); - tmp = widget->parent; - gtk_widget_unref (widget); - widget = tmp; - } + gtk_widget_ref (widget); + handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event); + tmp = widget->parent; + gtk_widget_unref (widget); + widget = tmp; } } +#if 0 static void gtk_error (gchar *str) { @@ -1610,7 +1390,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); @@ -1643,7 +1423,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); @@ -1665,3 +1445,4 @@ gtk_print (gchar *str) if (!GTK_WIDGET_VISIBLE (window)) gtk_widget_show (window); } +#endif