]> Pileus Git - ~andy/gtk/blob - gtk/gtkmain.c
gtk: Don't include private GDK headers
[~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   _gtk_rc_init ();
800
801   /* Set the 'initialized' flag.
802    */
803   gtk_initialized = TRUE;
804
805   /* load gtk modules */
806   if (gtk_modules_string)
807     {
808       _gtk_modules_init (argc, argv, gtk_modules_string->str);
809       g_string_free (gtk_modules_string, TRUE);
810     }
811   else
812     {
813       _gtk_modules_init (argc, argv, NULL);
814     }
815 }
816
817
818 typedef struct
819 {
820   gboolean open_default_display;
821 } OptionGroupInfo;
822
823 static gboolean
824 pre_parse_hook (GOptionContext *context,
825                 GOptionGroup   *group,
826                 gpointer        data,
827                 GError        **error)
828 {
829   do_pre_parse_initialization (NULL, NULL);
830   
831   return TRUE;
832 }
833
834 static gboolean
835 post_parse_hook (GOptionContext *context,
836                  GOptionGroup   *group,
837                  gpointer       data,
838                  GError        **error)
839 {
840   OptionGroupInfo *info = data;
841
842   
843   do_post_parse_initialization (NULL, NULL);
844   
845   if (info->open_default_display)
846     {
847       if (gdk_display_open_default_libgtk_only () == NULL)
848         {
849           const char *display_name = gdk_get_display_arg_name ();
850           g_set_error (error, 
851                        G_OPTION_ERROR, 
852                        G_OPTION_ERROR_FAILED,
853                        _("Cannot open display: %s"),
854                        display_name ? display_name : "" );
855           
856           return FALSE;
857         }
858     }
859
860   return TRUE;
861 }
862
863
864 /**
865  * gtk_get_debug_flags:
866  *
867  * Returns the GTK+ debug flags setting.
868  */
869 guint
870 gtk_get_debug_flags (void)
871 {
872   return debug_flags;
873 }
874
875 /**
876  * gtk_set_debug_flags:
877  *
878  * Sets the GTK+ debug flags.
879  */
880 void
881 gtk_set_debug_flags (guint flags)
882 {
883   debug_flags = flags;
884 }
885
886 /**
887  * gtk_get_option_group:
888  * @open_default_display: whether to open the default display 
889  *    when parsing the commandline arguments
890  * 
891  * Returns a #GOptionGroup for the commandline arguments recognized
892  * by GTK+ and GDK. You should add this group to your #GOptionContext 
893  * with g_option_context_add_group(), if you are using 
894  * g_option_context_parse() to parse your commandline arguments.
895  *
896  * Returns: a #GOptionGroup for the commandline arguments recognized
897  *   by GTK+
898  *
899  * Since: 2.6
900  */
901 GOptionGroup *
902 gtk_get_option_group (gboolean open_default_display)
903 {
904   GOptionGroup *group;
905   OptionGroupInfo *info;
906
907   gettext_initialization ();
908
909   info = g_new0 (OptionGroupInfo, 1);
910   info->open_default_display = open_default_display;
911   
912   group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
913   g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
914
915   gdk_add_option_entries_libgtk_only (group);
916   g_option_group_add_entries (group, gtk_args);
917   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
918   
919   return group;
920 }
921
922 /**
923  * gtk_init_with_args:
924  * @argc: a pointer to the number of command line arguments.
925  * @argv: a pointer to the array of command line arguments.
926  * @parameter_string: a string which is displayed in
927  *    the first line of <option>--help</option> output, after
928  *    <literal><replaceable>programname</replaceable> [OPTION...]</literal>
929  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
930  *    describing the options of your program
931  * @translation_domain: a translation domain to use for translating
932  *    the <option>--help</option> output for the options in @entries
933  *    and the @parameter_string with gettext(), or %NULL
934  * @error: a return location for errors
935  *
936  * This function does the same work as gtk_init_check().
937  * Additionally, it allows you to add your own commandline options,
938  * and it automatically generates nicely formatted
939  * <option>--help</option> output. Note that your program will
940  * be terminated after writing out the help output.
941  *
942  * Returns: %TRUE if the GUI has been successfully initialized,
943  *               %FALSE otherwise.
944  *
945  * Since: 2.6
946  */
947 gboolean
948 gtk_init_with_args (gint                 *argc,
949                     gchar              ***argv,
950                     const gchar          *parameter_string,
951                     const GOptionEntry   *entries,
952                     const gchar          *translation_domain,
953                     GError              **error)
954 {
955   GOptionContext *context;
956   GOptionGroup *gtk_group;
957   gboolean retval;
958
959   if (gtk_initialized)
960     return gdk_display_open_default_libgtk_only () != NULL;
961
962   gettext_initialization ();
963
964   if (!check_setugid ())
965     return FALSE;
966
967   gtk_group = gtk_get_option_group (TRUE);
968
969   context = g_option_context_new (parameter_string);
970   g_option_context_add_group (context, gtk_group);
971   g_option_context_set_translation_domain (context, translation_domain);
972
973   if (entries)
974     g_option_context_add_main_entries (context, entries, translation_domain);
975   retval = g_option_context_parse (context, argc, argv, error);
976
977   g_option_context_free (context);
978
979   return retval;
980 }
981
982
983 /**
984  * gtk_parse_args:
985  * @argc: (inout): a pointer to the number of command line arguments.
986  * @argv: (array) (inout): a pointer to the array of command line arguments.
987  *
988  * Parses command line arguments, and initializes global
989  * attributes of GTK+, but does not actually open a connection
990  * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
991  *
992  * Any arguments used by GTK+ or GDK are removed from the array and
993  * @argc and @argv are updated accordingly.
994  *
995  * You shouldn't call this function explicitely if you are using
996  * gtk_init(), or gtk_init_check().
997  *
998  * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
999  **/
1000 gboolean
1001 gtk_parse_args (int    *argc,
1002                 char ***argv)
1003 {
1004   GOptionContext *option_context;
1005   GOptionGroup *gtk_group;
1006   GError *error = NULL;
1007   
1008   if (gtk_initialized)
1009     return TRUE;
1010
1011   gettext_initialization ();
1012
1013   if (!check_setugid ())
1014     return FALSE;
1015
1016   option_context = g_option_context_new (NULL);
1017   g_option_context_set_ignore_unknown_options (option_context, TRUE);
1018   g_option_context_set_help_enabled (option_context, FALSE);
1019   gtk_group = gtk_get_option_group (FALSE);
1020   g_option_context_set_main_group (option_context, gtk_group);
1021   if (!g_option_context_parse (option_context, argc, argv, &error))
1022     {
1023       g_warning ("%s", error->message);
1024       g_error_free (error);
1025     }
1026
1027   g_option_context_free (option_context);
1028
1029   return TRUE;
1030 }
1031
1032 #ifdef G_PLATFORM_WIN32
1033 #undef gtk_init_check
1034 #endif
1035
1036 /**
1037  * gtk_init_check:
1038  * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1039  *   main() function. Changed if any arguments were handled.
1040  * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1041  *   Any parameters understood by gtk_init() are stripped before return.
1042  *
1043  * This function does the same work as gtk_init() with only
1044  * a single change: It does not terminate the program if the GUI can't be
1045  * initialized. Instead it returns %FALSE on failure.
1046  *
1047  * This way the application can fall back to some other means of communication 
1048  * with the user - for example a curses or command line interface.
1049  * 
1050  * Return value: %TRUE if the GUI has been successfully initialized, 
1051  *               %FALSE otherwise.
1052  **/
1053 gboolean
1054 gtk_init_check (int      *argc,
1055                 char   ***argv)
1056 {
1057   if (!gtk_parse_args (argc, argv))
1058     return FALSE;
1059
1060   return gdk_display_open_default_libgtk_only () != NULL;
1061 }
1062
1063 #ifdef G_PLATFORM_WIN32
1064 #undef gtk_init
1065 #endif
1066
1067 /**
1068  * gtk_init:
1069  * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1070  *   main() function. Changed if any arguments were handled.
1071  * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1072  *   Any parameters understood by gtk_init() are stripped before return.
1073  *
1074  * Call this function before using any other GTK+ functions in your GUI
1075  * applications.  It will initialize everything needed to operate the
1076  * toolkit and parses some standard command line options. @argc and 
1077  * @argv are adjusted accordingly so your own code will 
1078  * never see those standard arguments. 
1079  *
1080  * Note that there are some alternative ways to initialize GTK+: 
1081  * if you are calling gtk_parse_args(), gtk_init_check(), 
1082  * gtk_init_with_args() or g_option_context_parse() with 
1083  * the option group returned by gtk_get_option_group(), you 
1084  * <emphasis>don't</emphasis> have to call gtk_init().
1085  *
1086  * <note><para>
1087  * This function will terminate your program if it was unable to initialize 
1088  * the GUI for some reason. If you want your program to fall back to a 
1089  * textual interface you want to call gtk_init_check() instead.
1090  * </para></note>
1091  *
1092  * <note><para>
1093  * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1094  * during initialization, to ignore SIGPIPE signals, since these are
1095  * almost never wanted in graphical applications. If you do need to
1096  * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1097  * but notice that other libraries (e.g. libdbus or gvfs) might do
1098  * similar things.
1099  * </para></note>
1100  **/
1101 void
1102 gtk_init (int *argc, char ***argv)
1103 {
1104   if (!gtk_init_check (argc, argv))
1105     {
1106       const char *display_name_arg = gdk_get_display_arg_name ();
1107       if (display_name_arg == NULL)
1108         display_name_arg = getenv("DISPLAY");
1109       g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1110       exit (1);
1111     }
1112 }
1113
1114 #ifdef G_PLATFORM_WIN32
1115
1116 static void
1117 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1118 {
1119   if (sizeof_GtkWindow != sizeof (GtkWindow))
1120     g_error ("Incompatible build!\n"
1121              "The code using GTK+ thinks GtkWindow is of different\n"
1122              "size than it actually is in this build of GTK+.\n"
1123              "On Windows, this probably means that you have compiled\n"
1124              "your code with gcc without the -mms-bitfields switch,\n"
1125              "or that you are using an unsupported compiler.");
1126 }
1127
1128 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1129  * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1130  * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1131  * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1132  * -fnative-struct still matters. GtkBox is one such.
1133  */
1134 static void
1135 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1136 {
1137   if (sizeof_GtkBox != sizeof (GtkBox))
1138     g_error ("Incompatible build!\n"
1139              "The code using GTK+ thinks GtkBox is of different\n"
1140              "size than it actually is in this build of GTK+.\n"
1141              "On Windows, this probably means that you have compiled\n"
1142              "your code with gcc without the -mms-bitfields switch,\n"
1143              "or that you are using an unsupported compiler.");
1144 }
1145
1146 /* These two functions might get more checks added later, thus pass
1147  * in the number of extra args.
1148  */
1149 void
1150 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1151 {
1152   check_sizeof_GtkWindow (sizeof_GtkWindow);
1153   if (num_checks >= 2)
1154     check_sizeof_GtkBox (sizeof_GtkBox);
1155   gtk_init (argc, argv);
1156 }
1157
1158 gboolean
1159 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1160 {
1161   check_sizeof_GtkWindow (sizeof_GtkWindow);
1162   if (num_checks >= 2)
1163     check_sizeof_GtkBox (sizeof_GtkBox);
1164   return gtk_init_check (argc, argv);
1165 }
1166
1167 #endif
1168
1169 /**
1170  * gtk_set_locale:
1171  *
1172  * Initializes internationalization support for GTK+. gtk_init()
1173  * automatically does this, so there is typically no point
1174  * in calling this function.
1175  *
1176  * If you are calling this function because you changed the locale
1177  * after GTK+ is was initialized, then calling this function
1178  * may help a bit. (Note, however, that changing the locale
1179  * after GTK+ is initialized may produce inconsistent results and
1180  * is not really supported.)
1181  * 
1182  * In detail - sets the current locale according to the
1183  * program environment. This is the same as calling the C library function
1184  * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the 
1185  * locale specific setup of the windowing system used by GDK.
1186  * 
1187  * Returns: a string corresponding to the locale set, typically in the
1188  * form lang_COUNTRY, where lang is an ISO-639 language code, and
1189  * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1190  * result of the setlocale(); it is also used on other machines, such as 
1191  * Windows, where the C library returns a different result. The string is 
1192  * owned by GTK+ and should not be modified or freed.
1193  **/
1194 gchar *
1195 gtk_set_locale (void)
1196 {
1197   return gdk_set_locale ();
1198 }
1199
1200 /**
1201  * _gtk_get_lc_ctype:
1202  *
1203  * Return the Unix-style locale string for the language currently in
1204  * effect. On Unix systems, this is the return value from
1205  * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1206  * affect this through the environment variables LC_ALL, LC_CTYPE or
1207  * LANG (checked in that order). The locale strings typically is in
1208  * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1209  * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1210  * Swedish as written in Finland or pt_BR for Portuguese as written in
1211  * Brazil.
1212  * 
1213  * On Windows, the C library doesn't use any such environment
1214  * variables, and setting them won't affect the behaviour of functions
1215  * like ctime(). The user sets the locale through the Regional Options 
1216  * in the Control Panel. The C library (in the setlocale() function) 
1217  * does not use country and language codes, but country and language 
1218  * names spelled out in English. 
1219  * However, this function does check the above environment
1220  * variables, and does return a Unix-style locale string based on
1221  * either said environment variables or the thread's current locale.
1222  *
1223  * Return value: a dynamically allocated string, free with g_free().
1224  */
1225
1226 gchar *
1227 _gtk_get_lc_ctype (void)
1228 {
1229 #ifdef G_OS_WIN32
1230   /* Somebody might try to set the locale for this process using the
1231    * LANG or LC_ environment variables. The Microsoft C library
1232    * doesn't know anything about them. You set the locale in the
1233    * Control Panel. Setting these env vars won't have any affect on
1234    * locale-dependent C library functions like ctime(). But just for
1235    * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1236    * it easier to test GTK and Pango in various default languages, you
1237    * don't have to clickety-click in the Control Panel, you can simply
1238    * start the program with LC_ALL=something on the command line.)
1239    */
1240   gchar *p;
1241
1242   p = getenv ("LC_ALL");
1243   if (p != NULL)
1244     return g_strdup (p);
1245
1246   p = getenv ("LC_CTYPE");
1247   if (p != NULL)
1248     return g_strdup (p);
1249
1250   p = getenv ("LANG");
1251   if (p != NULL)
1252     return g_strdup (p);
1253
1254   return g_win32_getlocale ();
1255 #else
1256   return g_strdup (setlocale (LC_CTYPE, NULL));
1257 #endif
1258 }
1259
1260 /**
1261  * gtk_get_default_language:
1262  *
1263  * Returns the #PangoLanguage for the default language currently in
1264  * effect. (Note that this can change over the life of an
1265  * application.)  The default language is derived from the current
1266  * locale. It determines, for example, whether GTK+ uses the
1267  * right-to-left or left-to-right text direction.
1268  *
1269  * This function is equivalent to pango_language_get_default().  See
1270  * that function for details.
1271  * 
1272  * Return value: the default language as a #PangoLanguage, must not be
1273  * freed
1274  **/
1275 PangoLanguage *
1276 gtk_get_default_language (void)
1277 {
1278   return pango_language_get_default ();
1279 }
1280
1281 void
1282 gtk_main (void)
1283 {
1284   GList *tmp_list;
1285   GMainLoop *loop;
1286
1287   gtk_main_loop_level++;
1288   
1289   loop = g_main_loop_new (NULL, TRUE);
1290   main_loops = g_slist_prepend (main_loops, loop);
1291
1292   if (g_main_loop_is_running (main_loops->data))
1293     {
1294       GDK_THREADS_LEAVE ();
1295       g_main_loop_run (loop);
1296       GDK_THREADS_ENTER ();
1297       gdk_flush ();
1298     }
1299
1300   if (quit_functions)
1301     {
1302       GList *reinvoke_list = NULL;
1303       GtkQuitFunction *quitf;
1304
1305       while (quit_functions)
1306         {
1307           quitf = quit_functions->data;
1308
1309           tmp_list = quit_functions;
1310           quit_functions = g_list_remove_link (quit_functions, quit_functions);
1311           g_list_free_1 (tmp_list);
1312
1313           if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1314               gtk_quit_invoke_function (quitf))
1315             {
1316               reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1317             }
1318           else
1319             {
1320               gtk_quit_destroy (quitf);
1321             }
1322         }
1323       if (reinvoke_list)
1324         {
1325           GList *work;
1326           
1327           work = g_list_last (reinvoke_list);
1328           if (quit_functions)
1329             quit_functions->prev = work;
1330           work->next = quit_functions;
1331           quit_functions = work;
1332         }
1333
1334       gdk_flush ();
1335     }
1336     
1337   main_loops = g_slist_remove (main_loops, loop);
1338
1339   g_main_loop_unref (loop);
1340
1341   gtk_main_loop_level--;
1342
1343   if (gtk_main_loop_level == 0)
1344     {
1345       /* Try storing all clipboard data we have */
1346       _gtk_clipboard_store_all ();
1347
1348       /* Synchronize the recent manager singleton */
1349       _gtk_recent_manager_sync ();
1350     }
1351 }
1352
1353 guint
1354 gtk_main_level (void)
1355 {
1356   return gtk_main_loop_level;
1357 }
1358
1359 void
1360 gtk_main_quit (void)
1361 {
1362   g_return_if_fail (main_loops != NULL);
1363
1364   g_main_loop_quit (main_loops->data);
1365 }
1366
1367 gboolean
1368 gtk_events_pending (void)
1369 {
1370   gboolean result;
1371   
1372   GDK_THREADS_LEAVE ();  
1373   result = g_main_context_pending (NULL);
1374   GDK_THREADS_ENTER ();
1375
1376   return result;
1377 }
1378
1379 gboolean
1380 gtk_main_iteration (void)
1381 {
1382   GDK_THREADS_LEAVE ();
1383   g_main_context_iteration (NULL, TRUE);
1384   GDK_THREADS_ENTER ();
1385
1386   if (main_loops)
1387     return !g_main_loop_is_running (main_loops->data);
1388   else
1389     return TRUE;
1390 }
1391
1392 gboolean
1393 gtk_main_iteration_do (gboolean blocking)
1394 {
1395   GDK_THREADS_LEAVE ();
1396   g_main_context_iteration (NULL, blocking);
1397   GDK_THREADS_ENTER ();
1398
1399   if (main_loops)
1400     return !g_main_loop_is_running (main_loops->data);
1401   else
1402     return TRUE;
1403 }
1404
1405 /* private libgtk to libgdk interfaces
1406  */
1407 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay  *display,
1408                                            GdkDevice   *device,
1409                                            GdkWindow  **grab_window,
1410                                            gboolean    *owner_events);
1411
1412 static void
1413 rewrite_events_translate (GdkWindow *old_window,
1414                           GdkWindow *new_window,
1415                           gdouble   *x,
1416                           gdouble   *y)
1417 {
1418   gint old_origin_x, old_origin_y;
1419   gint new_origin_x, new_origin_y;
1420
1421   gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1422   gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1423
1424   *x += old_origin_x - new_origin_x;
1425   *y += old_origin_y - new_origin_y;
1426 }
1427
1428 static GdkEvent *
1429 rewrite_event_for_window (GdkEvent  *event,
1430                           GdkWindow *new_window)
1431 {
1432   event = gdk_event_copy (event);
1433
1434   switch (event->type)
1435     {
1436     case GDK_SCROLL:
1437       rewrite_events_translate (event->any.window,
1438                                 new_window,
1439                                 &event->scroll.x, &event->scroll.y);
1440       break;
1441     case GDK_BUTTON_PRESS:
1442     case GDK_2BUTTON_PRESS:
1443     case GDK_3BUTTON_PRESS:
1444     case GDK_BUTTON_RELEASE:
1445       rewrite_events_translate (event->any.window,
1446                                 new_window,
1447                                 &event->button.x, &event->button.y);
1448       break;
1449     case GDK_MOTION_NOTIFY:
1450       rewrite_events_translate (event->any.window,
1451                                 new_window,
1452                                 &event->motion.x, &event->motion.y);
1453       break;
1454     case GDK_KEY_PRESS:
1455     case GDK_KEY_RELEASE:
1456     case GDK_PROXIMITY_IN:
1457     case GDK_PROXIMITY_OUT:
1458       break;
1459
1460     default:
1461       return event;
1462     }
1463
1464   g_object_unref (event->any.window);
1465   event->any.window = g_object_ref (new_window);
1466
1467   return event;
1468 }
1469
1470 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1471  * then what X11 does is deliver the event normally if it was going to this
1472  * client, otherwise, delivers it in terms of the grab window. This function
1473  * rewrites events to the effect that events going to the same window group
1474  * are delivered normally, otherwise, the event is delivered in terms of the
1475  * grab window.
1476  */
1477 static GdkEvent *
1478 rewrite_event_for_grabs (GdkEvent *event)
1479 {
1480   GdkWindow *grab_window;
1481   GtkWidget *event_widget, *grab_widget;
1482   gpointer grab_widget_ptr;
1483   gboolean owner_events;
1484   GdkDisplay *display;
1485   GdkDevice *device;
1486
1487   switch (event->type)
1488     {
1489     case GDK_SCROLL:
1490     case GDK_BUTTON_PRESS:
1491     case GDK_2BUTTON_PRESS:
1492     case GDK_3BUTTON_PRESS:
1493     case GDK_BUTTON_RELEASE:
1494     case GDK_MOTION_NOTIFY:
1495     case GDK_PROXIMITY_IN:
1496     case GDK_PROXIMITY_OUT:
1497     case GDK_KEY_PRESS:
1498     case GDK_KEY_RELEASE:
1499       display = gdk_window_get_display (event->any.window);
1500       device = gdk_event_get_device (event);
1501
1502       if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1503           !owner_events)
1504         return NULL;
1505       break;
1506     default:
1507       return NULL;
1508     }
1509
1510   event_widget = gtk_get_event_widget (event);
1511   gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1512   grab_widget = grab_widget_ptr;
1513
1514   if (grab_widget &&
1515       gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1516     return rewrite_event_for_window (event, grab_window);
1517   else
1518     return NULL;
1519 }
1520
1521 void 
1522 gtk_main_do_event (GdkEvent *event)
1523 {
1524   GtkWidget *event_widget;
1525   GtkWidget *grab_widget = NULL;
1526   GtkWindowGroup *window_group;
1527   GdkEvent *rewritten_event = NULL;
1528   GdkDevice *device;
1529   GList *tmp_list;
1530
1531   if (event->type == GDK_SETTING)
1532     {
1533       _gtk_settings_handle_event (&event->setting);
1534       return;
1535     }
1536
1537   if (event->type == GDK_OWNER_CHANGE)
1538     {
1539       _gtk_clipboard_handle_event (&event->owner_change);
1540       return;
1541     }
1542
1543   /* Find the widget which got the event. We store the widget
1544    *  in the user_data field of GdkWindow's.
1545    *  Ignore the event if we don't have a widget for it, except
1546    *  for GDK_PROPERTY_NOTIFY events which are handled specialy.
1547    *  Though this happens rarely, bogus events can occour
1548    *  for e.g. destroyed GdkWindows. 
1549    */
1550   event_widget = gtk_get_event_widget (event);
1551   if (!event_widget)
1552     {
1553       /* To handle selection INCR transactions, we select
1554        * PropertyNotify events on the requestor window and create
1555        * a corresponding (fake) GdkWindow so that events get
1556        * here. There won't be a widget though, so we have to handle
1557            * them specially
1558            */
1559       if (event->type == GDK_PROPERTY_NOTIFY)
1560         _gtk_selection_incr_event (event->any.window,
1561                                    &event->property);
1562
1563       return;
1564     }
1565
1566   /* If pointer or keyboard grabs are in effect, munge the events
1567    * so that each window group looks like a separate app.
1568    */
1569   rewritten_event = rewrite_event_for_grabs (event);
1570   if (rewritten_event)
1571     {
1572       event = rewritten_event;
1573       event_widget = gtk_get_event_widget (event);
1574     }
1575
1576   window_group = gtk_main_get_window_group (event_widget);
1577   device = gdk_event_get_device (event);
1578
1579   /* check whether there is a (device) grab in effect...
1580    */
1581   if (device)
1582     grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1583
1584   if (!grab_widget && window_group->grabs)
1585     grab_widget = window_group->grabs->data;
1586
1587   /* If the grab widget is an ancestor of the event widget
1588    *  then we send the event to the original event widget.
1589    *  This is the key to implementing modality.
1590    */
1591   if (!grab_widget ||
1592       (gtk_widget_is_sensitive (event_widget) &&
1593        gtk_widget_is_ancestor (event_widget, grab_widget)))
1594     grab_widget = event_widget;
1595
1596   /* If the widget receiving events is actually blocked by another device GTK+ grab */
1597   if (device &&
1598       _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1599     {
1600       if (rewritten_event)
1601         gdk_event_free (rewritten_event);
1602
1603       return;
1604     }
1605
1606   /* Push the event onto a stack of current events for
1607    * gtk_current_event_get().
1608    */
1609   current_events = g_list_prepend (current_events, event);
1610
1611   /* Not all events get sent to the grabbing widget.
1612    * The delete, destroy, expose, focus change and resize
1613    *  events still get sent to the event widget because
1614    *  1) these events have no meaning for the grabbing widget
1615    *  and 2) redirecting these events to the grabbing widget
1616    *  could cause the display to be messed up.
1617    * 
1618    * Drag events are also not redirected, since it isn't
1619    *  clear what the semantics of that would be.
1620    */
1621   switch (event->type)
1622     {
1623     case GDK_NOTHING:
1624       break;
1625       
1626     case GDK_DELETE:
1627       g_object_ref (event_widget);
1628       if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1629           !gtk_widget_event (event_widget, event))
1630         gtk_widget_destroy (event_widget);
1631       g_object_unref (event_widget);
1632       break;
1633       
1634     case GDK_DESTROY:
1635       /* Unexpected GDK_DESTROY from the outside, ignore for
1636        * child windows, handle like a GDK_DELETE for toplevels
1637        */
1638       if (!gtk_widget_get_parent (event_widget))
1639         {
1640           g_object_ref (event_widget);
1641           if (!gtk_widget_event (event_widget, event) &&
1642               gtk_widget_get_realized (event_widget))
1643             gtk_widget_destroy (event_widget);
1644           g_object_unref (event_widget);
1645         }
1646       break;
1647       
1648     case GDK_EXPOSE:
1649       if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1650         {
1651           gdk_window_begin_paint_region (event->any.window, event->expose.region);
1652           gtk_widget_send_expose (event_widget, event);
1653           gdk_window_end_paint (event->any.window);
1654         }
1655       else
1656         {
1657           /* The app may paint with a previously allocated cairo_t,
1658              which will draw directly to the window. We can't catch cairo
1659              drap operatoins to automatically flush the window, thus we
1660              need to explicitly flush any outstanding moves or double
1661              buffering */
1662           gdk_window_flush (event->any.window);
1663           gtk_widget_send_expose (event_widget, event);
1664         }
1665       break;
1666
1667     case GDK_PROPERTY_NOTIFY:
1668     case GDK_FOCUS_CHANGE:
1669     case GDK_CONFIGURE:
1670     case GDK_MAP:
1671     case GDK_UNMAP:
1672     case GDK_SELECTION_CLEAR:
1673     case GDK_SELECTION_REQUEST:
1674     case GDK_SELECTION_NOTIFY:
1675     case GDK_CLIENT_EVENT:
1676     case GDK_VISIBILITY_NOTIFY:
1677     case GDK_WINDOW_STATE:
1678     case GDK_GRAB_BROKEN:
1679     case GDK_DAMAGE:
1680       gtk_widget_event (event_widget, event);
1681       break;
1682
1683     case GDK_SCROLL:
1684     case GDK_BUTTON_PRESS:
1685     case GDK_2BUTTON_PRESS:
1686     case GDK_3BUTTON_PRESS:
1687       gtk_propagate_event (grab_widget, event);
1688       break;
1689
1690     case GDK_KEY_PRESS:
1691     case GDK_KEY_RELEASE:
1692       if (key_snoopers)
1693         {
1694           if (gtk_invoke_key_snoopers (grab_widget, event))
1695             break;
1696         }
1697       /* Catch alt press to enable auto-mnemonics;
1698        * menus are handled elsewhere
1699        */
1700       if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1701           !GTK_IS_MENU_SHELL (grab_widget))
1702         {
1703           gboolean auto_mnemonics;
1704
1705           g_object_get (gtk_widget_get_settings (grab_widget),
1706                         "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1707
1708           if (auto_mnemonics)
1709             {
1710               gboolean mnemonics_visible;
1711               GtkWidget *window;
1712
1713               mnemonics_visible = (event->type == GDK_KEY_PRESS);
1714
1715               window = gtk_widget_get_toplevel (grab_widget);
1716
1717               if (GTK_IS_WINDOW (window))
1718                 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1719             }
1720         }
1721       /* else fall through */
1722     case GDK_MOTION_NOTIFY:
1723     case GDK_BUTTON_RELEASE:
1724     case GDK_PROXIMITY_IN:
1725     case GDK_PROXIMITY_OUT:
1726       gtk_propagate_event (grab_widget, event);
1727       break;
1728       
1729     case GDK_ENTER_NOTIFY:
1730       _gtk_widget_set_device_window (event_widget,
1731                                      gdk_event_get_device (event),
1732                                      event->any.window);
1733       if (gtk_widget_is_sensitive (grab_widget))
1734         gtk_widget_event (grab_widget, event);
1735       break;
1736       
1737     case GDK_LEAVE_NOTIFY:
1738       _gtk_widget_set_device_window (event_widget,
1739                                      gdk_event_get_device (event),
1740                                      NULL);
1741       if (gtk_widget_is_sensitive (grab_widget))
1742         gtk_widget_event (grab_widget, event);
1743       break;
1744       
1745     case GDK_DRAG_STATUS:
1746     case GDK_DROP_FINISHED:
1747       _gtk_drag_source_handle_event (event_widget, event);
1748       break;
1749     case GDK_DRAG_ENTER:
1750     case GDK_DRAG_LEAVE:
1751     case GDK_DRAG_MOTION:
1752     case GDK_DROP_START:
1753       _gtk_drag_dest_handle_event (event_widget, event);
1754       break;
1755     default:
1756       g_assert_not_reached ();
1757       break;
1758     }
1759
1760   if (event->type == GDK_ENTER_NOTIFY
1761       || event->type == GDK_LEAVE_NOTIFY
1762       || event->type == GDK_BUTTON_PRESS
1763       || event->type == GDK_2BUTTON_PRESS
1764       || event->type == GDK_3BUTTON_PRESS
1765       || event->type == GDK_KEY_PRESS
1766       || event->type == GDK_DRAG_ENTER
1767       || event->type == GDK_GRAB_BROKEN
1768       || event->type == GDK_MOTION_NOTIFY
1769       || event->type == GDK_SCROLL)
1770     {
1771       _gtk_tooltip_handle_event (event);
1772     }
1773   
1774   tmp_list = current_events;
1775   current_events = g_list_remove_link (current_events, tmp_list);
1776   g_list_free_1 (tmp_list);
1777
1778   if (rewritten_event)
1779     gdk_event_free (rewritten_event);
1780 }
1781
1782 gboolean
1783 gtk_true (void)
1784 {
1785   return TRUE;
1786 }
1787
1788 gboolean
1789 gtk_false (void)
1790 {
1791   return FALSE;
1792 }
1793
1794 static GtkWindowGroup *
1795 gtk_main_get_window_group (GtkWidget   *widget)
1796 {
1797   GtkWidget *toplevel = NULL;
1798
1799   if (widget)
1800     toplevel = gtk_widget_get_toplevel (widget);
1801
1802   if (GTK_IS_WINDOW (toplevel))
1803     return gtk_window_get_group (GTK_WINDOW (toplevel));
1804   else
1805     return gtk_window_get_group (NULL);
1806 }
1807
1808 typedef struct
1809 {
1810   GtkWidget *old_grab_widget;
1811   GtkWidget *new_grab_widget;
1812   gboolean   was_grabbed;
1813   gboolean   is_grabbed;
1814   gboolean   from_grab;
1815   GList     *notified_windows;
1816   GdkDevice *device;
1817 } GrabNotifyInfo;
1818
1819 static void
1820 synth_crossing_for_grab_notify (GtkWidget       *from,
1821                                 GtkWidget       *to,
1822                                 GrabNotifyInfo  *info,
1823                                 GList           *devices,
1824                                 GdkCrossingMode  mode)
1825 {
1826   while (devices)
1827     {
1828       GdkDevice *device = devices->data;
1829       GdkWindow *from_window, *to_window;
1830
1831       /* Do not propagate events more than once to
1832        * the same windows if non-multidevice aware.
1833        */
1834       if (!from)
1835         from_window = NULL;
1836       else
1837         {
1838           from_window = _gtk_widget_get_device_window (from, device);
1839
1840           if (from_window &&
1841               !gdk_window_get_support_multidevice (from_window) &&
1842               g_list_find (info->notified_windows, from_window))
1843             from_window = NULL;
1844         }
1845
1846       if (!to)
1847         to_window = NULL;
1848       else
1849         {
1850           to_window = _gtk_widget_get_device_window (to, device);
1851
1852           if (to_window &&
1853               !gdk_window_get_support_multidevice (to_window) &&
1854               g_list_find (info->notified_windows, to_window))
1855             to_window = NULL;
1856         }
1857
1858       if (from_window || to_window)
1859         {
1860           _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1861                                            (to_window) ? to : NULL,
1862                                            device, mode);
1863
1864           if (from_window)
1865             info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1866
1867           if (to_window)
1868             info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1869         }
1870
1871       devices = devices->next;
1872     }
1873 }
1874
1875 static void
1876 gtk_grab_notify_foreach (GtkWidget *child,
1877                          gpointer   data)
1878 {
1879   GrabNotifyInfo *info = data;
1880   gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1881   GList *devices;
1882
1883   was_grabbed = info->was_grabbed;
1884   is_grabbed = info->is_grabbed;
1885
1886   info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1887   info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1888
1889   was_shadowed = info->old_grab_widget && !info->was_grabbed;
1890   is_shadowed = info->new_grab_widget && !info->is_grabbed;
1891
1892   g_object_ref (child);
1893
1894   if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1895     gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1896
1897   if (info->device &&
1898       _gtk_widget_get_device_window (child, info->device))
1899     {
1900       /* Device specified and is on widget */
1901       devices = g_list_prepend (NULL, info->device);
1902     }
1903   else
1904     devices = _gtk_widget_list_devices (child);
1905
1906   if (is_shadowed)
1907     {
1908       _gtk_widget_set_shadowed (child, TRUE);
1909       if (!was_shadowed && devices &&
1910           gtk_widget_is_sensitive (child))
1911         synth_crossing_for_grab_notify (child, info->new_grab_widget,
1912                                         info, devices,
1913                                         GDK_CROSSING_GTK_GRAB);
1914     }
1915   else
1916     {
1917       _gtk_widget_set_shadowed (child, FALSE);
1918       if (was_shadowed && devices &&
1919           gtk_widget_is_sensitive (child))
1920         synth_crossing_for_grab_notify (info->old_grab_widget, child,
1921                                         info, devices,
1922                                         info->from_grab ? GDK_CROSSING_GTK_GRAB :
1923                                         GDK_CROSSING_GTK_UNGRAB);
1924     }
1925
1926   if (was_shadowed != is_shadowed)
1927     _gtk_widget_grab_notify (child, was_shadowed);
1928
1929   g_object_unref (child);
1930   g_list_free (devices);
1931
1932   info->was_grabbed = was_grabbed;
1933   info->is_grabbed = is_grabbed;
1934 }
1935
1936 static void
1937 gtk_grab_notify (GtkWindowGroup *group,
1938                  GdkDevice      *device,
1939                  GtkWidget      *old_grab_widget,
1940                  GtkWidget      *new_grab_widget,
1941                  gboolean        from_grab)
1942 {
1943   GList *toplevels;
1944   GrabNotifyInfo info = { 0 };
1945
1946   if (old_grab_widget == new_grab_widget)
1947     return;
1948
1949   info.old_grab_widget = old_grab_widget;
1950   info.new_grab_widget = new_grab_widget;
1951   info.from_grab = from_grab;
1952   info.device = device;
1953
1954   g_object_ref (group);
1955
1956   toplevels = gtk_window_list_toplevels ();
1957   g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1958
1959   while (toplevels)
1960     {
1961       GtkWindow *toplevel = toplevels->data;
1962       toplevels = g_list_delete_link (toplevels, toplevels);
1963
1964       info.was_grabbed = FALSE;
1965       info.is_grabbed = FALSE;
1966
1967       if (group == gtk_window_get_group (toplevel))
1968         gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1969       g_object_unref (toplevel);
1970     }
1971
1972   g_list_free (info.notified_windows);
1973   g_object_unref (group);
1974 }
1975
1976 void
1977 gtk_grab_add (GtkWidget *widget)
1978 {
1979   GtkWindowGroup *group;
1980   GtkWidget *old_grab_widget;
1981   
1982   g_return_if_fail (widget != NULL);
1983   
1984   if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1985     {
1986       _gtk_widget_set_has_grab (widget, TRUE);
1987       
1988       group = gtk_main_get_window_group (widget);
1989
1990       if (group->grabs)
1991         old_grab_widget = (GtkWidget *)group->grabs->data;
1992       else
1993         old_grab_widget = NULL;
1994
1995       g_object_ref (widget);
1996       group->grabs = g_slist_prepend (group->grabs, widget);
1997
1998       gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1999     }
2000 }
2001
2002 /**
2003  * gtk_grab_get_current:
2004  *
2005  * Queries the current grab of the default window group.
2006  *
2007  * Return value: (transfer none): The widget which currently
2008  *     has the grab or %NULL if no grab is active
2009  */
2010 GtkWidget*
2011 gtk_grab_get_current (void)
2012 {
2013   GtkWindowGroup *group;
2014
2015   group = gtk_main_get_window_group (NULL);
2016
2017   if (group->grabs)
2018     return GTK_WIDGET (group->grabs->data);
2019   return NULL;
2020 }
2021
2022 void
2023 gtk_grab_remove (GtkWidget *widget)
2024 {
2025   GtkWindowGroup *group;
2026   GtkWidget *new_grab_widget;
2027   
2028   g_return_if_fail (widget != NULL);
2029   
2030   if (gtk_widget_has_grab (widget))
2031     {
2032       _gtk_widget_set_has_grab (widget, FALSE);
2033
2034       group = gtk_main_get_window_group (widget);
2035       group->grabs = g_slist_remove (group->grabs, widget);
2036       
2037       if (group->grabs)
2038         new_grab_widget = (GtkWidget *)group->grabs->data;
2039       else
2040         new_grab_widget = NULL;
2041
2042       gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2043       
2044       g_object_unref (widget);
2045     }
2046 }
2047
2048 /**
2049  * gtk_device_grab_add:
2050  * @widget: a #GtkWidget
2051  * @device: a #GtkDevice to grab on.
2052  * @block_others: %TRUE to prevent other devices to interact with @widget.
2053  *
2054  * Adds a GTK+ grab on @device, so all the events on @device and its
2055  * associated pointer or keyboard (if any) are delivered to @widget.
2056  * If the @block_others parameter is %TRUE, any other devices will be
2057  * unable to interact with @widget during the grab.
2058  *
2059  * Since: 3.0
2060  **/
2061 void
2062 gtk_device_grab_add (GtkWidget        *widget,
2063                      GdkDevice        *device,
2064                      gboolean          block_others)
2065 {
2066   GtkWindowGroup *group;
2067   GtkWidget *old_grab_widget;
2068
2069   g_return_if_fail (GTK_IS_WIDGET (widget));
2070   g_return_if_fail (GDK_IS_DEVICE (device));
2071
2072   group = gtk_main_get_window_group (widget);
2073   old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2074
2075   if (old_grab_widget != widget)
2076     _gtk_window_group_add_device_grab (group, widget, device, block_others);
2077
2078   gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2079 }
2080
2081 /**
2082  * gtk_device_grab_remove:
2083  * @widget: a #GtkWidget
2084  * @device: a #GdkDevice
2085  *
2086  * Removes a device grab from the given widget. You have to pair calls
2087  * to gtk_device_grab_add() and gtk_device_grab_remove().
2088  *
2089  * Since: 3.0
2090  **/
2091 void
2092 gtk_device_grab_remove (GtkWidget *widget,
2093                         GdkDevice *device)
2094 {
2095   GtkWindowGroup *group;
2096   GtkWidget *new_grab_widget;
2097
2098   g_return_if_fail (GTK_IS_WIDGET (widget));
2099   g_return_if_fail (GDK_IS_DEVICE (device));
2100
2101   group = gtk_main_get_window_group (widget);
2102   _gtk_window_group_remove_device_grab (group, widget, device);
2103   new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2104
2105   gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2106 }
2107
2108 guint
2109 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2110                          gpointer        func_data)
2111 {
2112   GtkKeySnooperData *data;
2113   static guint snooper_id = 1;
2114
2115   g_return_val_if_fail (snooper != NULL, 0);
2116
2117   data = g_new (GtkKeySnooperData, 1);
2118   data->func = snooper;
2119   data->func_data = func_data;
2120   data->id = snooper_id++;
2121   key_snoopers = g_slist_prepend (key_snoopers, data);
2122
2123   return data->id;
2124 }
2125
2126 void
2127 gtk_key_snooper_remove (guint snooper_id)
2128 {
2129   GtkKeySnooperData *data = NULL;
2130   GSList *slist;
2131
2132   slist = key_snoopers;
2133   while (slist)
2134     {
2135       data = slist->data;
2136       if (data->id == snooper_id)
2137         break;
2138
2139       slist = slist->next;
2140       data = NULL;
2141     }
2142   if (data)
2143     {
2144       key_snoopers = g_slist_remove (key_snoopers, data);
2145       g_free (data);
2146     }
2147 }
2148
2149 static gint
2150 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2151                          GdkEvent  *event)
2152 {
2153   GSList *slist;
2154   gint return_val = FALSE;
2155
2156   slist = key_snoopers;
2157   while (slist && !return_val)
2158     {
2159       GtkKeySnooperData *data;
2160
2161       data = slist->data;
2162       slist = slist->next;
2163       return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2164     }
2165
2166   return return_val;
2167 }
2168
2169 guint
2170 gtk_quit_add_full (guint                main_level,
2171                    GtkFunction          function,
2172                    GtkCallbackMarshal   marshal,
2173                    gpointer             data,
2174                    GDestroyNotify       destroy)
2175 {
2176   static guint quit_id = 1;
2177   GtkQuitFunction *quitf;
2178   
2179   g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2180
2181   quitf = g_slice_new (GtkQuitFunction);
2182   
2183   quitf->id = quit_id++;
2184   quitf->main_level = main_level;
2185   quitf->function = function;
2186   quitf->marshal = marshal;
2187   quitf->data = data;
2188   quitf->destroy = destroy;
2189
2190   quit_functions = g_list_prepend (quit_functions, quitf);
2191   
2192   return quitf->id;
2193 }
2194
2195 static void
2196 gtk_quit_destroy (GtkQuitFunction *quitf)
2197 {
2198   if (quitf->destroy)
2199     quitf->destroy (quitf->data);
2200   g_slice_free (GtkQuitFunction, quitf);
2201 }
2202
2203 static gint
2204 gtk_quit_destructor (GtkWidget **object_p)
2205 {
2206   if (*object_p)
2207     gtk_widget_destroy (*object_p);
2208   g_free (object_p);
2209
2210   return FALSE;
2211 }
2212
2213 void
2214 gtk_quit_add_destroy (guint      main_level,
2215                       GtkWidget *object)
2216 {
2217   GtkWidget **object_p;
2218
2219   g_return_if_fail (main_level > 0);
2220   g_return_if_fail (GTK_IS_WIDGET (object));
2221
2222   object_p = g_new (GtkWidget*, 1);
2223   *object_p = object;
2224   g_signal_connect (object,
2225                     "destroy",
2226                     G_CALLBACK (gtk_widget_destroyed),
2227                     object_p);
2228   gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2229 }
2230
2231 guint
2232 gtk_quit_add (guint       main_level,
2233               GtkFunction function,
2234               gpointer    data)
2235 {
2236   return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2237 }
2238
2239 void
2240 gtk_quit_remove (guint id)
2241 {
2242   GtkQuitFunction *quitf;
2243   GList *tmp_list;
2244   
2245   tmp_list = quit_functions;
2246   while (tmp_list)
2247     {
2248       quitf = tmp_list->data;
2249       
2250       if (quitf->id == id)
2251         {
2252           quit_functions = g_list_remove_link (quit_functions, tmp_list);
2253           g_list_free (tmp_list);
2254           gtk_quit_destroy (quitf);
2255           
2256           return;
2257         }
2258       
2259       tmp_list = tmp_list->next;
2260     }
2261 }
2262
2263 void
2264 gtk_quit_remove_by_data (gpointer data)
2265 {
2266   GtkQuitFunction *quitf;
2267   GList *tmp_list;
2268   
2269   tmp_list = quit_functions;
2270   while (tmp_list)
2271     {
2272       quitf = tmp_list->data;
2273       
2274       if (quitf->data == data)
2275         {
2276           quit_functions = g_list_remove_link (quit_functions, tmp_list);
2277           g_list_free (tmp_list);
2278           gtk_quit_destroy (quitf);
2279
2280           return;
2281         }
2282       
2283       tmp_list = tmp_list->next;
2284     }
2285 }
2286
2287 /**
2288  * gtk_get_current_event:
2289  * 
2290  * Obtains a copy of the event currently being processed by GTK+.  For
2291  * example, if you get a "clicked" signal from #GtkButton, the current
2292  * event will be the #GdkEventButton that triggered the "clicked"
2293  * signal. The returned event must be freed with gdk_event_free().
2294  * If there is no current event, the function returns %NULL.
2295  * 
2296  * Return value: a copy of the current event, or %NULL if no current event.
2297  **/
2298 GdkEvent*
2299 gtk_get_current_event (void)
2300 {
2301   if (current_events)
2302     return gdk_event_copy (current_events->data);
2303   else
2304     return NULL;
2305 }
2306
2307 /**
2308  * gtk_get_current_event_time:
2309  * 
2310  * If there is a current event and it has a timestamp, return that
2311  * timestamp, otherwise return %GDK_CURRENT_TIME.
2312  * 
2313  * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2314  **/
2315 guint32
2316 gtk_get_current_event_time (void)
2317 {
2318   if (current_events)
2319     return gdk_event_get_time (current_events->data);
2320   else
2321     return GDK_CURRENT_TIME;
2322 }
2323
2324 /**
2325  * gtk_get_current_event_state:
2326  * @state: a location to store the state of the current event
2327  * 
2328  * If there is a current event and it has a state field, place
2329  * that state field in @state and return %TRUE, otherwise return
2330  * %FALSE.
2331  * 
2332  * Return value: %TRUE if there was a current event and it had a state field
2333  **/
2334 gboolean
2335 gtk_get_current_event_state (GdkModifierType *state)
2336 {
2337   g_return_val_if_fail (state != NULL, FALSE);
2338   
2339   if (current_events)
2340     return gdk_event_get_state (current_events->data, state);
2341   else
2342     {
2343       *state = 0;
2344       return FALSE;
2345     }
2346 }
2347
2348 /**
2349  * gtk_get_current_event_device:
2350  *
2351  * If there is a current event and it has a device, return that
2352  * device, otherwise return %NULL.
2353  *
2354  * Returns: (transfer none): a #GdkDevice, or %NULL
2355  **/
2356 GdkDevice *
2357 gtk_get_current_event_device (void)
2358 {
2359   if (current_events)
2360     return gdk_event_get_device (current_events->data);
2361   else
2362     return NULL;
2363 }
2364
2365 /**
2366  * gtk_get_event_widget:
2367  * @event: a #GdkEvent
2368  *
2369  * If @event is %NULL or the event was not associated with any widget,
2370  * returns %NULL, otherwise returns the widget that received the event
2371  * originally.
2372  * 
2373  * Return value: (transfer none): the widget that originally
2374  *     received @event, or %NULL
2375  **/
2376 GtkWidget*
2377 gtk_get_event_widget (GdkEvent *event)
2378 {
2379   GtkWidget *widget;
2380   gpointer widget_ptr;
2381
2382   widget = NULL;
2383   if (event && event->any.window && 
2384       (event->type == GDK_DESTROY || !gdk_window_is_destroyed (event->any.window)))
2385     {
2386       gdk_window_get_user_data (event->any.window, &widget_ptr);
2387       widget = widget_ptr;
2388     }
2389   
2390   return widget;
2391 }
2392
2393 static gint
2394 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2395 {
2396   if (!quitf->marshal)
2397     return quitf->function (quitf->data);
2398   else
2399     {
2400       GtkArg args[1];
2401       gint ret_val = FALSE;
2402
2403       args[0].name = NULL;
2404       args[0].type = G_TYPE_BOOLEAN;
2405       args[0].d.pointer_data = &ret_val;
2406       ((GtkCallbackMarshal) quitf->marshal) (NULL,
2407                                              quitf->data,
2408                                              0, args);
2409       return ret_val;
2410     }
2411 }
2412
2413 /**
2414  * gtk_propagate_event:
2415  * @widget: a #GtkWidget
2416  * @event: an event
2417  *
2418  * Sends an event to a widget, propagating the event to parent widgets
2419  * if the event remains unhandled. Events received by GTK+ from GDK
2420  * normally begin in gtk_main_do_event(). Depending on the type of
2421  * event, existence of modal dialogs, grabs, etc., the event may be
2422  * propagated; if so, this function is used. gtk_propagate_event()
2423  * calls gtk_widget_event() on each widget it decides to send the
2424  * event to.  So gtk_widget_event() is the lowest-level function; it
2425  * simply emits the "event" and possibly an event-specific signal on a
2426  * widget.  gtk_propagate_event() is a bit higher-level, and
2427  * gtk_main_do_event() is the highest level.
2428  *
2429  * All that said, you most likely don't want to use any of these
2430  * functions; synthesizing events is rarely needed. Consider asking on
2431  * the mailing list for better ways to achieve your goals. For
2432  * example, use gdk_window_invalidate_rect() or
2433  * gtk_widget_queue_draw() instead of making up expose events.
2434  * 
2435  **/
2436 void
2437 gtk_propagate_event (GtkWidget *widget,
2438                      GdkEvent  *event)
2439 {
2440   gint handled_event;
2441   
2442   g_return_if_fail (GTK_IS_WIDGET (widget));
2443   g_return_if_fail (event != NULL);
2444   
2445   handled_event = FALSE;
2446
2447   g_object_ref (widget);
2448       
2449   if ((event->type == GDK_KEY_PRESS) ||
2450       (event->type == GDK_KEY_RELEASE))
2451     {
2452       /* Only send key events within Window widgets to the Window
2453        *  The Window widget will in turn pass the
2454        *  key event on to the currently focused widget
2455        *  for that window.
2456        */
2457       GtkWidget *window;
2458
2459       window = gtk_widget_get_toplevel (widget);
2460       if (GTK_IS_WINDOW (window))
2461         {
2462           /* If there is a grab within the window, give the grab widget
2463            * a first crack at the key event
2464            */
2465           if (widget != window && gtk_widget_has_grab (widget))
2466             handled_event = gtk_widget_event (widget, event);
2467           
2468           if (!handled_event)
2469             {
2470               window = gtk_widget_get_toplevel (widget);
2471               if (GTK_IS_WINDOW (window))
2472                 {
2473                   if (gtk_widget_is_sensitive (window))
2474                     gtk_widget_event (window, event);
2475                 }
2476             }
2477                   
2478           handled_event = TRUE; /* don't send to widget */
2479         }
2480     }
2481   
2482   /* Other events get propagated up the widget tree
2483    *  so that parents can see the button and motion
2484    *  events of the children.
2485    */
2486   if (!handled_event)
2487     {
2488       while (TRUE)
2489         {
2490           GtkWidget *tmp;
2491
2492           /* Scroll events are special cased here because it
2493            * feels wrong when scrolling a GtkViewport, say,
2494            * to have children of the viewport eat the scroll
2495            * event
2496            */
2497           if (!gtk_widget_is_sensitive (widget))
2498             handled_event = event->type != GDK_SCROLL;
2499           else
2500             handled_event = gtk_widget_event (widget, event);
2501
2502           tmp = gtk_widget_get_parent (widget);
2503           g_object_unref (widget);
2504
2505           widget = tmp;
2506           
2507           if (!handled_event && widget)
2508             g_object_ref (widget);
2509           else
2510             break;
2511         }
2512     }
2513   else
2514     g_object_unref (widget);
2515 }
2516
2517 gboolean
2518 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2519                                   GValue                *return_accu,
2520                                   const GValue          *handler_return,
2521                                   gpointer               dummy)
2522 {
2523   gboolean continue_emission;
2524   gboolean signal_handled;
2525   
2526   signal_handled = g_value_get_boolean (handler_return);
2527   g_value_set_boolean (return_accu, signal_handled);
2528   continue_emission = !signal_handled;
2529   
2530   return continue_emission;
2531 }