]> Pileus Git - ~andy/gtk/blob - gtk/gtkmain.c
Deprecate widget flag: GTK_WIDGET_VISIBLE
[~andy/gtk] / gtk / gtkmain.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #include <glib.h>
30 #include "gdkconfig.h"
31
32 #include <locale.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #include <sys/types.h>          /* For uid_t, gid_t */
41
42 #ifdef G_OS_WIN32
43 #define STRICT
44 #include <windows.h>
45 #undef STRICT
46 #endif
47
48 #include "gtkintl.h"
49
50 #include "gtkaccelmap.h"
51 #include "gtkbox.h"
52 #include "gtkclipboard.h"
53 #include "gtkdnd.h"
54 #include "gtkversion.h"
55 #include "gtkmain.h"
56 #include "gtkmodules.h"
57 #include "gtkrc.h"
58 #include "gtkrecentmanager.h"
59 #include "gtkselection.h"
60 #include "gtksettings.h"
61 #include "gtkwidget.h"
62 #include "gtkwindow.h"
63 #include "gtktooltip.h"
64 #include "gtkdebug.h"
65 #include "gtkalias.h"
66 #include "gtkmenu.h"
67 #include "gdk/gdkkeysyms.h"
68
69 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
70
71 #ifdef G_OS_WIN32
72
73 static HMODULE gtk_dll;
74
75 BOOL WINAPI
76 DllMain (HINSTANCE hinstDLL,
77          DWORD     fdwReason,
78          LPVOID    lpvReserved)
79 {
80   switch (fdwReason)
81     {
82     case DLL_PROCESS_ATTACH:
83       gtk_dll = (HMODULE) hinstDLL;
84       break;
85     }
86
87   return TRUE;
88 }
89
90 /* These here before inclusion of gtkprivate.h so that the original
91  * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
92  * bit sucky.
93  */
94 const gchar *
95 _gtk_get_libdir (void)
96 {
97   static char *gtk_libdir = NULL;
98   if (gtk_libdir == NULL)
99     {
100       gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
101       gchar *slash = strrchr (root, '\\');
102       if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
103         gtk_libdir = GTK_LIBDIR;
104       else
105         gtk_libdir = g_build_filename (root, "lib", NULL);
106       g_free (root);
107     }
108
109   return gtk_libdir;
110 }
111
112 const gchar *
113 _gtk_get_localedir (void)
114 {
115   static char *gtk_localedir = NULL;
116   if (gtk_localedir == NULL)
117     {
118       const gchar *p;
119       gchar *root, *temp;
120       
121       /* GTK_LOCALEDIR ends in either /lib/locale or
122        * /share/locale. Scan for that slash.
123        */
124       p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
125       while (*--p != '/')
126         ;
127       while (*--p != '/')
128         ;
129
130       root = g_win32_get_package_installation_directory_of_module (gtk_dll);
131       temp = g_build_filename (root, p, NULL);
132       g_free (root);
133
134       /* gtk_localedir is passed to bindtextdomain() which isn't
135        * UTF-8-aware.
136        */
137       gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
138       g_free (temp);
139     }
140   return gtk_localedir;
141 }
142
143 #endif
144
145 #include "gtkprivate.h"
146
147 /* Private type definitions
148  */
149 typedef struct _GtkInitFunction          GtkInitFunction;
150 typedef struct _GtkQuitFunction          GtkQuitFunction;
151 typedef struct _GtkClosure               GtkClosure;
152 typedef struct _GtkKeySnooperData        GtkKeySnooperData;
153
154 struct _GtkInitFunction
155 {
156   GtkFunction function;
157   gpointer data;
158 };
159
160 struct _GtkQuitFunction
161 {
162   guint id;
163   guint main_level;
164   GtkCallbackMarshal marshal;
165   GtkFunction function;
166   gpointer data;
167   GDestroyNotify destroy;
168 };
169
170 struct _GtkClosure
171 {
172   GtkCallbackMarshal marshal;
173   gpointer data;
174   GDestroyNotify destroy;
175 };
176
177 struct _GtkKeySnooperData
178 {
179   GtkKeySnoopFunc func;
180   gpointer func_data;
181   guint id;
182 };
183
184 static gint  gtk_quit_invoke_function    (GtkQuitFunction    *quitf);
185 static void  gtk_quit_destroy            (GtkQuitFunction    *quitf);
186 static gint  gtk_invoke_key_snoopers     (GtkWidget          *grab_widget,
187                                           GdkEvent           *event);
188
189 static void     gtk_destroy_closure      (gpointer            data);
190 static gboolean gtk_invoke_idle_timeout  (gpointer            data);
191 static void     gtk_invoke_input         (gpointer            data,
192                                           gint                source,
193                                           GdkInputCondition   condition);
194
195 #if 0
196 static void  gtk_error                   (gchar              *str);
197 static void  gtk_warning                 (gchar              *str);
198 static void  gtk_message                 (gchar              *str);
199 static void  gtk_print                   (gchar              *str);
200 #endif
201
202 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget   *widget);
203
204 const guint gtk_major_version = GTK_MAJOR_VERSION;
205 const guint gtk_minor_version = GTK_MINOR_VERSION;
206 const guint gtk_micro_version = GTK_MICRO_VERSION;
207 const guint gtk_binary_age = GTK_BINARY_AGE;
208 const guint gtk_interface_age = GTK_INTERFACE_AGE;
209
210 static guint gtk_main_loop_level = 0;
211 static gint pre_initialized = FALSE;
212 static gint gtk_initialized = FALSE;
213 static GList *current_events = NULL;
214
215 static GSList *main_loops = NULL;      /* stack of currently executing main loops */
216
217 static GList *init_functions = NULL;       /* A list of init functions.
218                                             */
219 static GList *quit_functions = NULL;       /* A list of quit functions.
220                                             */
221 static GSList *key_snoopers = NULL;
222
223 guint gtk_debug_flags = 0;                 /* Global GTK debug flag */
224
225 #ifdef G_ENABLE_DEBUG
226 static const GDebugKey gtk_debug_keys[] = {
227   {"misc", GTK_DEBUG_MISC},
228   {"plugsocket", GTK_DEBUG_PLUGSOCKET},
229   {"text", GTK_DEBUG_TEXT},
230   {"tree", GTK_DEBUG_TREE},
231   {"updates", GTK_DEBUG_UPDATES},
232   {"keybindings", GTK_DEBUG_KEYBINDINGS},
233   {"multihead", GTK_DEBUG_MULTIHEAD},
234   {"modules", GTK_DEBUG_MODULES},
235   {"geometry", GTK_DEBUG_GEOMETRY},
236   {"icontheme", GTK_DEBUG_ICONTHEME},
237   {"printing", GTK_DEBUG_PRINTING},
238   {"builder", GTK_DEBUG_BUILDER}
239 };
240 #endif /* G_ENABLE_DEBUG */
241
242 /**
243  * gtk_check_version:
244  * @required_major: the required major version.
245  * @required_minor: the required minor version.
246  * @required_micro: the required micro version.
247  * 
248  * Checks that the GTK+ library in use is compatible with the
249  * given version. Generally you would pass in the constants
250  * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
251  * as the three arguments to this function; that produces
252  * a check that the library in use is compatible with
253  * the version of GTK+ the application or module was compiled
254  * against.
255  *
256  * Compatibility is defined by two things: first the version
257  * of the running library is newer than the version
258  * @required_major.required_minor.@required_micro. Second
259  * the running library must be binary compatible with the
260  * version @required_major.required_minor.@required_micro
261  * (same major version.)
262  *
263  * This function is primarily for GTK+ modules; the module
264  * can call this function to check that it wasn't loaded
265  * into an incompatible version of GTK+. However, such a
266  * a check isn't completely reliable, since the module may be
267  * linked against an old version of GTK+ and calling the
268  * old version of gtk_check_version(), but still get loaded
269  * into an application using a newer version of GTK+.
270  *
271  * Return value: %NULL if the GTK+ library is compatible with the
272  *   given version, or a string describing the version mismatch.
273  *   The returned string is owned by GTK+ and should not be modified
274  *   or freed.
275  **/
276 const gchar*
277 gtk_check_version (guint required_major,
278                    guint required_minor,
279                    guint required_micro)
280 {
281   gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
282   gint required_effective_micro = 100 * required_minor + required_micro;
283
284   if (required_major > GTK_MAJOR_VERSION)
285     return "Gtk+ version too old (major mismatch)";
286   if (required_major < GTK_MAJOR_VERSION)
287     return "Gtk+ version too new (major mismatch)";
288   if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
289     return "Gtk+ version too new (micro mismatch)";
290   if (required_effective_micro > gtk_effective_micro)
291     return "Gtk+ version too old (micro mismatch)";
292   return NULL;
293 }
294
295 /* This checks to see if the process is running suid or sgid
296  * at the current time. If so, we don't allow GTK+ to be initialized.
297  * This is meant to be a mild check - we only error out if we
298  * can prove the programmer is doing something wrong, not if
299  * they could be doing something wrong. For this reason, we
300  * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
301  */
302 static gboolean
303 check_setugid (void)
304 {
305 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
306 #ifndef G_OS_WIN32
307   uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
308   gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
309   
310 #ifdef HAVE_GETRESUID
311   /* These aren't in the header files, so we prototype them here.
312    */
313   int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
314   int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
315
316   if (getresuid (&ruid, &euid, &suid) != 0 ||
317       getresgid (&rgid, &egid, &sgid) != 0)
318 #endif /* HAVE_GETRESUID */
319     {
320       suid = ruid = getuid ();
321       sgid = rgid = getgid ();
322       euid = geteuid ();
323       egid = getegid ();
324     }
325
326   if (ruid != euid || ruid != suid ||
327       rgid != egid || rgid != sgid)
328     {
329       g_warning ("This process is currently running setuid or setgid.\n"
330                  "This is not a supported use of GTK+. You must create a helper\n"
331                  "program instead. For further details, see:\n\n"
332                  "    http://www.gtk.org/setuid.html\n\n"
333                  "Refusing to initialize GTK+.");
334       exit (1);
335     }
336 #endif
337   return TRUE;
338 }
339
340 #ifdef G_OS_WIN32
341
342 const gchar *
343 _gtk_get_datadir (void)
344 {
345   static char *gtk_datadir = NULL;
346   if (gtk_datadir == NULL)
347     {
348       gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
349       gtk_datadir = g_build_filename (root, "share", NULL);
350       g_free (root);
351     }
352
353   return gtk_datadir;
354 }
355
356 const gchar *
357 _gtk_get_sysconfdir (void)
358 {
359   static char *gtk_sysconfdir = NULL;
360   if (gtk_sysconfdir == NULL)
361     {
362       gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
363       gtk_sysconfdir = g_build_filename (root, "etc", NULL);
364       g_free (root);
365     }
366
367   return gtk_sysconfdir;
368 }
369
370 const gchar *
371 _gtk_get_data_prefix (void)
372 {
373   static char *gtk_data_prefix = NULL;
374   if (gtk_data_prefix == NULL)
375     gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
376
377   return gtk_data_prefix;
378 }
379
380 #endif /* G_OS_WIN32 */
381
382 static gboolean do_setlocale = TRUE;
383
384 /**
385  * gtk_disable_setlocale:
386  * 
387  * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
388  * gtk_parse_args() from automatically
389  * calling <literal>setlocale (LC_ALL, "")</literal>. You would 
390  * want to use this function if you wanted to set the locale for 
391  * your program to something other than the user's locale, or if 
392  * you wanted to set different values for different locale categories.
393  *
394  * Most programs should not need to call this function.
395  **/
396 void
397 gtk_disable_setlocale (void)
398 {
399   if (pre_initialized)
400     g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
401     
402   do_setlocale = FALSE;
403 }
404
405 #ifdef G_PLATFORM_WIN32
406 #undef gtk_init_check
407 #endif
408
409 static GString *gtk_modules_string = NULL;
410 static gboolean g_fatal_warnings = FALSE;
411
412 #ifdef G_ENABLE_DEBUG
413 static gboolean
414 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
415 {
416   gtk_debug_flags |= g_parse_debug_string (value,
417                                            gtk_debug_keys,
418                                            G_N_ELEMENTS (gtk_debug_keys));
419
420   return TRUE;
421 }
422
423 static gboolean
424 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
425 {
426   gtk_debug_flags &= ~g_parse_debug_string (value,
427                                             gtk_debug_keys,
428                                             G_N_ELEMENTS (gtk_debug_keys));
429
430   return TRUE;
431 }
432 #endif /* G_ENABLE_DEBUG */
433
434 static gboolean
435 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
436 {
437   if (value && *value)
438     {
439       if (gtk_modules_string)
440         g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
441       else
442         gtk_modules_string = g_string_new (NULL);
443       
444       g_string_append (gtk_modules_string, value);
445     }
446
447   return TRUE;
448 }
449
450 static const GOptionEntry gtk_args[] = {
451   { "gtk-module",       0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,   
452     /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"), 
453     /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
454   { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, 
455     /* Description of --g-fatal-warnings in --help output */   N_("Make all warnings fatal"), NULL },
456 #ifdef G_ENABLE_DEBUG
457   { "gtk-debug",        0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,    
458     /* Description of --gtk-debug=FLAGS in --help output */    N_("GTK+ debugging flags to set"), 
459     /* Placeholder in --gtk-debug=FLAGS in --help output */    N_("FLAGS") },
460   { "gtk-no-debug",     0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb, 
461     /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"), 
462     /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
463 #endif 
464   { NULL }
465 };
466
467 #ifdef G_OS_WIN32
468
469 static char *iso639_to_check = NULL;
470 static char *iso3166_to_check = NULL;
471 static char *script_to_check = NULL;
472 static gboolean setlocale_called = FALSE;
473
474 static BOOL CALLBACK
475 enum_locale_proc (LPTSTR locale)
476 {
477   LCID lcid;
478   char iso639[10];
479   char iso3166[10];
480   char *endptr;
481
482
483   lcid = strtoul (locale, &endptr, 16);
484   if (*endptr == '\0' &&
485       GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
486       GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
487     {
488       if (strcmp (iso639, iso639_to_check) == 0 &&
489           ((iso3166_to_check != NULL &&
490             strcmp (iso3166, iso3166_to_check) == 0) ||
491            (iso3166_to_check == NULL &&
492             SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
493         {
494           char language[100], country[100];
495           char locale[300];
496
497           if (script_to_check != NULL)
498             {
499               /* If lcid is the "other" script for this language,
500                * return TRUE, i.e. continue looking.
501                */
502               if (strcmp (script_to_check, "Latn") == 0)
503                 {
504                   switch (LANGIDFROMLCID (lcid))
505                     {
506                     case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
507                       return TRUE;
508                     case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
509                       return TRUE;
510                     case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
511                       return TRUE;
512                     case MAKELANGID (LANG_SERBIAN, 0x07):
513                       /* Serbian in Bosnia and Herzegovina, Cyrillic */
514                       return TRUE;
515                     }
516                 }
517               else if (strcmp (script_to_check, "Cyrl") == 0)
518                 {
519                   switch (LANGIDFROMLCID (lcid))
520                     {
521                     case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
522                       return TRUE;
523                     case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
524                       return TRUE;
525                     case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
526                       return TRUE;
527                     case MAKELANGID (LANG_SERBIAN, 0x06):
528                       /* Serbian in Bosnia and Herzegovina, Latin */
529                       return TRUE;
530                     }
531                 }
532             }
533
534           SetThreadLocale (lcid);
535
536           if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
537               GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
538             {
539               strcpy (locale, language);
540               strcat (locale, "_");
541               strcat (locale, country);
542
543               if (setlocale (LC_ALL, locale) != NULL)
544                 setlocale_called = TRUE;
545             }
546
547           return FALSE;
548         }
549     }
550
551   return TRUE;
552 }
553   
554 #endif
555
556 static void
557 setlocale_initialization (void)
558 {
559   static gboolean initialized = FALSE;
560
561   if (initialized)
562     return;
563   initialized = TRUE;
564
565   if (do_setlocale)
566     {
567 #ifdef G_OS_WIN32
568       /* If some of the POSIXish environment variables are set, set
569        * the Win32 thread locale correspondingly.
570        */ 
571       char *p = getenv ("LC_ALL");
572       if (p == NULL)
573         p = getenv ("LANG");
574
575       if (p != NULL)
576         {
577           p = g_strdup (p);
578           if (strcmp (p, "C") == 0)
579             SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
580           else
581             {
582               /* Check if one of the supported locales match the
583                * environment variable. If so, use that locale.
584                */
585               iso639_to_check = p;
586               iso3166_to_check = strchr (iso639_to_check, '_');
587               if (iso3166_to_check != NULL)
588                 {
589                   *iso3166_to_check++ = '\0';
590
591                   script_to_check = strchr (iso3166_to_check, '@');
592                   if (script_to_check != NULL)
593                     *script_to_check++ = '\0';
594
595                   /* Handle special cases. */
596                   
597                   /* The standard code for Serbia and Montenegro was
598                    * "CS", but MSFT uses for some reason "SP". By now
599                    * (October 2006), SP has split into two, "RS" and
600                    * "ME", but don't bother trying to handle those
601                    * yet. Do handle the even older "YU", though.
602                    */
603                   if (strcmp (iso3166_to_check, "CS") == 0 ||
604                       strcmp (iso3166_to_check, "YU") == 0)
605                     iso3166_to_check = "SP";
606                 }
607               else
608                 {
609                   script_to_check = strchr (iso639_to_check, '@');
610                   if (script_to_check != NULL)
611                     *script_to_check++ = '\0';
612                   /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
613                   if (strcmp (iso639_to_check, "sr") == 0)
614                     iso3166_to_check = "SP";
615                 }
616
617               EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
618             }
619           g_free (p);
620         }
621       if (!setlocale_called)
622         setlocale (LC_ALL, "");
623 #else
624       if (!setlocale (LC_ALL, ""))
625         g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
626 #endif
627     }
628 }
629
630 static void
631 do_pre_parse_initialization (int    *argc,
632                              char ***argv)
633 {
634   const gchar *env_string;
635   
636 #if     0
637   g_set_error_handler (gtk_error);
638   g_set_warning_handler (gtk_warning);
639   g_set_message_handler (gtk_message);
640   g_set_print_handler (gtk_print);
641 #endif
642
643   if (pre_initialized)
644     return;
645
646   pre_initialized = TRUE;
647
648   gdk_pre_parse_libgtk_only ();
649   gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
650   
651 #ifdef G_ENABLE_DEBUG
652   env_string = g_getenv ("GTK_DEBUG");
653   if (env_string != NULL)
654     {
655       gtk_debug_flags = g_parse_debug_string (env_string,
656                                               gtk_debug_keys,
657                                               G_N_ELEMENTS (gtk_debug_keys));
658       env_string = NULL;
659     }
660 #endif  /* G_ENABLE_DEBUG */
661
662   env_string = g_getenv ("GTK_MODULES");
663   if (env_string)
664     gtk_modules_string = g_string_new (env_string);
665 }
666
667 static void
668 gettext_initialization (void)
669 {
670   setlocale_initialization ();
671
672 #ifdef ENABLE_NLS
673   bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
674   bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
675 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
676   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
677   bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
678 #    endif
679 #endif  
680 }
681
682 static void
683 do_post_parse_initialization (int    *argc,
684                               char ***argv)
685 {
686   if (gtk_initialized)
687     return;
688
689   gettext_initialization ();
690
691 #ifdef SIGPIPE
692   signal (SIGPIPE, SIG_IGN);
693 #endif
694
695   if (g_fatal_warnings)
696     {
697       GLogLevelFlags fatal_mask;
698
699       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
700       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
701       g_log_set_always_fatal (fatal_mask);
702     }
703
704   if (gtk_debug_flags & GTK_DEBUG_UPDATES)
705     gdk_window_set_debug_updates (TRUE);
706
707   {
708   /* Translate to default:RTL if you want your widgets
709    * to be RTL, otherwise translate to default:LTR.
710    * Do *not* translate it to "predefinito:LTR", if it
711    * it isn't default:LTR or default:RTL it will not work 
712    */
713     char *e = _("default:LTR");
714     if (strcmp (e, "default:RTL")==0) 
715       gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
716     else if (strcmp (e, "default:LTR"))
717       g_warning ("Whoever translated default:LTR did so wrongly.\n");
718   }
719
720   /* do what the call to gtk_type_init() used to do */
721   g_type_init ();
722
723   _gtk_accel_map_init ();
724   _gtk_rc_init ();
725
726   /* Set the 'initialized' flag.
727    */
728   gtk_initialized = TRUE;
729
730   /* load gtk modules */
731   if (gtk_modules_string)
732     {
733       _gtk_modules_init (argc, argv, gtk_modules_string->str);
734       g_string_free (gtk_modules_string, TRUE);
735     }
736   else
737     {
738       _gtk_modules_init (argc, argv, NULL);
739     }
740 }
741
742
743 typedef struct
744 {
745   gboolean open_default_display;
746 } OptionGroupInfo;
747
748 static gboolean
749 pre_parse_hook (GOptionContext *context,
750                 GOptionGroup   *group,
751                 gpointer        data,
752                 GError        **error)
753 {
754   do_pre_parse_initialization (NULL, NULL);
755   
756   return TRUE;
757 }
758
759 static gboolean
760 post_parse_hook (GOptionContext *context,
761                  GOptionGroup   *group,
762                  gpointer       data,
763                  GError        **error)
764 {
765   OptionGroupInfo *info = data;
766
767   
768   do_post_parse_initialization (NULL, NULL);
769   
770   if (info->open_default_display)
771     {
772       if (gdk_display_open_default_libgtk_only () == NULL)
773         {
774           const char *display_name = gdk_get_display_arg_name ();
775           g_set_error (error, 
776                        G_OPTION_ERROR, 
777                        G_OPTION_ERROR_FAILED,
778                        _("Cannot open display: %s"),
779                        display_name ? display_name : "" );
780           
781           return FALSE;
782         }
783     }
784
785   return TRUE;
786 }
787
788
789 /**
790  * gtk_get_option_group:
791  * @open_default_display: whether to open the default display 
792  *    when parsing the commandline arguments
793  * 
794  * Returns a #GOptionGroup for the commandline arguments recognized
795  * by GTK+ and GDK. You should add this group to your #GOptionContext 
796  * with g_option_context_add_group(), if you are using 
797  * g_option_context_parse() to parse your commandline arguments.
798  *
799  * Returns: a #GOptionGroup for the commandline arguments recognized
800  *   by GTK+
801  *
802  * Since: 2.6
803  */
804 GOptionGroup *
805 gtk_get_option_group (gboolean open_default_display)
806 {
807   GOptionGroup *group;
808   OptionGroupInfo *info;
809
810   gettext_initialization ();
811
812   info = g_new0 (OptionGroupInfo, 1);
813   info->open_default_display = open_default_display;
814   
815   group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
816   g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
817
818   gdk_add_option_entries_libgtk_only (group);
819   g_option_group_add_entries (group, gtk_args);
820   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
821   
822   return group;
823 }
824
825 /**
826  * gtk_init_with_args:
827  * @argc: a pointer to the number of command line arguments.
828  * @argv: a pointer to the array of command line arguments.
829  * @parameter_string: a string which is displayed in
830  *    the first line of <option>--help</option> output, after 
831  *    <literal><replaceable>programname</replaceable> [OPTION...]</literal>
832  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
833  *    describing the options of your program
834  * @translation_domain: a translation domain to use for translating
835  *    the <option>--help</option> output for the options in @entries
836  *    with gettext(), or %NULL
837  * @error: a return location for errors 
838  *
839  * This function does the same work as gtk_init_check(). 
840  * Additionally, it allows you to add your own commandline options, 
841  * and it automatically generates nicely formatted 
842  * <option>--help</option> output. Note that your program will
843  * be terminated after writing out the help output.
844  *
845  * Returns: %TRUE if the GUI has been successfully initialized, 
846  *               %FALSE otherwise.
847  * 
848  * Since: 2.6
849  */
850 gboolean
851 gtk_init_with_args (int            *argc,
852                     char         ***argv,
853                     const char     *parameter_string,
854                     GOptionEntry   *entries,
855                     const char     *translation_domain,
856                     GError        **error)
857 {
858   GOptionContext *context;
859   GOptionGroup *gtk_group;
860   gboolean retval;
861
862   if (gtk_initialized)
863     return gdk_display_open_default_libgtk_only () != NULL;
864
865   gettext_initialization ();
866
867   if (!check_setugid ())
868     return FALSE;
869
870   gtk_group = gtk_get_option_group (TRUE);
871   
872   context = g_option_context_new (parameter_string);
873   g_option_context_add_group (context, gtk_group);
874   
875   if (entries)
876     g_option_context_add_main_entries (context, entries, translation_domain);
877   retval = g_option_context_parse (context, argc, argv, error);
878   
879   g_option_context_free (context);
880
881   return retval;
882 }
883
884
885 /**
886  * gtk_parse_args:
887  * @argc: (inout): a pointer to the number of command line arguments.
888  * @argv: (array) (inout): a pointer to the array of command line arguments.
889  *
890  * Parses command line arguments, and initializes global
891  * attributes of GTK+, but does not actually open a connection
892  * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
893  *
894  * Any arguments used by GTK+ or GDK are removed from the array and
895  * @argc and @argv are updated accordingly.
896  *
897  * You shouldn't call this function explicitely if you are using
898  * gtk_init(), or gtk_init_check().
899  *
900  * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
901  **/
902 gboolean
903 gtk_parse_args (int    *argc,
904                 char ***argv)
905 {
906   GOptionContext *option_context;
907   GOptionGroup *gtk_group;
908   GError *error = NULL;
909   
910   if (gtk_initialized)
911     return TRUE;
912
913   gettext_initialization ();
914
915   if (!check_setugid ())
916     return FALSE;
917
918   option_context = g_option_context_new (NULL);
919   g_option_context_set_ignore_unknown_options (option_context, TRUE);
920   g_option_context_set_help_enabled (option_context, FALSE);
921   gtk_group = gtk_get_option_group (FALSE);
922   g_option_context_set_main_group (option_context, gtk_group);
923   if (!g_option_context_parse (option_context, argc, argv, &error))
924     {
925       g_warning ("%s", error->message);
926       g_error_free (error);
927     }
928
929   g_option_context_free (option_context);
930
931   return TRUE;
932 }
933
934 #ifdef G_PLATFORM_WIN32
935 #undef gtk_init_check
936 #endif
937
938 /**
939  * gtk_init_check:
940  * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
941  *   main() function. Changed if any arguments were handled.
942  * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
943  *   Any parameters understood by gtk_init() are stripped before return.
944  *
945  * This function does the same work as gtk_init() with only
946  * a single change: It does not terminate the program if the GUI can't be
947  * initialized. Instead it returns %FALSE on failure.
948  *
949  * This way the application can fall back to some other means of communication 
950  * with the user - for example a curses or command line interface.
951  * 
952  * Return value: %TRUE if the GUI has been successfully initialized, 
953  *               %FALSE otherwise.
954  **/
955 gboolean
956 gtk_init_check (int      *argc,
957                 char   ***argv)
958 {
959   if (!gtk_parse_args (argc, argv))
960     return FALSE;
961
962   return gdk_display_open_default_libgtk_only () != NULL;
963 }
964
965 #ifdef G_PLATFORM_WIN32
966 #undef gtk_init
967 #endif
968
969 /**
970  * gtk_init:
971  * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
972  *   main() function. Changed if any arguments were handled.
973  * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
974  *   Any parameters understood by gtk_init() are stripped before return.
975  *
976  * Call this function before using any other GTK+ functions in your GUI
977  * applications.  It will initialize everything needed to operate the
978  * toolkit and parses some standard command line options. @argc and 
979  * @argv are adjusted accordingly so your own code will 
980  * never see those standard arguments. 
981  *
982  * Note that there are some alternative ways to initialize GTK+: 
983  * if you are calling gtk_parse_args(), gtk_init_check(), 
984  * gtk_init_with_args() or g_option_context_parse() with 
985  * the option group returned by gtk_get_option_group(), you 
986  * <emphasis>don't</emphasis> have to call gtk_init().
987  *
988  * <note><para>
989  * This function will terminate your program if it was unable to initialize 
990  * the GUI for some reason. If you want your program to fall back to a 
991  * textual interface you want to call gtk_init_check() instead.
992  * </para></note>
993  *
994  * <note><para>
995  * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
996  * during initialization, to ignore SIGPIPE signals, since these are
997  * almost never wanted in graphical applications. If you do need to
998  * handle SIGPIPE for some reason, reset the handler after gtk_init(),
999  * but notice that other libraries (e.g. libdbus or gvfs) might do
1000  * similar things.
1001  * </para></note>
1002  **/
1003 void
1004 gtk_init (int *argc, char ***argv)
1005 {
1006   if (!gtk_init_check (argc, argv))
1007     {
1008       const char *display_name_arg = gdk_get_display_arg_name ();
1009       if (display_name_arg == NULL)
1010         display_name_arg = getenv("DISPLAY");
1011       g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1012       exit (1);
1013     }
1014 }
1015
1016 #ifdef G_PLATFORM_WIN32
1017
1018 static void
1019 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1020 {
1021   if (sizeof_GtkWindow != sizeof (GtkWindow))
1022     g_error ("Incompatible build!\n"
1023              "The code using GTK+ thinks GtkWindow is of different\n"
1024              "size than it actually is in this build of GTK+.\n"
1025              "On Windows, this probably means that you have compiled\n"
1026              "your code with gcc without the -mms-bitfields switch,\n"
1027              "or that you are using an unsupported compiler.");
1028 }
1029
1030 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1031  * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1032  * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1033  * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1034  * -fnative-struct still matters. GtkBox is one such.
1035  */
1036 static void
1037 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1038 {
1039   if (sizeof_GtkBox != sizeof (GtkBox))
1040     g_error ("Incompatible build!\n"
1041              "The code using GTK+ thinks GtkBox is of different\n"
1042              "size than it actually is in this build of GTK+.\n"
1043              "On Windows, this probably means that you have compiled\n"
1044              "your code with gcc without the -mms-bitfields switch,\n"
1045              "or that you are using an unsupported compiler.");
1046 }
1047
1048 /* These two functions might get more checks added later, thus pass
1049  * in the number of extra args.
1050  */
1051 void
1052 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1053 {
1054   check_sizeof_GtkWindow (sizeof_GtkWindow);
1055   if (num_checks >= 2)
1056     check_sizeof_GtkBox (sizeof_GtkBox);
1057   gtk_init (argc, argv);
1058 }
1059
1060 gboolean
1061 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1062 {
1063   check_sizeof_GtkWindow (sizeof_GtkWindow);
1064   if (num_checks >= 2)
1065     check_sizeof_GtkBox (sizeof_GtkBox);
1066   return gtk_init_check (argc, argv);
1067 }
1068
1069 #endif
1070
1071 void
1072 gtk_exit (gint errorcode)
1073 {
1074   exit (errorcode);
1075 }
1076
1077
1078 /**
1079  * gtk_set_locale:
1080  *
1081  * Initializes internationalization support for GTK+. gtk_init()
1082  * automatically does this, so there is typically no point
1083  * in calling this function.
1084  *
1085  * If you are calling this function because you changed the locale
1086  * after GTK+ is was initialized, then calling this function
1087  * may help a bit. (Note, however, that changing the locale
1088  * after GTK+ is initialized may produce inconsistent results and
1089  * is not really supported.)
1090  * 
1091  * In detail - sets the current locale according to the
1092  * program environment. This is the same as calling the C library function
1093  * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the 
1094  * locale specific setup of the windowing system used by GDK.
1095  * 
1096  * Returns: a string corresponding to the locale set, typically in the
1097  * form lang_COUNTRY, where lang is an ISO-639 language code, and
1098  * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1099  * result of the setlocale(); it is also used on other machines, such as 
1100  * Windows, where the C library returns a different result. The string is 
1101  * owned by GTK+ and should not be modified or freed.
1102  **/
1103 gchar *
1104 gtk_set_locale (void)
1105 {
1106   return gdk_set_locale ();
1107 }
1108
1109 /**
1110  * _gtk_get_lc_ctype:
1111  *
1112  * Return the Unix-style locale string for the language currently in
1113  * effect. On Unix systems, this is the return value from
1114  * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1115  * affect this through the environment variables LC_ALL, LC_CTYPE or
1116  * LANG (checked in that order). The locale strings typically is in
1117  * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1118  * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1119  * Swedish as written in Finland or pt_BR for Portuguese as written in
1120  * Brazil.
1121  * 
1122  * On Windows, the C library doesn't use any such environment
1123  * variables, and setting them won't affect the behaviour of functions
1124  * like ctime(). The user sets the locale through the Regional Options 
1125  * in the Control Panel. The C library (in the setlocale() function) 
1126  * does not use country and language codes, but country and language 
1127  * names spelled out in English. 
1128  * However, this function does check the above environment
1129  * variables, and does return a Unix-style locale string based on
1130  * either said environment variables or the thread's current locale.
1131  *
1132  * Return value: a dynamically allocated string, free with g_free().
1133  */
1134
1135 gchar *
1136 _gtk_get_lc_ctype (void)
1137 {
1138 #ifdef G_OS_WIN32
1139   /* Somebody might try to set the locale for this process using the
1140    * LANG or LC_ environment variables. The Microsoft C library
1141    * doesn't know anything about them. You set the locale in the
1142    * Control Panel. Setting these env vars won't have any affect on
1143    * locale-dependent C library functions like ctime(). But just for
1144    * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1145    * it easier to test GTK and Pango in various default languages, you
1146    * don't have to clickety-click in the Control Panel, you can simply
1147    * start the program with LC_ALL=something on the command line.)
1148    */
1149   gchar *p;
1150
1151   p = getenv ("LC_ALL");
1152   if (p != NULL)
1153     return g_strdup (p);
1154
1155   p = getenv ("LC_CTYPE");
1156   if (p != NULL)
1157     return g_strdup (p);
1158
1159   p = getenv ("LANG");
1160   if (p != NULL)
1161     return g_strdup (p);
1162
1163   return g_win32_getlocale ();
1164 #else
1165   return g_strdup (setlocale (LC_CTYPE, NULL));
1166 #endif
1167 }
1168
1169 /**
1170  * gtk_get_default_language:
1171  *
1172  * Returns the #PangoLanguage for the default language currently in
1173  * effect. (Note that this can change over the life of an
1174  * application.)  The default language is derived from the current
1175  * locale. It determines, for example, whether GTK+ uses the
1176  * right-to-left or left-to-right text direction.
1177  *
1178  * This function is equivalent to pango_language_get_default().  See
1179  * that function for details.
1180  * 
1181  * Return value: the default language as a #PangoLanguage, must not be
1182  * freed
1183  **/
1184 PangoLanguage *
1185 gtk_get_default_language (void)
1186 {
1187   return pango_language_get_default ();
1188 }
1189
1190 void
1191 gtk_main (void)
1192 {
1193   GList *tmp_list;
1194   GList *functions;
1195   GtkInitFunction *init;
1196   GMainLoop *loop;
1197
1198   gtk_main_loop_level++;
1199   
1200   loop = g_main_loop_new (NULL, TRUE);
1201   main_loops = g_slist_prepend (main_loops, loop);
1202
1203   tmp_list = functions = init_functions;
1204   init_functions = NULL;
1205   
1206   while (tmp_list)
1207     {
1208       init = tmp_list->data;
1209       tmp_list = tmp_list->next;
1210       
1211       (* init->function) (init->data);
1212       g_free (init);
1213     }
1214   g_list_free (functions);
1215
1216   if (g_main_loop_is_running (main_loops->data))
1217     {
1218       GDK_THREADS_LEAVE ();
1219       g_main_loop_run (loop);
1220       GDK_THREADS_ENTER ();
1221       gdk_flush ();
1222     }
1223
1224   if (quit_functions)
1225     {
1226       GList *reinvoke_list = NULL;
1227       GtkQuitFunction *quitf;
1228
1229       while (quit_functions)
1230         {
1231           quitf = quit_functions->data;
1232
1233           tmp_list = quit_functions;
1234           quit_functions = g_list_remove_link (quit_functions, quit_functions);
1235           g_list_free_1 (tmp_list);
1236
1237           if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1238               gtk_quit_invoke_function (quitf))
1239             {
1240               reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1241             }
1242           else
1243             {
1244               gtk_quit_destroy (quitf);
1245             }
1246         }
1247       if (reinvoke_list)
1248         {
1249           GList *work;
1250           
1251           work = g_list_last (reinvoke_list);
1252           if (quit_functions)
1253             quit_functions->prev = work;
1254           work->next = quit_functions;
1255           quit_functions = work;
1256         }
1257
1258       gdk_flush ();
1259     }
1260     
1261   main_loops = g_slist_remove (main_loops, loop);
1262
1263   g_main_loop_unref (loop);
1264
1265   gtk_main_loop_level--;
1266
1267   if (gtk_main_loop_level == 0)
1268     {
1269       /* Try storing all clipboard data we have */
1270       _gtk_clipboard_store_all ();
1271
1272       /* Synchronize the recent manager singleton */
1273       _gtk_recent_manager_sync ();
1274     }
1275 }
1276
1277 guint
1278 gtk_main_level (void)
1279 {
1280   return gtk_main_loop_level;
1281 }
1282
1283 void
1284 gtk_main_quit (void)
1285 {
1286   g_return_if_fail (main_loops != NULL);
1287
1288   g_main_loop_quit (main_loops->data);
1289 }
1290
1291 gboolean
1292 gtk_events_pending (void)
1293 {
1294   gboolean result;
1295   
1296   GDK_THREADS_LEAVE ();  
1297   result = g_main_context_pending (NULL);
1298   GDK_THREADS_ENTER ();
1299
1300   return result;
1301 }
1302
1303 gboolean
1304 gtk_main_iteration (void)
1305 {
1306   GDK_THREADS_LEAVE ();
1307   g_main_context_iteration (NULL, TRUE);
1308   GDK_THREADS_ENTER ();
1309
1310   if (main_loops)
1311     return !g_main_loop_is_running (main_loops->data);
1312   else
1313     return TRUE;
1314 }
1315
1316 gboolean
1317 gtk_main_iteration_do (gboolean blocking)
1318 {
1319   GDK_THREADS_LEAVE ();
1320   g_main_context_iteration (NULL, blocking);
1321   GDK_THREADS_ENTER ();
1322
1323   if (main_loops)
1324     return !g_main_loop_is_running (main_loops->data);
1325   else
1326     return TRUE;
1327 }
1328
1329 /* private libgtk to libgdk interfaces
1330  */
1331 gboolean gdk_pointer_grab_info_libgtk_only  (GdkDisplay *display,
1332                                              GdkWindow **grab_window,
1333                                              gboolean   *owner_events);
1334 gboolean gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1335                                              GdkWindow **grab_window,
1336                                              gboolean   *owner_events);
1337
1338 static void
1339 rewrite_events_translate (GdkWindow *old_window,
1340                           GdkWindow *new_window,
1341                           gdouble   *x,
1342                           gdouble   *y)
1343 {
1344   gint old_origin_x, old_origin_y;
1345   gint new_origin_x, new_origin_y;
1346
1347   gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1348   gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1349
1350   *x += old_origin_x - new_origin_x;
1351   *y += old_origin_y - new_origin_y;
1352 }
1353
1354 static GdkEvent *
1355 rewrite_event_for_window (GdkEvent  *event,
1356                           GdkWindow *new_window)
1357 {
1358   event = gdk_event_copy (event);
1359
1360   switch (event->type)
1361     {
1362     case GDK_SCROLL:
1363       rewrite_events_translate (event->any.window,
1364                                 new_window,
1365                                 &event->scroll.x, &event->scroll.y);
1366       break;
1367     case GDK_BUTTON_PRESS:
1368     case GDK_2BUTTON_PRESS:
1369     case GDK_3BUTTON_PRESS:
1370     case GDK_BUTTON_RELEASE:
1371       rewrite_events_translate (event->any.window,
1372                                 new_window,
1373                                 &event->button.x, &event->button.y);
1374       break;
1375     case GDK_MOTION_NOTIFY:
1376       rewrite_events_translate (event->any.window,
1377                                 new_window,
1378                                 &event->motion.x, &event->motion.y);
1379       break;
1380     case GDK_KEY_PRESS:
1381     case GDK_KEY_RELEASE:
1382     case GDK_PROXIMITY_IN:
1383     case GDK_PROXIMITY_OUT:
1384       break;
1385
1386     default:
1387       return event;
1388     }
1389
1390   g_object_unref (event->any.window);
1391   event->any.window = g_object_ref (new_window);
1392
1393   return event;
1394 }
1395
1396 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1397  * then what X11 does is deliver the event normally if it was going to this
1398  * client, otherwise, delivers it in terms of the grab window. This function
1399  * rewrites events to the effect that events going to the same window group
1400  * are delivered normally, otherwise, the event is delivered in terms of the
1401  * grab window.
1402  */
1403 static GdkEvent *
1404 rewrite_event_for_grabs (GdkEvent *event)
1405 {
1406   GdkWindow *grab_window;
1407   GtkWidget *event_widget, *grab_widget;
1408   gpointer grab_widget_ptr;
1409   gboolean owner_events;
1410   GdkDisplay *display;
1411
1412   switch (event->type)
1413     {
1414     case GDK_SCROLL:
1415     case GDK_BUTTON_PRESS:
1416     case GDK_2BUTTON_PRESS:
1417     case GDK_3BUTTON_PRESS:
1418     case GDK_BUTTON_RELEASE:
1419     case GDK_MOTION_NOTIFY:
1420     case GDK_PROXIMITY_IN:
1421     case GDK_PROXIMITY_OUT:
1422       display = gdk_drawable_get_display (event->proximity.window);
1423       if (!gdk_pointer_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1424           !owner_events)
1425         return NULL;
1426       break;
1427
1428     case GDK_KEY_PRESS:
1429     case GDK_KEY_RELEASE:
1430       display = gdk_drawable_get_display (event->key.window);
1431       if (!gdk_keyboard_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1432           !owner_events)
1433         return NULL;
1434       break;
1435
1436     default:
1437       return NULL;
1438     }
1439
1440   event_widget = gtk_get_event_widget (event);
1441   gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1442   grab_widget = grab_widget_ptr;
1443
1444   if (grab_widget &&
1445       gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1446     return rewrite_event_for_window (event, grab_window);
1447   else
1448     return NULL;
1449 }
1450
1451 void 
1452 gtk_main_do_event (GdkEvent *event)
1453 {
1454   GtkWidget *event_widget;
1455   GtkWidget *grab_widget;
1456   GtkWindowGroup *window_group;
1457   GdkEvent *rewritten_event = NULL;
1458   GList *tmp_list;
1459
1460   if (event->type == GDK_SETTING)
1461     {
1462       _gtk_settings_handle_event (&event->setting);
1463       return;
1464     }
1465
1466   if (event->type == GDK_OWNER_CHANGE)
1467     {
1468       _gtk_clipboard_handle_event (&event->owner_change);
1469       return;
1470     }
1471
1472   /* Find the widget which got the event. We store the widget
1473    *  in the user_data field of GdkWindow's.
1474    *  Ignore the event if we don't have a widget for it, except
1475    *  for GDK_PROPERTY_NOTIFY events which are handled specialy.
1476    *  Though this happens rarely, bogus events can occour
1477    *  for e.g. destroyed GdkWindows. 
1478    */
1479   event_widget = gtk_get_event_widget (event);
1480   if (!event_widget)
1481     {
1482       /* To handle selection INCR transactions, we select
1483        * PropertyNotify events on the requestor window and create
1484        * a corresponding (fake) GdkWindow so that events get
1485        * here. There won't be a widget though, so we have to handle
1486            * them specially
1487            */
1488       if (event->type == GDK_PROPERTY_NOTIFY)
1489         _gtk_selection_incr_event (event->any.window,
1490                                    &event->property);
1491
1492       return;
1493     }
1494
1495   /* If pointer or keyboard grabs are in effect, munge the events
1496    * so that each window group looks like a separate app.
1497    */
1498   rewritten_event = rewrite_event_for_grabs (event);
1499   if (rewritten_event)
1500     {
1501       event = rewritten_event;
1502       event_widget = gtk_get_event_widget (event);
1503     }
1504   
1505   window_group = gtk_main_get_window_group (event_widget);
1506
1507   /* Push the event onto a stack of current events for
1508    * gtk_current_event_get().
1509    */
1510   current_events = g_list_prepend (current_events, event);
1511
1512   /* If there is a grab in effect...
1513    */
1514   if (window_group->grabs)
1515     {
1516       grab_widget = window_group->grabs->data;
1517       
1518       /* If the grab widget is an ancestor of the event widget
1519        *  then we send the event to the original event widget.
1520        *  This is the key to implementing modality.
1521        */
1522       if (gtk_widget_is_sensitive (event_widget) &&
1523           gtk_widget_is_ancestor (event_widget, grab_widget))
1524         grab_widget = event_widget;
1525     }
1526   else
1527     {
1528       grab_widget = event_widget;
1529     }
1530
1531   /* Not all events get sent to the grabbing widget.
1532    * The delete, destroy, expose, focus change and resize
1533    *  events still get sent to the event widget because
1534    *  1) these events have no meaning for the grabbing widget
1535    *  and 2) redirecting these events to the grabbing widget
1536    *  could cause the display to be messed up.
1537    * 
1538    * Drag events are also not redirected, since it isn't
1539    *  clear what the semantics of that would be.
1540    */
1541   switch (event->type)
1542     {
1543     case GDK_NOTHING:
1544       break;
1545       
1546     case GDK_DELETE:
1547       g_object_ref (event_widget);
1548       if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1549           !gtk_widget_event (event_widget, event))
1550         gtk_widget_destroy (event_widget);
1551       g_object_unref (event_widget);
1552       break;
1553       
1554     case GDK_DESTROY:
1555       /* Unexpected GDK_DESTROY from the outside, ignore for
1556        * child windows, handle like a GDK_DELETE for toplevels
1557        */
1558       if (!event_widget->parent)
1559         {
1560           g_object_ref (event_widget);
1561           if (!gtk_widget_event (event_widget, event) &&
1562               GTK_WIDGET_REALIZED (event_widget))
1563             gtk_widget_destroy (event_widget);
1564           g_object_unref (event_widget);
1565         }
1566       break;
1567       
1568     case GDK_EXPOSE:
1569       if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1570         {
1571           gdk_window_begin_paint_region (event->any.window, event->expose.region);
1572           gtk_widget_send_expose (event_widget, event);
1573           gdk_window_end_paint (event->any.window);
1574         }
1575       else
1576         {
1577           /* The app may paint with a previously allocated cairo_t,
1578              which will draw directly to the window. We can't catch cairo
1579              drap operatoins to automatically flush the window, thus we
1580              need to explicitly flush any outstanding moves or double
1581              buffering */
1582           gdk_window_flush (event->any.window);
1583           gtk_widget_send_expose (event_widget, event);
1584         }
1585       break;
1586
1587     case GDK_PROPERTY_NOTIFY:
1588     case GDK_NO_EXPOSE:
1589     case GDK_FOCUS_CHANGE:
1590     case GDK_CONFIGURE:
1591     case GDK_MAP:
1592     case GDK_UNMAP:
1593     case GDK_SELECTION_CLEAR:
1594     case GDK_SELECTION_REQUEST:
1595     case GDK_SELECTION_NOTIFY:
1596     case GDK_CLIENT_EVENT:
1597     case GDK_VISIBILITY_NOTIFY:
1598     case GDK_WINDOW_STATE:
1599     case GDK_GRAB_BROKEN:
1600     case GDK_DAMAGE:
1601       gtk_widget_event (event_widget, event);
1602       break;
1603
1604     case GDK_SCROLL:
1605     case GDK_BUTTON_PRESS:
1606     case GDK_2BUTTON_PRESS:
1607     case GDK_3BUTTON_PRESS:
1608       gtk_propagate_event (grab_widget, event);
1609       break;
1610
1611     case GDK_KEY_PRESS:
1612     case GDK_KEY_RELEASE:
1613       if (key_snoopers)
1614         {
1615           if (gtk_invoke_key_snoopers (grab_widget, event))
1616             break;
1617         }
1618       /* Catch alt press to enable auto-mnemonics;
1619        * menus are handled elsewhere
1620        */
1621       if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1622           !GTK_IS_MENU_SHELL (grab_widget))
1623         {
1624           gboolean auto_mnemonics;
1625
1626           g_object_get (gtk_widget_get_settings (grab_widget),
1627                         "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1628
1629           if (auto_mnemonics)
1630             {
1631               gboolean mnemonics_visible;
1632               GtkWidget *window;
1633
1634               mnemonics_visible = (event->type == GDK_KEY_PRESS);
1635
1636               window = gtk_widget_get_toplevel (grab_widget);
1637
1638               if (GTK_IS_WINDOW (window))
1639                 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1640             }
1641         }
1642       /* else fall through */
1643     case GDK_MOTION_NOTIFY:
1644     case GDK_BUTTON_RELEASE:
1645     case GDK_PROXIMITY_IN:
1646     case GDK_PROXIMITY_OUT:
1647       gtk_propagate_event (grab_widget, event);
1648       break;
1649       
1650     case GDK_ENTER_NOTIFY:
1651       GTK_PRIVATE_SET_FLAG (event_widget, GTK_HAS_POINTER);
1652       _gtk_widget_set_pointer_window (event_widget, event->any.window);
1653       if (gtk_widget_is_sensitive (grab_widget))
1654         gtk_widget_event (grab_widget, event);
1655       break;
1656       
1657     case GDK_LEAVE_NOTIFY:
1658       GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_HAS_POINTER);
1659       if (gtk_widget_is_sensitive (grab_widget))
1660         gtk_widget_event (grab_widget, event);
1661       break;
1662       
1663     case GDK_DRAG_STATUS:
1664     case GDK_DROP_FINISHED:
1665       _gtk_drag_source_handle_event (event_widget, event);
1666       break;
1667     case GDK_DRAG_ENTER:
1668     case GDK_DRAG_LEAVE:
1669     case GDK_DRAG_MOTION:
1670     case GDK_DROP_START:
1671       _gtk_drag_dest_handle_event (event_widget, event);
1672       break;
1673     default:
1674       g_assert_not_reached ();
1675       break;
1676     }
1677
1678   if (event->type == GDK_ENTER_NOTIFY
1679       || event->type == GDK_LEAVE_NOTIFY
1680       || event->type == GDK_BUTTON_PRESS
1681       || event->type == GDK_2BUTTON_PRESS
1682       || event->type == GDK_3BUTTON_PRESS
1683       || event->type == GDK_KEY_PRESS
1684       || event->type == GDK_DRAG_ENTER
1685       || event->type == GDK_GRAB_BROKEN
1686       || event->type == GDK_MOTION_NOTIFY
1687       || event->type == GDK_SCROLL)
1688     {
1689       _gtk_tooltip_handle_event (event);
1690     }
1691   
1692   tmp_list = current_events;
1693   current_events = g_list_remove_link (current_events, tmp_list);
1694   g_list_free_1 (tmp_list);
1695
1696   if (rewritten_event)
1697     gdk_event_free (rewritten_event);
1698 }
1699
1700 gboolean
1701 gtk_true (void)
1702 {
1703   return TRUE;
1704 }
1705
1706 gboolean
1707 gtk_false (void)
1708 {
1709   return FALSE;
1710 }
1711
1712 static GtkWindowGroup *
1713 gtk_main_get_window_group (GtkWidget   *widget)
1714 {
1715   GtkWidget *toplevel = NULL;
1716
1717   if (widget)
1718     toplevel = gtk_widget_get_toplevel (widget);
1719
1720   if (GTK_IS_WINDOW (toplevel))
1721     return gtk_window_get_group (GTK_WINDOW (toplevel));
1722   else
1723     return gtk_window_get_group (NULL);
1724 }
1725
1726 typedef struct
1727 {
1728   GtkWidget *old_grab_widget;
1729   GtkWidget *new_grab_widget;
1730   gboolean   was_grabbed;
1731   gboolean   is_grabbed;
1732   gboolean   from_grab;
1733 } GrabNotifyInfo;
1734
1735 static void
1736 gtk_grab_notify_foreach (GtkWidget *child,
1737                          gpointer   data)
1738                         
1739 {
1740   GrabNotifyInfo *info = data;
1741  
1742   gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1743
1744   was_grabbed = info->was_grabbed;
1745   is_grabbed = info->is_grabbed;
1746
1747   info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1748   info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1749
1750   was_shadowed = info->old_grab_widget && !info->was_grabbed;
1751   is_shadowed = info->new_grab_widget && !info->is_grabbed;
1752
1753   g_object_ref (child);
1754
1755   if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1756     gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1757   
1758   if (is_shadowed)
1759     {
1760       GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1761       if (!was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1762           && gtk_widget_is_sensitive (child))
1763         _gtk_widget_synthesize_crossing (child, info->new_grab_widget,
1764                                          GDK_CROSSING_GTK_GRAB);
1765     }
1766   else
1767     {
1768       GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1769       if (was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1770           && gtk_widget_is_sensitive (child))
1771         _gtk_widget_synthesize_crossing (info->old_grab_widget, child,
1772                                          info->from_grab ? GDK_CROSSING_GTK_GRAB
1773                                          : GDK_CROSSING_GTK_UNGRAB);
1774     }
1775
1776   if (was_shadowed != is_shadowed)
1777     _gtk_widget_grab_notify (child, was_shadowed);
1778   
1779   g_object_unref (child);
1780   
1781   info->was_grabbed = was_grabbed;
1782   info->is_grabbed = is_grabbed;
1783 }
1784
1785 static void
1786 gtk_grab_notify (GtkWindowGroup *group,
1787                  GtkWidget      *old_grab_widget,
1788                  GtkWidget      *new_grab_widget,
1789                  gboolean        from_grab)
1790 {
1791   GList *toplevels;
1792   GrabNotifyInfo info;
1793
1794   if (old_grab_widget == new_grab_widget)
1795     return;
1796
1797   info.old_grab_widget = old_grab_widget;
1798   info.new_grab_widget = new_grab_widget;
1799   info.from_grab = from_grab;
1800
1801   g_object_ref (group);
1802
1803   toplevels = gtk_window_list_toplevels ();
1804   g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1805                             
1806   while (toplevels)
1807     {
1808       GtkWindow *toplevel = toplevels->data;
1809       toplevels = g_list_delete_link (toplevels, toplevels);
1810
1811       info.was_grabbed = FALSE;
1812       info.is_grabbed = FALSE;
1813
1814       if (group == gtk_window_get_group (toplevel))
1815         gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1816       g_object_unref (toplevel);
1817     }
1818
1819   g_object_unref (group);
1820 }
1821
1822 void
1823 gtk_grab_add (GtkWidget *widget)
1824 {
1825   GtkWindowGroup *group;
1826   GtkWidget *old_grab_widget;
1827   
1828   g_return_if_fail (widget != NULL);
1829   
1830   if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1831     {
1832       GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
1833       
1834       group = gtk_main_get_window_group (widget);
1835
1836       if (group->grabs)
1837         old_grab_widget = (GtkWidget *)group->grabs->data;
1838       else
1839         old_grab_widget = NULL;
1840
1841       g_object_ref (widget);
1842       group->grabs = g_slist_prepend (group->grabs, widget);
1843
1844       gtk_grab_notify (group, old_grab_widget, widget, TRUE);
1845     }
1846 }
1847
1848 GtkWidget*
1849 gtk_grab_get_current (void)
1850 {
1851   GtkWindowGroup *group;
1852
1853   group = gtk_main_get_window_group (NULL);
1854
1855   if (group->grabs)
1856     return GTK_WIDGET (group->grabs->data);
1857   return NULL;
1858 }
1859
1860 void
1861 gtk_grab_remove (GtkWidget *widget)
1862 {
1863   GtkWindowGroup *group;
1864   GtkWidget *new_grab_widget;
1865   
1866   g_return_if_fail (widget != NULL);
1867   
1868   if (gtk_widget_has_grab (widget))
1869     {
1870       GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
1871
1872       group = gtk_main_get_window_group (widget);
1873       group->grabs = g_slist_remove (group->grabs, widget);
1874       
1875       if (group->grabs)
1876         new_grab_widget = (GtkWidget *)group->grabs->data;
1877       else
1878         new_grab_widget = NULL;
1879
1880       gtk_grab_notify (group, widget, new_grab_widget, FALSE);
1881       
1882       g_object_unref (widget);
1883     }
1884 }
1885
1886 void
1887 gtk_init_add (GtkFunction function,
1888               gpointer    data)
1889 {
1890   GtkInitFunction *init;
1891   
1892   init = g_new (GtkInitFunction, 1);
1893   init->function = function;
1894   init->data = data;
1895   
1896   init_functions = g_list_prepend (init_functions, init);
1897 }
1898
1899 guint
1900 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
1901                          gpointer        func_data)
1902 {
1903   GtkKeySnooperData *data;
1904   static guint snooper_id = 1;
1905
1906   g_return_val_if_fail (snooper != NULL, 0);
1907
1908   data = g_new (GtkKeySnooperData, 1);
1909   data->func = snooper;
1910   data->func_data = func_data;
1911   data->id = snooper_id++;
1912   key_snoopers = g_slist_prepend (key_snoopers, data);
1913
1914   return data->id;
1915 }
1916
1917 void
1918 gtk_key_snooper_remove (guint snooper_id)
1919 {
1920   GtkKeySnooperData *data = NULL;
1921   GSList *slist;
1922
1923   slist = key_snoopers;
1924   while (slist)
1925     {
1926       data = slist->data;
1927       if (data->id == snooper_id)
1928         break;
1929
1930       slist = slist->next;
1931       data = NULL;
1932     }
1933   if (data)
1934     {
1935       key_snoopers = g_slist_remove (key_snoopers, data);
1936       g_free (data);
1937     }
1938 }
1939
1940 static gint
1941 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
1942                          GdkEvent  *event)
1943 {
1944   GSList *slist;
1945   gint return_val = FALSE;
1946
1947   slist = key_snoopers;
1948   while (slist && !return_val)
1949     {
1950       GtkKeySnooperData *data;
1951
1952       data = slist->data;
1953       slist = slist->next;
1954       return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
1955     }
1956
1957   return return_val;
1958 }
1959
1960 guint
1961 gtk_quit_add_full (guint                main_level,
1962                    GtkFunction          function,
1963                    GtkCallbackMarshal   marshal,
1964                    gpointer             data,
1965                    GDestroyNotify       destroy)
1966 {
1967   static guint quit_id = 1;
1968   GtkQuitFunction *quitf;
1969   
1970   g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
1971
1972   quitf = g_slice_new (GtkQuitFunction);
1973   
1974   quitf->id = quit_id++;
1975   quitf->main_level = main_level;
1976   quitf->function = function;
1977   quitf->marshal = marshal;
1978   quitf->data = data;
1979   quitf->destroy = destroy;
1980
1981   quit_functions = g_list_prepend (quit_functions, quitf);
1982   
1983   return quitf->id;
1984 }
1985
1986 static void
1987 gtk_quit_destroy (GtkQuitFunction *quitf)
1988 {
1989   if (quitf->destroy)
1990     quitf->destroy (quitf->data);
1991   g_slice_free (GtkQuitFunction, quitf);
1992 }
1993
1994 static gint
1995 gtk_quit_destructor (GtkObject **object_p)
1996 {
1997   if (*object_p)
1998     gtk_object_destroy (*object_p);
1999   g_free (object_p);
2000
2001   return FALSE;
2002 }
2003
2004 void
2005 gtk_quit_add_destroy (guint              main_level,
2006                       GtkObject         *object)
2007 {
2008   GtkObject **object_p;
2009
2010   g_return_if_fail (main_level > 0);
2011   g_return_if_fail (GTK_IS_OBJECT (object));
2012
2013   object_p = g_new (GtkObject*, 1);
2014   *object_p = object;
2015   g_signal_connect (object,
2016                     "destroy",
2017                     G_CALLBACK (gtk_widget_destroyed),
2018                     object_p);
2019   gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2020 }
2021
2022 guint
2023 gtk_quit_add (guint       main_level,
2024               GtkFunction function,
2025               gpointer    data)
2026 {
2027   return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2028 }
2029
2030 void
2031 gtk_quit_remove (guint id)
2032 {
2033   GtkQuitFunction *quitf;
2034   GList *tmp_list;
2035   
2036   tmp_list = quit_functions;
2037   while (tmp_list)
2038     {
2039       quitf = tmp_list->data;
2040       
2041       if (quitf->id == id)
2042         {
2043           quit_functions = g_list_remove_link (quit_functions, tmp_list);
2044           g_list_free (tmp_list);
2045           gtk_quit_destroy (quitf);
2046           
2047           return;
2048         }
2049       
2050       tmp_list = tmp_list->next;
2051     }
2052 }
2053
2054 void
2055 gtk_quit_remove_by_data (gpointer data)
2056 {
2057   GtkQuitFunction *quitf;
2058   GList *tmp_list;
2059   
2060   tmp_list = quit_functions;
2061   while (tmp_list)
2062     {
2063       quitf = tmp_list->data;
2064       
2065       if (quitf->data == data)
2066         {
2067           quit_functions = g_list_remove_link (quit_functions, tmp_list);
2068           g_list_free (tmp_list);
2069           gtk_quit_destroy (quitf);
2070
2071           return;
2072         }
2073       
2074       tmp_list = tmp_list->next;
2075     }
2076 }
2077
2078 guint
2079 gtk_timeout_add_full (guint32            interval,
2080                       GtkFunction        function,
2081                       GtkCallbackMarshal marshal,
2082                       gpointer           data,
2083                       GDestroyNotify     destroy)
2084 {
2085   if (marshal)
2086     {
2087       GtkClosure *closure;
2088
2089       closure = g_new (GtkClosure, 1);
2090       closure->marshal = marshal;
2091       closure->data = data;
2092       closure->destroy = destroy;
2093
2094       return g_timeout_add_full (0, interval, 
2095                                  gtk_invoke_idle_timeout,
2096                                  closure,
2097                                  gtk_destroy_closure);
2098     }
2099   else
2100     return g_timeout_add_full (0, interval, function, data, destroy);
2101 }
2102
2103 guint
2104 gtk_timeout_add (guint32     interval,
2105                  GtkFunction function,
2106                  gpointer    data)
2107 {
2108   return g_timeout_add_full (0, interval, function, data, NULL);
2109 }
2110
2111 void
2112 gtk_timeout_remove (guint tag)
2113 {
2114   g_source_remove (tag);
2115 }
2116
2117 guint
2118 gtk_idle_add_full (gint                 priority,
2119                    GtkFunction          function,
2120                    GtkCallbackMarshal   marshal,
2121                    gpointer             data,
2122                    GDestroyNotify       destroy)
2123 {
2124   if (marshal)
2125     {
2126       GtkClosure *closure;
2127
2128       closure = g_new (GtkClosure, 1);
2129       closure->marshal = marshal;
2130       closure->data = data;
2131       closure->destroy = destroy;
2132
2133       return g_idle_add_full (priority,
2134                               gtk_invoke_idle_timeout,
2135                               closure,
2136                               gtk_destroy_closure);
2137     }
2138   else
2139     return g_idle_add_full (priority, function, data, destroy);
2140 }
2141
2142 guint
2143 gtk_idle_add (GtkFunction function,
2144               gpointer    data)
2145 {
2146   return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
2147 }
2148
2149 guint       
2150 gtk_idle_add_priority (gint        priority,
2151                        GtkFunction function,
2152                        gpointer    data)
2153 {
2154   return g_idle_add_full (priority, function, data, NULL);
2155 }
2156
2157 void
2158 gtk_idle_remove (guint tag)
2159 {
2160   g_source_remove (tag);
2161 }
2162
2163 void
2164 gtk_idle_remove_by_data (gpointer data)
2165 {
2166   if (!g_idle_remove_by_data (data))
2167     g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
2168 }
2169
2170 guint
2171 gtk_input_add_full (gint                source,
2172                     GdkInputCondition   condition,
2173                     GdkInputFunction    function,
2174                     GtkCallbackMarshal  marshal,
2175                     gpointer            data,
2176                     GDestroyNotify      destroy)
2177 {
2178   if (marshal)
2179     {
2180       GtkClosure *closure;
2181
2182       closure = g_new (GtkClosure, 1);
2183       closure->marshal = marshal;
2184       closure->data = data;
2185       closure->destroy = destroy;
2186
2187       return gdk_input_add_full (source,
2188                                  condition,
2189                                  (GdkInputFunction) gtk_invoke_input,
2190                                  closure,
2191                                  (GDestroyNotify) gtk_destroy_closure);
2192     }
2193   else
2194     return gdk_input_add_full (source, condition, function, data, destroy);
2195 }
2196
2197 void
2198 gtk_input_remove (guint tag)
2199 {
2200   g_source_remove (tag);
2201 }
2202
2203 static void
2204 gtk_destroy_closure (gpointer data)
2205 {
2206   GtkClosure *closure = data;
2207
2208   if (closure->destroy)
2209     (closure->destroy) (closure->data);
2210   g_free (closure);
2211 }
2212
2213 static gboolean
2214 gtk_invoke_idle_timeout (gpointer data)
2215 {
2216   GtkClosure *closure = data;
2217
2218   GtkArg args[1];
2219   gint ret_val = FALSE;
2220   args[0].name = NULL;
2221   args[0].type = G_TYPE_BOOLEAN;
2222   args[0].d.pointer_data = &ret_val;
2223   closure->marshal (NULL, closure->data,  0, args);
2224   return ret_val;
2225 }
2226
2227 static void
2228 gtk_invoke_input (gpointer          data,
2229                   gint              source,
2230                   GdkInputCondition condition)
2231 {
2232   GtkClosure *closure = data;
2233
2234   GtkArg args[3];
2235   args[0].type = G_TYPE_INT;
2236   args[0].name = NULL;
2237   GTK_VALUE_INT (args[0]) = source;
2238   args[1].type = GDK_TYPE_INPUT_CONDITION;
2239   args[1].name = NULL;
2240   GTK_VALUE_FLAGS (args[1]) = condition;
2241   args[2].type = G_TYPE_NONE;
2242   args[2].name = NULL;
2243
2244   closure->marshal (NULL, closure->data, 2, args);
2245 }
2246
2247 /**
2248  * gtk_get_current_event:
2249  * 
2250  * Obtains a copy of the event currently being processed by GTK+.  For
2251  * example, if you get a "clicked" signal from #GtkButton, the current
2252  * event will be the #GdkEventButton that triggered the "clicked"
2253  * signal. The returned event must be freed with gdk_event_free().
2254  * If there is no current event, the function returns %NULL.
2255  * 
2256  * Return value: a copy of the current event, or %NULL if no current event.
2257  **/
2258 GdkEvent*
2259 gtk_get_current_event (void)
2260 {
2261   if (current_events)
2262     return gdk_event_copy (current_events->data);
2263   else
2264     return NULL;
2265 }
2266
2267 /**
2268  * gtk_get_current_event_time:
2269  * 
2270  * If there is a current event and it has a timestamp, return that
2271  * timestamp, otherwise return %GDK_CURRENT_TIME.
2272  * 
2273  * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2274  **/
2275 guint32
2276 gtk_get_current_event_time (void)
2277 {
2278   if (current_events)
2279     return gdk_event_get_time (current_events->data);
2280   else
2281     return GDK_CURRENT_TIME;
2282 }
2283
2284 /**
2285  * gtk_get_current_event_state:
2286  * @state: a location to store the state of the current event
2287  * 
2288  * If there is a current event and it has a state field, place
2289  * that state field in @state and return %TRUE, otherwise return
2290  * %FALSE.
2291  * 
2292  * Return value: %TRUE if there was a current event and it had a state field
2293  **/
2294 gboolean
2295 gtk_get_current_event_state (GdkModifierType *state)
2296 {
2297   g_return_val_if_fail (state != NULL, FALSE);
2298   
2299   if (current_events)
2300     return gdk_event_get_state (current_events->data, state);
2301   else
2302     {
2303       *state = 0;
2304       return FALSE;
2305     }
2306 }
2307
2308 /**
2309  * gtk_get_event_widget:
2310  * @event: a #GdkEvent
2311  *
2312  * If @event is %NULL or the event was not associated with any widget,
2313  * returns %NULL, otherwise returns the widget that received the event
2314  * originally.
2315  * 
2316  * Return value: the widget that originally received @event, or %NULL
2317  **/
2318 GtkWidget*
2319 gtk_get_event_widget (GdkEvent *event)
2320 {
2321   GtkWidget *widget;
2322   gpointer widget_ptr;
2323
2324   widget = NULL;
2325   if (event && event->any.window && 
2326       (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2327     {
2328       gdk_window_get_user_data (event->any.window, &widget_ptr);
2329       widget = widget_ptr;
2330     }
2331   
2332   return widget;
2333 }
2334
2335 static gint
2336 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2337 {
2338   if (!quitf->marshal)
2339     return quitf->function (quitf->data);
2340   else
2341     {
2342       GtkArg args[1];
2343       gint ret_val = FALSE;
2344
2345       args[0].name = NULL;
2346       args[0].type = G_TYPE_BOOLEAN;
2347       args[0].d.pointer_data = &ret_val;
2348       ((GtkCallbackMarshal) quitf->marshal) (NULL,
2349                                              quitf->data,
2350                                              0, args);
2351       return ret_val;
2352     }
2353 }
2354
2355 /**
2356  * gtk_propagate_event:
2357  * @widget: a #GtkWidget
2358  * @event: an event
2359  *
2360  * Sends an event to a widget, propagating the event to parent widgets
2361  * if the event remains unhandled. Events received by GTK+ from GDK
2362  * normally begin in gtk_main_do_event(). Depending on the type of
2363  * event, existence of modal dialogs, grabs, etc., the event may be
2364  * propagated; if so, this function is used. gtk_propagate_event()
2365  * calls gtk_widget_event() on each widget it decides to send the
2366  * event to.  So gtk_widget_event() is the lowest-level function; it
2367  * simply emits the "event" and possibly an event-specific signal on a
2368  * widget.  gtk_propagate_event() is a bit higher-level, and
2369  * gtk_main_do_event() is the highest level.
2370  *
2371  * All that said, you most likely don't want to use any of these
2372  * functions; synthesizing events is rarely needed. Consider asking on
2373  * the mailing list for better ways to achieve your goals. For
2374  * example, use gdk_window_invalidate_rect() or
2375  * gtk_widget_queue_draw() instead of making up expose events.
2376  * 
2377  **/
2378 void
2379 gtk_propagate_event (GtkWidget *widget,
2380                      GdkEvent  *event)
2381 {
2382   gint handled_event;
2383   
2384   g_return_if_fail (GTK_IS_WIDGET (widget));
2385   g_return_if_fail (event != NULL);
2386   
2387   handled_event = FALSE;
2388
2389   g_object_ref (widget);
2390       
2391   if ((event->type == GDK_KEY_PRESS) ||
2392       (event->type == GDK_KEY_RELEASE))
2393     {
2394       /* Only send key events within Window widgets to the Window
2395        *  The Window widget will in turn pass the
2396        *  key event on to the currently focused widget
2397        *  for that window.
2398        */
2399       GtkWidget *window;
2400
2401       window = gtk_widget_get_toplevel (widget);
2402       if (GTK_IS_WINDOW (window))
2403         {
2404           /* If there is a grab within the window, give the grab widget
2405            * a first crack at the key event
2406            */
2407           if (widget != window && gtk_widget_has_grab (widget))
2408             handled_event = gtk_widget_event (widget, event);
2409           
2410           if (!handled_event)
2411             {
2412               window = gtk_widget_get_toplevel (widget);
2413               if (GTK_IS_WINDOW (window))
2414                 {
2415                   if (gtk_widget_is_sensitive (window))
2416                     gtk_widget_event (window, event);
2417                 }
2418             }
2419                   
2420           handled_event = TRUE; /* don't send to widget */
2421         }
2422     }
2423   
2424   /* Other events get propagated up the widget tree
2425    *  so that parents can see the button and motion
2426    *  events of the children.
2427    */
2428   if (!handled_event)
2429     {
2430       while (TRUE)
2431         {
2432           GtkWidget *tmp;
2433
2434           /* Scroll events are special cased here because it
2435            * feels wrong when scrolling a GtkViewport, say,
2436            * to have children of the viewport eat the scroll
2437            * event
2438            */
2439           if (!gtk_widget_is_sensitive (widget))
2440             handled_event = event->type != GDK_SCROLL;
2441           else
2442             handled_event = gtk_widget_event (widget, event);
2443               
2444           tmp = widget->parent;
2445           g_object_unref (widget);
2446
2447           widget = tmp;
2448           
2449           if (!handled_event && widget)
2450             g_object_ref (widget);
2451           else
2452             break;
2453         }
2454     }
2455   else
2456     g_object_unref (widget);
2457 }
2458
2459 #if 0
2460 static void
2461 gtk_error (gchar *str)
2462 {
2463   gtk_print (str);
2464 }
2465
2466 static void
2467 gtk_warning (gchar *str)
2468 {
2469   gtk_print (str);
2470 }
2471
2472 static void
2473 gtk_message (gchar *str)
2474 {
2475   gtk_print (str);
2476 }
2477
2478 static void
2479 gtk_print (gchar *str)
2480 {
2481   static GtkWidget *window = NULL;
2482   static GtkWidget *text;
2483   static int level = 0;
2484   GtkWidget *box1;
2485   GtkWidget *box2;
2486   GtkWidget *table;
2487   GtkWidget *hscrollbar;
2488   GtkWidget *vscrollbar;
2489   GtkWidget *separator;
2490   GtkWidget *button;
2491   
2492   if (level > 0)
2493     {
2494       fputs (str, stdout);
2495       fflush (stdout);
2496       return;
2497     }
2498   
2499   if (!window)
2500     {
2501       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2502       
2503       gtk_signal_connect (GTK_OBJECT (window), "destroy",
2504                           G_CALLBACK (gtk_widget_destroyed),
2505                           &window);
2506       
2507       gtk_window_set_title (GTK_WINDOW (window), "Messages");
2508       
2509       box1 = gtk_vbox_new (FALSE, 0);
2510       gtk_container_add (GTK_CONTAINER (window), box1);
2511       gtk_widget_show (box1);
2512       
2513       
2514       box2 = gtk_vbox_new (FALSE, 10);
2515       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2516       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2517       gtk_widget_show (box2);
2518       
2519       
2520       table = gtk_table_new (2, 2, FALSE);
2521       gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2522       gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2523       gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2524       gtk_widget_show (table);
2525       
2526       text = gtk_text_new (NULL, NULL);
2527       gtk_text_set_editable (GTK_TEXT (text), FALSE);
2528       gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2529       gtk_widget_show (text);
2530       gtk_widget_realize (text);
2531       
2532       hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2533       gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2534                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2535       gtk_widget_show (hscrollbar);
2536       
2537       vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2538       gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2539                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2540       gtk_widget_show (vscrollbar);
2541       
2542       separator = gtk_hseparator_new ();
2543       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2544       gtk_widget_show (separator);
2545       
2546       
2547       box2 = gtk_vbox_new (FALSE, 10);
2548       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2549       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2550       gtk_widget_show (box2);
2551       
2552       
2553       button = gtk_button_new_with_label ("close");
2554       gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2555                                  G_CALLBACK (gtk_widget_hide),
2556                                  GTK_OBJECT (window));
2557       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2558       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2559       gtk_widget_grab_default (button);
2560       gtk_widget_show (button);
2561     }
2562   
2563   level += 1;
2564   gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2565   level -= 1;
2566   
2567   if (!gtk_widget_get_visible (window))
2568     gtk_widget_show (window);
2569 }
2570 #endif
2571
2572 gboolean
2573 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2574                                   GValue                *return_accu,
2575                                   const GValue          *handler_return,
2576                                   gpointer               dummy)
2577 {
2578   gboolean continue_emission;
2579   gboolean signal_handled;
2580   
2581   signal_handled = g_value_get_boolean (handler_return);
2582   g_value_set_boolean (return_accu, signal_handled);
2583   continue_emission = !signal_handled;
2584   
2585   return continue_emission;
2586 }
2587
2588 #define __GTK_MAIN_C__
2589 #include "gtkaliasdef.c"