1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
42 #include <sys/types.h> /* For uid_t, gid_t */
52 #include "gtkaccelmap.h"
54 #include "gtkclipboard.h"
56 #include "gtkversion.h"
57 #include "gtkmodules.h"
59 #include "gtkrecentmanager.h"
60 #include "gtkselection.h"
61 #include "gtksettings.h"
62 #include "gtkwidgetprivate.h"
63 #include "gtkwindowprivate.h"
64 #include "gtktooltip.h"
70 static HMODULE gtk_dll;
73 DllMain (HINSTANCE hinstDLL,
79 case DLL_PROCESS_ATTACH:
80 gtk_dll = (HMODULE) hinstDLL;
87 /* These here before inclusion of gtkprivate.h so that the original
88 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
92 _gtk_get_libdir (void)
94 static char *gtk_libdir = NULL;
95 if (gtk_libdir == NULL)
97 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
98 gchar *slash = strrchr (root, '\\');
99 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
100 gtk_libdir = GTK_LIBDIR;
102 gtk_libdir = g_build_filename (root, "lib", NULL);
110 _gtk_get_localedir (void)
112 static char *gtk_localedir = NULL;
113 if (gtk_localedir == NULL)
118 /* GTK_LOCALEDIR ends in either /lib/locale or
119 * /share/locale. Scan for that slash.
121 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
127 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
128 temp = g_build_filename (root, p, NULL);
131 /* gtk_localedir is passed to bindtextdomain() which isn't
134 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
137 return gtk_localedir;
142 #include "gtkprivate.h"
144 /* Private type definitions
146 typedef struct _GtkQuitFunction GtkQuitFunction;
147 typedef struct _GtkKeySnooperData GtkKeySnooperData;
149 struct _GtkQuitFunction
153 GtkCallbackMarshal marshal;
154 GtkFunction function;
156 GDestroyNotify destroy;
159 struct _GtkKeySnooperData
161 GtkKeySnoopFunc func;
166 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
167 static void gtk_quit_destroy (GtkQuitFunction *quitf);
168 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
171 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
173 static guint gtk_main_loop_level = 0;
174 static gint pre_initialized = FALSE;
175 static gint gtk_initialized = FALSE;
176 static GList *current_events = NULL;
178 static GSList *main_loops = NULL; /* stack of currently executing main loops */
180 static GList *quit_functions = NULL; /* A list of quit functions.
182 static GSList *key_snoopers = NULL;
184 static guint debug_flags = 0; /* Global GTK debug flag */
186 #ifdef G_ENABLE_DEBUG
187 static const GDebugKey gtk_debug_keys[] = {
188 {"misc", GTK_DEBUG_MISC},
189 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
190 {"text", GTK_DEBUG_TEXT},
191 {"tree", GTK_DEBUG_TREE},
192 {"updates", GTK_DEBUG_UPDATES},
193 {"keybindings", GTK_DEBUG_KEYBINDINGS},
194 {"multihead", GTK_DEBUG_MULTIHEAD},
195 {"modules", GTK_DEBUG_MODULES},
196 {"geometry", GTK_DEBUG_GEOMETRY},
197 {"icontheme", GTK_DEBUG_ICONTHEME},
198 {"printing", GTK_DEBUG_PRINTING},
199 {"builder", GTK_DEBUG_BUILDER},
200 {"size-request", GTK_DEBUG_SIZE_REQUEST},
202 #endif /* G_ENABLE_DEBUG */
205 * gtk_get_major_version:
207 * Returns the major version number of the GTK+ library. (e.g. in GTK+ version
210 * This function is in the library, so it represents the GTK+ library
211 * your code is running against. Contrast with the #GTK_MAJOR_VERSION
212 * macro, which represents the major version of the GTK+ headers you
213 * have included when compiling your code.
215 * Returns: the major version number of the GTK+ library.
220 gtk_get_major_version (void)
222 return GTK_MAJOR_VERSION;
226 * gtk_get_minor_version:
228 * Returns the minor version number of the GTK+ library. (e.g. in GTK+ version
231 * This function is in the library, so it represents the GTK+ library
232 * your code is are running against. Contrast with the
233 * #GTK_MINOR_VERSION macro, which represents the minor version of the
234 * GTK+ headers you have included when compiling your code.
236 * Returns: the minor version number of the GTK+ library.
241 gtk_get_minor_version (void)
243 return GTK_MINOR_VERSION;
247 * gtk_get_micro_version:
249 * Returns the micro version number of the GTK+ library. (e.g. in GTK+ version
252 * This function is in the library, so it represents the GTK+ library
253 * your code is are running against. Contrast with the
254 * #GTK_MICRO_VERSION macro, which represents the micro version of the
255 * GTK+ headers you have included when compiling your code.
257 * Returns: the micro version number of the GTK+ library.
262 gtk_get_micro_version (void)
264 return GTK_MICRO_VERSION;
268 * gtk_get_binary_age:
270 * Returns the binary age as passed to
271 * <application>libtool</application> when building the GTK+ library
272 * the process is running against. If
273 * <application>libtool</application> means nothing to you, don't
276 * Returns: the binary age of the GTK+ library.
281 gtk_get_binary_age (void)
283 return GTK_BINARY_AGE;
287 * gtk_get_interface_age:
289 * Returns the interface age as passed to
290 * <application>libtool</application> when building the GTK+ library
291 * the process is running against. If
292 * <application>libtool</application> means nothing to you, don't
295 * Returns: the interface age of the GTK+ library.
300 gtk_get_interface_age (void)
302 return GTK_INTERFACE_AGE;
307 * @required_major: the required major version.
308 * @required_minor: the required minor version.
309 * @required_micro: the required micro version.
311 * Checks that the GTK+ library in use is compatible with the
312 * given version. Generally you would pass in the constants
313 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
314 * as the three arguments to this function; that produces
315 * a check that the library in use is compatible with
316 * the version of GTK+ the application or module was compiled
319 * Compatibility is defined by two things: first the version
320 * of the running library is newer than the version
321 * @required_major.required_minor.@required_micro. Second
322 * the running library must be binary compatible with the
323 * version @required_major.required_minor.@required_micro
324 * (same major version.)
326 * This function is primarily for GTK+ modules; the module
327 * can call this function to check that it wasn't loaded
328 * into an incompatible version of GTK+. However, such a
329 * check isn't completely reliable, since the module may be
330 * linked against an old version of GTK+ and calling the
331 * old version of gtk_check_version(), but still get loaded
332 * into an application using a newer version of GTK+.
334 * Return value: %NULL if the GTK+ library is compatible with the
335 * given version, or a string describing the version mismatch.
336 * The returned string is owned by GTK+ and should not be modified
340 gtk_check_version (guint required_major,
341 guint required_minor,
342 guint required_micro)
344 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
345 gint required_effective_micro = 100 * required_minor + required_micro;
347 if (required_major > GTK_MAJOR_VERSION)
348 return "Gtk+ version too old (major mismatch)";
349 if (required_major < GTK_MAJOR_VERSION)
350 return "Gtk+ version too new (major mismatch)";
351 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
352 return "Gtk+ version too new (micro mismatch)";
353 if (required_effective_micro > gtk_effective_micro)
354 return "Gtk+ version too old (micro mismatch)";
358 /* This checks to see if the process is running suid or sgid
359 * at the current time. If so, we don't allow GTK+ to be initialized.
360 * This is meant to be a mild check - we only error out if we
361 * can prove the programmer is doing something wrong, not if
362 * they could be doing something wrong. For this reason, we
363 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
368 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
370 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
371 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
373 #ifdef HAVE_GETRESUID
374 /* These aren't in the header files, so we prototype them here.
376 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
377 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
379 if (getresuid (&ruid, &euid, &suid) != 0 ||
380 getresgid (&rgid, &egid, &sgid) != 0)
381 #endif /* HAVE_GETRESUID */
383 suid = ruid = getuid ();
384 sgid = rgid = getgid ();
389 if (ruid != euid || ruid != suid ||
390 rgid != egid || rgid != sgid)
392 g_warning ("This process is currently running setuid or setgid.\n"
393 "This is not a supported use of GTK+. You must create a helper\n"
394 "program instead. For further details, see:\n\n"
395 " http://www.gtk.org/setuid.html\n\n"
396 "Refusing to initialize GTK+.");
406 _gtk_get_datadir (void)
408 static char *gtk_datadir = NULL;
409 if (gtk_datadir == NULL)
411 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
412 gtk_datadir = g_build_filename (root, "share", NULL);
420 _gtk_get_sysconfdir (void)
422 static char *gtk_sysconfdir = NULL;
423 if (gtk_sysconfdir == NULL)
425 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
426 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
430 return gtk_sysconfdir;
434 _gtk_get_data_prefix (void)
436 static char *gtk_data_prefix = NULL;
437 if (gtk_data_prefix == NULL)
438 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
440 return gtk_data_prefix;
443 #endif /* G_OS_WIN32 */
445 static gboolean do_setlocale = TRUE;
448 * gtk_disable_setlocale:
450 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
451 * gtk_parse_args() from automatically
452 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
453 * want to use this function if you wanted to set the locale for
454 * your program to something other than the user's locale, or if
455 * you wanted to set different values for different locale categories.
457 * Most programs should not need to call this function.
460 gtk_disable_setlocale (void)
463 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
465 do_setlocale = FALSE;
468 #ifdef G_PLATFORM_WIN32
469 #undef gtk_init_check
472 static GString *gtk_modules_string = NULL;
473 static gboolean g_fatal_warnings = FALSE;
475 #ifdef G_ENABLE_DEBUG
477 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
479 debug_flags |= g_parse_debug_string (value,
481 G_N_ELEMENTS (gtk_debug_keys));
487 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
489 debug_flags &= ~g_parse_debug_string (value,
491 G_N_ELEMENTS (gtk_debug_keys));
495 #endif /* G_ENABLE_DEBUG */
498 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
502 if (gtk_modules_string)
503 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
505 gtk_modules_string = g_string_new (NULL);
507 g_string_append (gtk_modules_string, value);
513 static const GOptionEntry gtk_args[] = {
514 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
515 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
516 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
517 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
518 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
519 #ifdef G_ENABLE_DEBUG
520 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
521 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
522 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
523 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
524 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
525 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
532 static char *iso639_to_check = NULL;
533 static char *iso3166_to_check = NULL;
534 static char *script_to_check = NULL;
535 static gboolean setlocale_called = FALSE;
538 enum_locale_proc (LPTSTR locale)
546 lcid = strtoul (locale, &endptr, 16);
547 if (*endptr == '\0' &&
548 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
549 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
551 if (strcmp (iso639, iso639_to_check) == 0 &&
552 ((iso3166_to_check != NULL &&
553 strcmp (iso3166, iso3166_to_check) == 0) ||
554 (iso3166_to_check == NULL &&
555 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
557 char language[100], country[100];
560 if (script_to_check != NULL)
562 /* If lcid is the "other" script for this language,
563 * return TRUE, i.e. continue looking.
565 if (strcmp (script_to_check, "Latn") == 0)
567 switch (LANGIDFROMLCID (lcid))
569 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
571 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
573 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
575 case MAKELANGID (LANG_SERBIAN, 0x07):
576 /* Serbian in Bosnia and Herzegovina, Cyrillic */
580 else if (strcmp (script_to_check, "Cyrl") == 0)
582 switch (LANGIDFROMLCID (lcid))
584 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
586 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
588 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
590 case MAKELANGID (LANG_SERBIAN, 0x06):
591 /* Serbian in Bosnia and Herzegovina, Latin */
597 SetThreadLocale (lcid);
599 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
600 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
602 strcpy (locale, language);
603 strcat (locale, "_");
604 strcat (locale, country);
606 if (setlocale (LC_ALL, locale) != NULL)
607 setlocale_called = TRUE;
620 setlocale_initialization (void)
622 static gboolean initialized = FALSE;
631 /* If some of the POSIXish environment variables are set, set
632 * the Win32 thread locale correspondingly.
634 char *p = getenv ("LC_ALL");
641 if (strcmp (p, "C") == 0)
642 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
645 /* Check if one of the supported locales match the
646 * environment variable. If so, use that locale.
649 iso3166_to_check = strchr (iso639_to_check, '_');
650 if (iso3166_to_check != NULL)
652 *iso3166_to_check++ = '\0';
654 script_to_check = strchr (iso3166_to_check, '@');
655 if (script_to_check != NULL)
656 *script_to_check++ = '\0';
658 /* Handle special cases. */
660 /* The standard code for Serbia and Montenegro was
661 * "CS", but MSFT uses for some reason "SP". By now
662 * (October 2006), SP has split into two, "RS" and
663 * "ME", but don't bother trying to handle those
664 * yet. Do handle the even older "YU", though.
666 if (strcmp (iso3166_to_check, "CS") == 0 ||
667 strcmp (iso3166_to_check, "YU") == 0)
668 iso3166_to_check = "SP";
672 script_to_check = strchr (iso639_to_check, '@');
673 if (script_to_check != NULL)
674 *script_to_check++ = '\0';
675 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
676 if (strcmp (iso639_to_check, "sr") == 0)
677 iso3166_to_check = "SP";
680 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
684 if (!setlocale_called)
685 setlocale (LC_ALL, "");
687 if (!setlocale (LC_ALL, ""))
688 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
694 check_mixed_deps (void)
699 module = g_module_open (NULL, 0);
701 if (g_module_symbol (module, "gtk_progress_get_type", &func))
703 g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
706 g_module_close (module);
710 do_pre_parse_initialization (int *argc,
713 const gchar *env_string;
718 pre_initialized = TRUE;
722 gdk_pre_parse_libgtk_only ();
723 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
725 #ifdef G_ENABLE_DEBUG
726 env_string = g_getenv ("GTK_DEBUG");
727 if (env_string != NULL)
729 debug_flags = g_parse_debug_string (env_string,
731 G_N_ELEMENTS (gtk_debug_keys));
734 #endif /* G_ENABLE_DEBUG */
736 env_string = g_getenv ("GTK_MODULES");
738 gtk_modules_string = g_string_new (env_string);
742 gettext_initialization (void)
744 setlocale_initialization ();
747 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
748 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
749 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
750 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
751 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
757 do_post_parse_initialization (int *argc,
763 gettext_initialization ();
766 signal (SIGPIPE, SIG_IGN);
769 if (g_fatal_warnings)
771 GLogLevelFlags fatal_mask;
773 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
774 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
775 g_log_set_always_fatal (fatal_mask);
778 if (debug_flags & GTK_DEBUG_UPDATES)
779 gdk_window_set_debug_updates (TRUE);
782 /* Translate to default:RTL if you want your widgets
783 * to be RTL, otherwise translate to default:LTR.
784 * Do *not* translate it to "predefinito:LTR", if it
785 * it isn't default:LTR or default:RTL it will not work
787 char *e = _("default:LTR");
788 if (strcmp (e, "default:RTL")==0)
789 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
790 else if (strcmp (e, "default:LTR"))
791 g_warning ("Whoever translated default:LTR did so wrongly.\n");
794 /* do what the call to gtk_type_init() used to do */
797 _gtk_accel_map_init ();
799 /* Set the 'initialized' flag.
801 gtk_initialized = TRUE;
803 /* load gtk modules */
804 if (gtk_modules_string)
806 _gtk_modules_init (argc, argv, gtk_modules_string->str);
807 g_string_free (gtk_modules_string, TRUE);
811 _gtk_modules_init (argc, argv, NULL);
818 gboolean open_default_display;
822 pre_parse_hook (GOptionContext *context,
827 do_pre_parse_initialization (NULL, NULL);
833 post_parse_hook (GOptionContext *context,
838 OptionGroupInfo *info = data;
841 do_post_parse_initialization (NULL, NULL);
843 if (info->open_default_display)
845 if (gdk_display_open_default_libgtk_only () == NULL)
847 const char *display_name = gdk_get_display_arg_name ();
850 G_OPTION_ERROR_FAILED,
851 _("Cannot open display: %s"),
852 display_name ? display_name : "" );
863 * gtk_get_debug_flags:
865 * Returns the GTK+ debug flags.
867 * This function is intended for GTK+ modules that want
868 * to adjust their debug output based on GTK+ debug flags.
870 * Returns: the GTK+ debug flags.
873 gtk_get_debug_flags (void)
879 * gtk_set_debug_flags:
881 * Sets the GTK+ debug flags.
884 gtk_set_debug_flags (guint flags)
890 * gtk_get_option_group:
891 * @open_default_display: whether to open the default display
892 * when parsing the commandline arguments
894 * Returns a #GOptionGroup for the commandline arguments recognized
895 * by GTK+ and GDK. You should add this group to your #GOptionContext
896 * with g_option_context_add_group(), if you are using
897 * g_option_context_parse() to parse your commandline arguments.
899 * Returns: a #GOptionGroup for the commandline arguments recognized
905 gtk_get_option_group (gboolean open_default_display)
908 OptionGroupInfo *info;
910 gettext_initialization ();
912 info = g_new0 (OptionGroupInfo, 1);
913 info->open_default_display = open_default_display;
915 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
916 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
918 gdk_add_option_entries_libgtk_only (group);
919 g_option_group_add_entries (group, gtk_args);
920 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
926 * gtk_init_with_args:
927 * @argc: a pointer to the number of command line arguments.
928 * @argv: a pointer to the array of command line arguments.
929 * @parameter_string: a string which is displayed in
930 * the first line of <option>--help</option> output, after
931 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
932 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
933 * describing the options of your program
934 * @translation_domain: a translation domain to use for translating
935 * the <option>--help</option> output for the options in @entries
936 * and the @parameter_string with gettext(), or %NULL
937 * @error: a return location for errors
939 * This function does the same work as gtk_init_check().
940 * Additionally, it allows you to add your own commandline options,
941 * and it automatically generates nicely formatted
942 * <option>--help</option> output. Note that your program will
943 * be terminated after writing out the help output.
945 * Returns: %TRUE if the GUI has been successfully initialized,
951 gtk_init_with_args (gint *argc,
953 const gchar *parameter_string,
954 const GOptionEntry *entries,
955 const gchar *translation_domain,
958 GOptionContext *context;
959 GOptionGroup *gtk_group;
963 return gdk_display_open_default_libgtk_only () != NULL;
965 gettext_initialization ();
967 if (!check_setugid ())
970 gtk_group = gtk_get_option_group (TRUE);
972 context = g_option_context_new (parameter_string);
973 g_option_context_add_group (context, gtk_group);
974 g_option_context_set_translation_domain (context, translation_domain);
977 g_option_context_add_main_entries (context, entries, translation_domain);
978 retval = g_option_context_parse (context, argc, argv, error);
980 g_option_context_free (context);
988 * @argc: (inout): a pointer to the number of command line arguments.
989 * @argv: (array) (inout): a pointer to the array of command line arguments.
991 * Parses command line arguments, and initializes global
992 * attributes of GTK+, but does not actually open a connection
993 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
995 * Any arguments used by GTK+ or GDK are removed from the array and
996 * @argc and @argv are updated accordingly.
998 * You shouldn't call this function explicitely if you are using
999 * gtk_init(), or gtk_init_check().
1001 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1004 gtk_parse_args (int *argc,
1007 GOptionContext *option_context;
1008 GOptionGroup *gtk_group;
1009 GError *error = NULL;
1011 if (gtk_initialized)
1014 gettext_initialization ();
1016 if (!check_setugid ())
1019 option_context = g_option_context_new (NULL);
1020 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1021 g_option_context_set_help_enabled (option_context, FALSE);
1022 gtk_group = gtk_get_option_group (FALSE);
1023 g_option_context_set_main_group (option_context, gtk_group);
1024 if (!g_option_context_parse (option_context, argc, argv, &error))
1026 g_warning ("%s", error->message);
1027 g_error_free (error);
1030 g_option_context_free (option_context);
1035 #ifdef G_PLATFORM_WIN32
1036 #undef gtk_init_check
1041 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1042 * main() function. Changed if any arguments were handled.
1043 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1044 * Any parameters understood by gtk_init() are stripped before return.
1046 * This function does the same work as gtk_init() with only
1047 * a single change: It does not terminate the program if the GUI can't be
1048 * initialized. Instead it returns %FALSE on failure.
1050 * This way the application can fall back to some other means of communication
1051 * with the user - for example a curses or command line interface.
1053 * Return value: %TRUE if the GUI has been successfully initialized,
1057 gtk_init_check (int *argc,
1060 if (!gtk_parse_args (argc, argv))
1063 return gdk_display_open_default_libgtk_only () != NULL;
1066 #ifdef G_PLATFORM_WIN32
1072 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1073 * main() function. Changed if any arguments were handled.
1074 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1075 * Any parameters understood by gtk_init() are stripped before return.
1077 * Call this function before using any other GTK+ functions in your GUI
1078 * applications. It will initialize everything needed to operate the
1079 * toolkit and parses some standard command line options. @argc and
1080 * @argv are adjusted accordingly so your own code will
1081 * never see those standard arguments.
1083 * Note that there are some alternative ways to initialize GTK+:
1084 * if you are calling gtk_parse_args(), gtk_init_check(),
1085 * gtk_init_with_args() or g_option_context_parse() with
1086 * the option group returned by gtk_get_option_group(), you
1087 * <emphasis>don't</emphasis> have to call gtk_init().
1090 * This function will terminate your program if it was unable to initialize
1091 * the GUI for some reason. If you want your program to fall back to a
1092 * textual interface you want to call gtk_init_check() instead.
1096 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1097 * during initialization, to ignore SIGPIPE signals, since these are
1098 * almost never wanted in graphical applications. If you do need to
1099 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1100 * but notice that other libraries (e.g. libdbus or gvfs) might do
1105 gtk_init (int *argc, char ***argv)
1107 if (!gtk_init_check (argc, argv))
1109 const char *display_name_arg = gdk_get_display_arg_name ();
1110 if (display_name_arg == NULL)
1111 display_name_arg = getenv("DISPLAY");
1112 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1117 #ifdef G_PLATFORM_WIN32
1120 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1122 if (sizeof_GtkWindow != sizeof (GtkWindow))
1123 g_error ("Incompatible build!\n"
1124 "The code using GTK+ thinks GtkWindow is of different\n"
1125 "size than it actually is in this build of GTK+.\n"
1126 "On Windows, this probably means that you have compiled\n"
1127 "your code with gcc without the -mms-bitfields switch,\n"
1128 "or that you are using an unsupported compiler.");
1131 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1132 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1133 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1134 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1135 * -fnative-struct still matters. GtkBox is one such.
1138 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1140 if (sizeof_GtkBox != sizeof (GtkBox))
1141 g_error ("Incompatible build!\n"
1142 "The code using GTK+ thinks GtkBox is of different\n"
1143 "size than it actually is in this build of GTK+.\n"
1144 "On Windows, this probably means that you have compiled\n"
1145 "your code with gcc without the -mms-bitfields switch,\n"
1146 "or that you are using an unsupported compiler.");
1149 /* These two functions might get more checks added later, thus pass
1150 * in the number of extra args.
1153 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1155 check_sizeof_GtkWindow (sizeof_GtkWindow);
1156 if (num_checks >= 2)
1157 check_sizeof_GtkBox (sizeof_GtkBox);
1158 gtk_init (argc, argv);
1162 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1164 check_sizeof_GtkWindow (sizeof_GtkWindow);
1165 if (num_checks >= 2)
1166 check_sizeof_GtkBox (sizeof_GtkBox);
1167 return gtk_init_check (argc, argv);
1175 * Initializes internationalization support for GTK+. gtk_init()
1176 * automatically does this, so there is typically no point
1177 * in calling this function.
1179 * If you are calling this function because you changed the locale
1180 * after GTK+ is was initialized, then calling this function
1181 * may help a bit. (Note, however, that changing the locale
1182 * after GTK+ is initialized may produce inconsistent results and
1183 * is not really supported.)
1185 * In detail - sets the current locale according to the
1186 * program environment. This is the same as calling the C library function
1187 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1188 * locale specific setup of the windowing system used by GDK.
1190 * Returns: a string corresponding to the locale set, typically in the
1191 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1192 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1193 * result of the setlocale(); it is also used on other machines, such as
1194 * Windows, where the C library returns a different result. The string is
1195 * owned by GTK+ and should not be modified or freed.
1198 gtk_set_locale (void)
1200 return gdk_set_locale ();
1204 * _gtk_get_lc_ctype:
1206 * Return the Unix-style locale string for the language currently in
1207 * effect. On Unix systems, this is the return value from
1208 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1209 * affect this through the environment variables LC_ALL, LC_CTYPE or
1210 * LANG (checked in that order). The locale strings typically is in
1211 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1212 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1213 * Swedish as written in Finland or pt_BR for Portuguese as written in
1216 * On Windows, the C library doesn't use any such environment
1217 * variables, and setting them won't affect the behaviour of functions
1218 * like ctime(). The user sets the locale through the Regional Options
1219 * in the Control Panel. The C library (in the setlocale() function)
1220 * does not use country and language codes, but country and language
1221 * names spelled out in English.
1222 * However, this function does check the above environment
1223 * variables, and does return a Unix-style locale string based on
1224 * either said environment variables or the thread's current locale.
1226 * Return value: a dynamically allocated string, free with g_free().
1230 _gtk_get_lc_ctype (void)
1233 /* Somebody might try to set the locale for this process using the
1234 * LANG or LC_ environment variables. The Microsoft C library
1235 * doesn't know anything about them. You set the locale in the
1236 * Control Panel. Setting these env vars won't have any affect on
1237 * locale-dependent C library functions like ctime(). But just for
1238 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1239 * it easier to test GTK and Pango in various default languages, you
1240 * don't have to clickety-click in the Control Panel, you can simply
1241 * start the program with LC_ALL=something on the command line.)
1245 p = getenv ("LC_ALL");
1247 return g_strdup (p);
1249 p = getenv ("LC_CTYPE");
1251 return g_strdup (p);
1253 p = getenv ("LANG");
1255 return g_strdup (p);
1257 return g_win32_getlocale ();
1259 return g_strdup (setlocale (LC_CTYPE, NULL));
1264 * gtk_get_default_language:
1266 * Returns the #PangoLanguage for the default language currently in
1267 * effect. (Note that this can change over the life of an
1268 * application.) The default language is derived from the current
1269 * locale. It determines, for example, whether GTK+ uses the
1270 * right-to-left or left-to-right text direction.
1272 * This function is equivalent to pango_language_get_default(). See
1273 * that function for details.
1275 * Return value: the default language as a #PangoLanguage, must not be
1279 gtk_get_default_language (void)
1281 return pango_language_get_default ();
1290 gtk_main_loop_level++;
1292 loop = g_main_loop_new (NULL, TRUE);
1293 main_loops = g_slist_prepend (main_loops, loop);
1295 if (g_main_loop_is_running (main_loops->data))
1297 GDK_THREADS_LEAVE ();
1298 g_main_loop_run (loop);
1299 GDK_THREADS_ENTER ();
1305 GList *reinvoke_list = NULL;
1306 GtkQuitFunction *quitf;
1308 while (quit_functions)
1310 quitf = quit_functions->data;
1312 tmp_list = quit_functions;
1313 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1314 g_list_free_1 (tmp_list);
1316 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1317 gtk_quit_invoke_function (quitf))
1319 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1323 gtk_quit_destroy (quitf);
1330 work = g_list_last (reinvoke_list);
1332 quit_functions->prev = work;
1333 work->next = quit_functions;
1334 quit_functions = work;
1340 main_loops = g_slist_remove (main_loops, loop);
1342 g_main_loop_unref (loop);
1344 gtk_main_loop_level--;
1346 if (gtk_main_loop_level == 0)
1348 /* Try storing all clipboard data we have */
1349 _gtk_clipboard_store_all ();
1351 /* Synchronize the recent manager singleton */
1352 _gtk_recent_manager_sync ();
1357 gtk_main_level (void)
1359 return gtk_main_loop_level;
1363 gtk_main_quit (void)
1365 g_return_if_fail (main_loops != NULL);
1367 g_main_loop_quit (main_loops->data);
1371 gtk_events_pending (void)
1375 GDK_THREADS_LEAVE ();
1376 result = g_main_context_pending (NULL);
1377 GDK_THREADS_ENTER ();
1383 gtk_main_iteration (void)
1385 GDK_THREADS_LEAVE ();
1386 g_main_context_iteration (NULL, TRUE);
1387 GDK_THREADS_ENTER ();
1390 return !g_main_loop_is_running (main_loops->data);
1396 gtk_main_iteration_do (gboolean blocking)
1398 GDK_THREADS_LEAVE ();
1399 g_main_context_iteration (NULL, blocking);
1400 GDK_THREADS_ENTER ();
1403 return !g_main_loop_is_running (main_loops->data);
1408 /* private libgtk to libgdk interfaces
1410 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1412 GdkWindow **grab_window,
1413 gboolean *owner_events);
1416 rewrite_events_translate (GdkWindow *old_window,
1417 GdkWindow *new_window,
1421 gint old_origin_x, old_origin_y;
1422 gint new_origin_x, new_origin_y;
1424 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1425 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1427 *x += old_origin_x - new_origin_x;
1428 *y += old_origin_y - new_origin_y;
1432 rewrite_event_for_window (GdkEvent *event,
1433 GdkWindow *new_window)
1435 event = gdk_event_copy (event);
1437 switch (event->type)
1440 rewrite_events_translate (event->any.window,
1442 &event->scroll.x, &event->scroll.y);
1444 case GDK_BUTTON_PRESS:
1445 case GDK_2BUTTON_PRESS:
1446 case GDK_3BUTTON_PRESS:
1447 case GDK_BUTTON_RELEASE:
1448 rewrite_events_translate (event->any.window,
1450 &event->button.x, &event->button.y);
1452 case GDK_MOTION_NOTIFY:
1453 rewrite_events_translate (event->any.window,
1455 &event->motion.x, &event->motion.y);
1458 case GDK_KEY_RELEASE:
1459 case GDK_PROXIMITY_IN:
1460 case GDK_PROXIMITY_OUT:
1467 g_object_unref (event->any.window);
1468 event->any.window = g_object_ref (new_window);
1473 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1474 * then what X11 does is deliver the event normally if it was going to this
1475 * client, otherwise, delivers it in terms of the grab window. This function
1476 * rewrites events to the effect that events going to the same window group
1477 * are delivered normally, otherwise, the event is delivered in terms of the
1481 rewrite_event_for_grabs (GdkEvent *event)
1483 GdkWindow *grab_window;
1484 GtkWidget *event_widget, *grab_widget;
1485 gpointer grab_widget_ptr;
1486 gboolean owner_events;
1487 GdkDisplay *display;
1490 switch (event->type)
1493 case GDK_BUTTON_PRESS:
1494 case GDK_2BUTTON_PRESS:
1495 case GDK_3BUTTON_PRESS:
1496 case GDK_BUTTON_RELEASE:
1497 case GDK_MOTION_NOTIFY:
1498 case GDK_PROXIMITY_IN:
1499 case GDK_PROXIMITY_OUT:
1501 case GDK_KEY_RELEASE:
1502 display = gdk_window_get_display (event->any.window);
1503 device = gdk_event_get_device (event);
1505 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1513 event_widget = gtk_get_event_widget (event);
1514 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1515 grab_widget = grab_widget_ptr;
1518 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1519 return rewrite_event_for_window (event, grab_window);
1525 gtk_main_do_event (GdkEvent *event)
1527 GtkWidget *event_widget;
1528 GtkWidget *grab_widget = NULL;
1529 GtkWindowGroup *window_group;
1530 GdkEvent *rewritten_event = NULL;
1534 if (event->type == GDK_SETTING)
1536 _gtk_settings_handle_event (&event->setting);
1540 if (event->type == GDK_OWNER_CHANGE)
1542 _gtk_clipboard_handle_event (&event->owner_change);
1546 /* Find the widget which got the event. We store the widget
1547 * in the user_data field of GdkWindow's.
1548 * Ignore the event if we don't have a widget for it, except
1549 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1550 * Though this happens rarely, bogus events can occour
1551 * for e.g. destroyed GdkWindows.
1553 event_widget = gtk_get_event_widget (event);
1556 /* To handle selection INCR transactions, we select
1557 * PropertyNotify events on the requestor window and create
1558 * a corresponding (fake) GdkWindow so that events get
1559 * here. There won't be a widget though, so we have to handle
1562 if (event->type == GDK_PROPERTY_NOTIFY)
1563 _gtk_selection_incr_event (event->any.window,
1569 /* If pointer or keyboard grabs are in effect, munge the events
1570 * so that each window group looks like a separate app.
1572 rewritten_event = rewrite_event_for_grabs (event);
1573 if (rewritten_event)
1575 event = rewritten_event;
1576 event_widget = gtk_get_event_widget (event);
1579 window_group = gtk_main_get_window_group (event_widget);
1580 device = gdk_event_get_device (event);
1582 /* check whether there is a (device) grab in effect...
1585 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1588 grab_widget = gtk_window_group_get_current_grab (window_group);
1590 /* If the grab widget is an ancestor of the event widget
1591 * then we send the event to the original event widget.
1592 * This is the key to implementing modality.
1595 (gtk_widget_is_sensitive (event_widget) &&
1596 gtk_widget_is_ancestor (event_widget, grab_widget)))
1597 grab_widget = event_widget;
1599 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1601 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1603 if (rewritten_event)
1604 gdk_event_free (rewritten_event);
1609 /* Push the event onto a stack of current events for
1610 * gtk_current_event_get().
1612 current_events = g_list_prepend (current_events, event);
1614 /* Not all events get sent to the grabbing widget.
1615 * The delete, destroy, expose, focus change and resize
1616 * events still get sent to the event widget because
1617 * 1) these events have no meaning for the grabbing widget
1618 * and 2) redirecting these events to the grabbing widget
1619 * could cause the display to be messed up.
1621 * Drag events are also not redirected, since it isn't
1622 * clear what the semantics of that would be.
1624 switch (event->type)
1630 g_object_ref (event_widget);
1631 if ((!gtk_window_group_get_current_grab (window_group) || gtk_widget_get_toplevel (gtk_window_group_get_current_grab (window_group)) == event_widget) &&
1632 !gtk_widget_event (event_widget, event))
1633 gtk_widget_destroy (event_widget);
1634 g_object_unref (event_widget);
1638 /* Unexpected GDK_DESTROY from the outside, ignore for
1639 * child windows, handle like a GDK_DELETE for toplevels
1641 if (!gtk_widget_get_parent (event_widget))
1643 g_object_ref (event_widget);
1644 if (!gtk_widget_event (event_widget, event) &&
1645 gtk_widget_get_realized (event_widget))
1646 gtk_widget_destroy (event_widget);
1647 g_object_unref (event_widget);
1652 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1654 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1655 gtk_widget_send_expose (event_widget, event);
1656 gdk_window_end_paint (event->any.window);
1660 /* The app may paint with a previously allocated cairo_t,
1661 which will draw directly to the window. We can't catch cairo
1662 draw operations to automatically flush the window, thus we
1663 need to explicitly flush any outstanding moves or double
1665 gdk_window_flush (event->any.window);
1666 gtk_widget_send_expose (event_widget, event);
1670 case GDK_PROPERTY_NOTIFY:
1671 case GDK_FOCUS_CHANGE:
1675 case GDK_SELECTION_CLEAR:
1676 case GDK_SELECTION_REQUEST:
1677 case GDK_SELECTION_NOTIFY:
1678 case GDK_CLIENT_EVENT:
1679 case GDK_VISIBILITY_NOTIFY:
1680 case GDK_WINDOW_STATE:
1681 case GDK_GRAB_BROKEN:
1683 gtk_widget_event (event_widget, event);
1687 case GDK_BUTTON_PRESS:
1688 case GDK_2BUTTON_PRESS:
1689 case GDK_3BUTTON_PRESS:
1690 gtk_propagate_event (grab_widget, event);
1694 case GDK_KEY_RELEASE:
1697 if (gtk_invoke_key_snoopers (grab_widget, event))
1700 /* Catch alt press to enable auto-mnemonics;
1701 * menus are handled elsewhere
1703 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1704 !GTK_IS_MENU_SHELL (grab_widget))
1706 gboolean auto_mnemonics;
1708 g_object_get (gtk_widget_get_settings (grab_widget),
1709 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1713 gboolean mnemonics_visible;
1716 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1718 window = gtk_widget_get_toplevel (grab_widget);
1720 if (GTK_IS_WINDOW (window))
1721 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1724 /* else fall through */
1725 case GDK_MOTION_NOTIFY:
1726 case GDK_BUTTON_RELEASE:
1727 case GDK_PROXIMITY_IN:
1728 case GDK_PROXIMITY_OUT:
1729 gtk_propagate_event (grab_widget, event);
1732 case GDK_ENTER_NOTIFY:
1733 _gtk_widget_set_device_window (event_widget,
1734 gdk_event_get_device (event),
1736 if (gtk_widget_is_sensitive (grab_widget))
1737 gtk_widget_event (grab_widget, event);
1740 case GDK_LEAVE_NOTIFY:
1741 _gtk_widget_set_device_window (event_widget,
1742 gdk_event_get_device (event),
1744 if (gtk_widget_is_sensitive (grab_widget))
1745 gtk_widget_event (grab_widget, event);
1748 case GDK_DRAG_STATUS:
1749 case GDK_DROP_FINISHED:
1750 _gtk_drag_source_handle_event (event_widget, event);
1752 case GDK_DRAG_ENTER:
1753 case GDK_DRAG_LEAVE:
1754 case GDK_DRAG_MOTION:
1755 case GDK_DROP_START:
1756 _gtk_drag_dest_handle_event (event_widget, event);
1759 g_assert_not_reached ();
1763 if (event->type == GDK_ENTER_NOTIFY
1764 || event->type == GDK_LEAVE_NOTIFY
1765 || event->type == GDK_BUTTON_PRESS
1766 || event->type == GDK_2BUTTON_PRESS
1767 || event->type == GDK_3BUTTON_PRESS
1768 || event->type == GDK_KEY_PRESS
1769 || event->type == GDK_DRAG_ENTER
1770 || event->type == GDK_GRAB_BROKEN
1771 || event->type == GDK_MOTION_NOTIFY
1772 || event->type == GDK_SCROLL)
1774 _gtk_tooltip_handle_event (event);
1777 tmp_list = current_events;
1778 current_events = g_list_remove_link (current_events, tmp_list);
1779 g_list_free_1 (tmp_list);
1781 if (rewritten_event)
1782 gdk_event_free (rewritten_event);
1797 static GtkWindowGroup *
1798 gtk_main_get_window_group (GtkWidget *widget)
1800 GtkWidget *toplevel = NULL;
1803 toplevel = gtk_widget_get_toplevel (widget);
1805 if (GTK_IS_WINDOW (toplevel))
1806 return gtk_window_get_group (GTK_WINDOW (toplevel));
1808 return gtk_window_get_group (NULL);
1813 GtkWidget *old_grab_widget;
1814 GtkWidget *new_grab_widget;
1815 gboolean was_grabbed;
1816 gboolean is_grabbed;
1818 GList *notified_windows;
1823 synth_crossing_for_grab_notify (GtkWidget *from,
1825 GrabNotifyInfo *info,
1827 GdkCrossingMode mode)
1831 GdkDevice *device = devices->data;
1832 GdkWindow *from_window, *to_window;
1834 /* Do not propagate events more than once to
1835 * the same windows if non-multidevice aware.
1841 from_window = _gtk_widget_get_device_window (from, device);
1844 !gdk_window_get_support_multidevice (from_window) &&
1845 g_list_find (info->notified_windows, from_window))
1853 to_window = _gtk_widget_get_device_window (to, device);
1856 !gdk_window_get_support_multidevice (to_window) &&
1857 g_list_find (info->notified_windows, to_window))
1861 if (from_window || to_window)
1863 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1864 (to_window) ? to : NULL,
1868 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1871 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1874 devices = devices->next;
1879 gtk_grab_notify_foreach (GtkWidget *child,
1882 GrabNotifyInfo *info = data;
1883 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1886 was_grabbed = info->was_grabbed;
1887 is_grabbed = info->is_grabbed;
1889 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1890 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1892 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1893 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1895 g_object_ref (child);
1897 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1898 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1901 _gtk_widget_get_device_window (child, info->device))
1903 /* Device specified and is on widget */
1904 devices = g_list_prepend (NULL, info->device);
1907 devices = _gtk_widget_list_devices (child);
1911 _gtk_widget_set_shadowed (child, TRUE);
1912 if (!was_shadowed && devices &&
1913 gtk_widget_is_sensitive (child))
1914 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1916 GDK_CROSSING_GTK_GRAB);
1920 _gtk_widget_set_shadowed (child, FALSE);
1921 if (was_shadowed && devices &&
1922 gtk_widget_is_sensitive (child))
1923 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1925 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1926 GDK_CROSSING_GTK_UNGRAB);
1929 if (was_shadowed != is_shadowed)
1930 _gtk_widget_grab_notify (child, was_shadowed);
1932 g_object_unref (child);
1933 g_list_free (devices);
1935 info->was_grabbed = was_grabbed;
1936 info->is_grabbed = is_grabbed;
1940 gtk_grab_notify (GtkWindowGroup *group,
1942 GtkWidget *old_grab_widget,
1943 GtkWidget *new_grab_widget,
1947 GrabNotifyInfo info = { 0 };
1949 if (old_grab_widget == new_grab_widget)
1952 info.old_grab_widget = old_grab_widget;
1953 info.new_grab_widget = new_grab_widget;
1954 info.from_grab = from_grab;
1955 info.device = device;
1957 g_object_ref (group);
1959 toplevels = gtk_window_list_toplevels ();
1960 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1964 GtkWindow *toplevel = toplevels->data;
1965 toplevels = g_list_delete_link (toplevels, toplevels);
1967 info.was_grabbed = FALSE;
1968 info.is_grabbed = FALSE;
1970 if (group == gtk_window_get_group (toplevel))
1971 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1972 g_object_unref (toplevel);
1975 g_list_free (info.notified_windows);
1976 g_object_unref (group);
1980 gtk_grab_add (GtkWidget *widget)
1982 GtkWindowGroup *group;
1983 GtkWidget *old_grab_widget;
1985 g_return_if_fail (widget != NULL);
1987 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1989 _gtk_widget_set_has_grab (widget, TRUE);
1991 group = gtk_main_get_window_group (widget);
1993 old_grab_widget = gtk_window_group_get_current_grab (group);
1995 g_object_ref (widget);
1996 _gtk_window_group_add_grab (group, widget);
1998 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
2003 * gtk_grab_get_current:
2005 * Queries the current grab of the default window group.
2007 * Return value: (transfer none): The widget which currently
2008 * has the grab or %NULL if no grab is active
2011 gtk_grab_get_current (void)
2013 GtkWindowGroup *group;
2015 group = gtk_main_get_window_group (NULL);
2017 return gtk_window_group_get_current_grab (group);
2021 gtk_grab_remove (GtkWidget *widget)
2023 GtkWindowGroup *group;
2024 GtkWidget *new_grab_widget;
2026 g_return_if_fail (widget != NULL);
2028 if (gtk_widget_has_grab (widget))
2030 _gtk_widget_set_has_grab (widget, FALSE);
2032 group = gtk_main_get_window_group (widget);
2033 _gtk_window_group_remove_grab (group, widget);
2034 new_grab_widget = gtk_window_group_get_current_grab (group);
2036 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2038 g_object_unref (widget);
2043 * gtk_device_grab_add:
2044 * @widget: a #GtkWidget
2045 * @device: a #GtkDevice to grab on.
2046 * @block_others: %TRUE to prevent other devices to interact with @widget.
2048 * Adds a GTK+ grab on @device, so all the events on @device and its
2049 * associated pointer or keyboard (if any) are delivered to @widget.
2050 * If the @block_others parameter is %TRUE, any other devices will be
2051 * unable to interact with @widget during the grab.
2056 gtk_device_grab_add (GtkWidget *widget,
2058 gboolean block_others)
2060 GtkWindowGroup *group;
2061 GtkWidget *old_grab_widget;
2063 g_return_if_fail (GTK_IS_WIDGET (widget));
2064 g_return_if_fail (GDK_IS_DEVICE (device));
2066 group = gtk_main_get_window_group (widget);
2067 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2069 if (old_grab_widget != widget)
2070 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2072 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2076 * gtk_device_grab_remove:
2077 * @widget: a #GtkWidget
2078 * @device: a #GdkDevice
2080 * Removes a device grab from the given widget. You have to pair calls
2081 * to gtk_device_grab_add() and gtk_device_grab_remove().
2086 gtk_device_grab_remove (GtkWidget *widget,
2089 GtkWindowGroup *group;
2090 GtkWidget *new_grab_widget;
2092 g_return_if_fail (GTK_IS_WIDGET (widget));
2093 g_return_if_fail (GDK_IS_DEVICE (device));
2095 group = gtk_main_get_window_group (widget);
2096 _gtk_window_group_remove_device_grab (group, widget, device);
2097 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2099 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2103 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2106 GtkKeySnooperData *data;
2107 static guint snooper_id = 1;
2109 g_return_val_if_fail (snooper != NULL, 0);
2111 data = g_new (GtkKeySnooperData, 1);
2112 data->func = snooper;
2113 data->func_data = func_data;
2114 data->id = snooper_id++;
2115 key_snoopers = g_slist_prepend (key_snoopers, data);
2121 gtk_key_snooper_remove (guint snooper_id)
2123 GtkKeySnooperData *data = NULL;
2126 slist = key_snoopers;
2130 if (data->id == snooper_id)
2133 slist = slist->next;
2138 key_snoopers = g_slist_remove (key_snoopers, data);
2144 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2148 gint return_val = FALSE;
2150 slist = key_snoopers;
2151 while (slist && !return_val)
2153 GtkKeySnooperData *data;
2156 slist = slist->next;
2157 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2164 gtk_quit_add_full (guint main_level,
2165 GtkFunction function,
2166 GtkCallbackMarshal marshal,
2168 GDestroyNotify destroy)
2170 static guint quit_id = 1;
2171 GtkQuitFunction *quitf;
2173 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2175 quitf = g_slice_new (GtkQuitFunction);
2177 quitf->id = quit_id++;
2178 quitf->main_level = main_level;
2179 quitf->function = function;
2180 quitf->marshal = marshal;
2182 quitf->destroy = destroy;
2184 quit_functions = g_list_prepend (quit_functions, quitf);
2190 gtk_quit_destroy (GtkQuitFunction *quitf)
2193 quitf->destroy (quitf->data);
2194 g_slice_free (GtkQuitFunction, quitf);
2198 gtk_quit_destructor (GtkWidget **object_p)
2201 gtk_widget_destroy (*object_p);
2208 gtk_quit_add_destroy (guint main_level,
2211 GtkWidget **object_p;
2213 g_return_if_fail (main_level > 0);
2214 g_return_if_fail (GTK_IS_WIDGET (object));
2216 object_p = g_new (GtkWidget*, 1);
2218 g_signal_connect (object,
2220 G_CALLBACK (gtk_widget_destroyed),
2222 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2226 gtk_quit_add (guint main_level,
2227 GtkFunction function,
2230 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2234 gtk_quit_remove (guint id)
2236 GtkQuitFunction *quitf;
2239 tmp_list = quit_functions;
2242 quitf = tmp_list->data;
2244 if (quitf->id == id)
2246 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2247 g_list_free (tmp_list);
2248 gtk_quit_destroy (quitf);
2253 tmp_list = tmp_list->next;
2258 gtk_quit_remove_by_data (gpointer data)
2260 GtkQuitFunction *quitf;
2263 tmp_list = quit_functions;
2266 quitf = tmp_list->data;
2268 if (quitf->data == data)
2270 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2271 g_list_free (tmp_list);
2272 gtk_quit_destroy (quitf);
2277 tmp_list = tmp_list->next;
2282 * gtk_get_current_event:
2284 * Obtains a copy of the event currently being processed by GTK+. For
2285 * example, if you get a "clicked" signal from #GtkButton, the current
2286 * event will be the #GdkEventButton that triggered the "clicked"
2287 * signal. The returned event must be freed with gdk_event_free().
2288 * If there is no current event, the function returns %NULL.
2290 * Return value: a copy of the current event, or %NULL if no current event.
2293 gtk_get_current_event (void)
2296 return gdk_event_copy (current_events->data);
2302 * gtk_get_current_event_time:
2304 * If there is a current event and it has a timestamp, return that
2305 * timestamp, otherwise return %GDK_CURRENT_TIME.
2307 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2310 gtk_get_current_event_time (void)
2313 return gdk_event_get_time (current_events->data);
2315 return GDK_CURRENT_TIME;
2319 * gtk_get_current_event_state:
2320 * @state: a location to store the state of the current event
2322 * If there is a current event and it has a state field, place
2323 * that state field in @state and return %TRUE, otherwise return
2326 * Return value: %TRUE if there was a current event and it had a state field
2329 gtk_get_current_event_state (GdkModifierType *state)
2331 g_return_val_if_fail (state != NULL, FALSE);
2334 return gdk_event_get_state (current_events->data, state);
2343 * gtk_get_current_event_device:
2345 * If there is a current event and it has a device, return that
2346 * device, otherwise return %NULL.
2348 * Returns: (transfer none): a #GdkDevice, or %NULL
2351 gtk_get_current_event_device (void)
2354 return gdk_event_get_device (current_events->data);
2360 * gtk_get_event_widget:
2361 * @event: a #GdkEvent
2363 * If @event is %NULL or the event was not associated with any widget,
2364 * returns %NULL, otherwise returns the widget that received the event
2367 * Return value: (transfer none): the widget that originally
2368 * received @event, or %NULL
2371 gtk_get_event_widget (GdkEvent *event)
2374 gpointer widget_ptr;
2377 if (event && event->any.window &&
2378 (event->type == GDK_DESTROY || !gdk_window_is_destroyed (event->any.window)))
2380 gdk_window_get_user_data (event->any.window, &widget_ptr);
2381 widget = widget_ptr;
2388 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2390 if (!quitf->marshal)
2391 return quitf->function (quitf->data);
2395 gint ret_val = FALSE;
2397 args[0].name = NULL;
2398 args[0].type = G_TYPE_BOOLEAN;
2399 args[0].d.pointer_data = &ret_val;
2400 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2408 * gtk_propagate_event:
2409 * @widget: a #GtkWidget
2412 * Sends an event to a widget, propagating the event to parent widgets
2413 * if the event remains unhandled. Events received by GTK+ from GDK
2414 * normally begin in gtk_main_do_event(). Depending on the type of
2415 * event, existence of modal dialogs, grabs, etc., the event may be
2416 * propagated; if so, this function is used. gtk_propagate_event()
2417 * calls gtk_widget_event() on each widget it decides to send the
2418 * event to. So gtk_widget_event() is the lowest-level function; it
2419 * simply emits the "event" and possibly an event-specific signal on a
2420 * widget. gtk_propagate_event() is a bit higher-level, and
2421 * gtk_main_do_event() is the highest level.
2423 * All that said, you most likely don't want to use any of these
2424 * functions; synthesizing events is rarely needed. Consider asking on
2425 * the mailing list for better ways to achieve your goals. For
2426 * example, use gdk_window_invalidate_rect() or
2427 * gtk_widget_queue_draw() instead of making up expose events.
2431 gtk_propagate_event (GtkWidget *widget,
2436 g_return_if_fail (GTK_IS_WIDGET (widget));
2437 g_return_if_fail (event != NULL);
2439 handled_event = FALSE;
2441 g_object_ref (widget);
2443 if ((event->type == GDK_KEY_PRESS) ||
2444 (event->type == GDK_KEY_RELEASE))
2446 /* Only send key events within Window widgets to the Window
2447 * The Window widget will in turn pass the
2448 * key event on to the currently focused widget
2453 window = gtk_widget_get_toplevel (widget);
2454 if (GTK_IS_WINDOW (window))
2456 /* If there is a grab within the window, give the grab widget
2457 * a first crack at the key event
2459 if (widget != window && gtk_widget_has_grab (widget))
2460 handled_event = gtk_widget_event (widget, event);
2464 window = gtk_widget_get_toplevel (widget);
2465 if (GTK_IS_WINDOW (window))
2467 if (gtk_widget_is_sensitive (window))
2468 gtk_widget_event (window, event);
2472 handled_event = TRUE; /* don't send to widget */
2476 /* Other events get propagated up the widget tree
2477 * so that parents can see the button and motion
2478 * events of the children.
2486 /* Scroll events are special cased here because it
2487 * feels wrong when scrolling a GtkViewport, say,
2488 * to have children of the viewport eat the scroll
2491 if (!gtk_widget_is_sensitive (widget))
2492 handled_event = event->type != GDK_SCROLL;
2494 handled_event = gtk_widget_event (widget, event);
2496 tmp = gtk_widget_get_parent (widget);
2497 g_object_unref (widget);
2501 if (!handled_event && widget)
2502 g_object_ref (widget);
2508 g_object_unref (widget);
2512 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2513 GValue *return_accu,
2514 const GValue *handler_return,
2517 gboolean continue_emission;
2518 gboolean signal_handled;
2520 signal_handled = g_value_get_boolean (handler_return);
2521 g_value_set_boolean (return_accu, signal_handled);
2522 continue_emission = !signal_handled;
2524 return continue_emission;