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