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