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);
1173 * _gtk_get_lc_ctype:
1175 * Return the Unix-style locale string for the language currently in
1176 * effect. On Unix systems, this is the return value from
1177 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1178 * affect this through the environment variables LC_ALL, LC_CTYPE or
1179 * LANG (checked in that order). The locale strings typically is in
1180 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1181 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1182 * Swedish as written in Finland or pt_BR for Portuguese as written in
1185 * On Windows, the C library doesn't use any such environment
1186 * variables, and setting them won't affect the behaviour of functions
1187 * like ctime(). The user sets the locale through the Regional Options
1188 * in the Control Panel. The C library (in the setlocale() function)
1189 * does not use country and language codes, but country and language
1190 * names spelled out in English.
1191 * However, this function does check the above environment
1192 * variables, and does return a Unix-style locale string based on
1193 * either said environment variables or the thread's current locale.
1195 * Return value: a dynamically allocated string, free with g_free().
1199 _gtk_get_lc_ctype (void)
1202 /* Somebody might try to set the locale for this process using the
1203 * LANG or LC_ environment variables. The Microsoft C library
1204 * doesn't know anything about them. You set the locale in the
1205 * Control Panel. Setting these env vars won't have any affect on
1206 * locale-dependent C library functions like ctime(). But just for
1207 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1208 * it easier to test GTK and Pango in various default languages, you
1209 * don't have to clickety-click in the Control Panel, you can simply
1210 * start the program with LC_ALL=something on the command line.)
1214 p = getenv ("LC_ALL");
1216 return g_strdup (p);
1218 p = getenv ("LC_CTYPE");
1220 return g_strdup (p);
1222 p = getenv ("LANG");
1224 return g_strdup (p);
1226 return g_win32_getlocale ();
1228 return g_strdup (setlocale (LC_CTYPE, NULL));
1233 * gtk_get_default_language:
1235 * Returns the #PangoLanguage for the default language currently in
1236 * effect. (Note that this can change over the life of an
1237 * application.) The default language is derived from the current
1238 * locale. It determines, for example, whether GTK+ uses the
1239 * right-to-left or left-to-right text direction.
1241 * This function is equivalent to pango_language_get_default(). See
1242 * that function for details.
1244 * Return value: the default language as a #PangoLanguage, must not be
1248 gtk_get_default_language (void)
1250 return pango_language_get_default ();
1259 gtk_main_loop_level++;
1261 loop = g_main_loop_new (NULL, TRUE);
1262 main_loops = g_slist_prepend (main_loops, loop);
1264 if (g_main_loop_is_running (main_loops->data))
1266 GDK_THREADS_LEAVE ();
1267 g_main_loop_run (loop);
1268 GDK_THREADS_ENTER ();
1274 GList *reinvoke_list = NULL;
1275 GtkQuitFunction *quitf;
1277 while (quit_functions)
1279 quitf = quit_functions->data;
1281 tmp_list = quit_functions;
1282 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1283 g_list_free_1 (tmp_list);
1285 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1286 gtk_quit_invoke_function (quitf))
1288 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1292 gtk_quit_destroy (quitf);
1299 work = g_list_last (reinvoke_list);
1301 quit_functions->prev = work;
1302 work->next = quit_functions;
1303 quit_functions = work;
1309 main_loops = g_slist_remove (main_loops, loop);
1311 g_main_loop_unref (loop);
1313 gtk_main_loop_level--;
1315 if (gtk_main_loop_level == 0)
1317 /* Try storing all clipboard data we have */
1318 _gtk_clipboard_store_all ();
1320 /* Synchronize the recent manager singleton */
1321 _gtk_recent_manager_sync ();
1326 gtk_main_level (void)
1328 return gtk_main_loop_level;
1332 gtk_main_quit (void)
1334 g_return_if_fail (main_loops != NULL);
1336 g_main_loop_quit (main_loops->data);
1340 gtk_events_pending (void)
1344 GDK_THREADS_LEAVE ();
1345 result = g_main_context_pending (NULL);
1346 GDK_THREADS_ENTER ();
1352 gtk_main_iteration (void)
1354 GDK_THREADS_LEAVE ();
1355 g_main_context_iteration (NULL, TRUE);
1356 GDK_THREADS_ENTER ();
1359 return !g_main_loop_is_running (main_loops->data);
1365 gtk_main_iteration_do (gboolean blocking)
1367 GDK_THREADS_LEAVE ();
1368 g_main_context_iteration (NULL, blocking);
1369 GDK_THREADS_ENTER ();
1372 return !g_main_loop_is_running (main_loops->data);
1377 /* private libgtk to libgdk interfaces
1379 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1381 GdkWindow **grab_window,
1382 gboolean *owner_events);
1385 rewrite_events_translate (GdkWindow *old_window,
1386 GdkWindow *new_window,
1390 gint old_origin_x, old_origin_y;
1391 gint new_origin_x, new_origin_y;
1393 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1394 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1396 *x += old_origin_x - new_origin_x;
1397 *y += old_origin_y - new_origin_y;
1401 rewrite_event_for_window (GdkEvent *event,
1402 GdkWindow *new_window)
1404 event = gdk_event_copy (event);
1406 switch (event->type)
1409 rewrite_events_translate (event->any.window,
1411 &event->scroll.x, &event->scroll.y);
1413 case GDK_BUTTON_PRESS:
1414 case GDK_2BUTTON_PRESS:
1415 case GDK_3BUTTON_PRESS:
1416 case GDK_BUTTON_RELEASE:
1417 rewrite_events_translate (event->any.window,
1419 &event->button.x, &event->button.y);
1421 case GDK_MOTION_NOTIFY:
1422 rewrite_events_translate (event->any.window,
1424 &event->motion.x, &event->motion.y);
1427 case GDK_KEY_RELEASE:
1428 case GDK_PROXIMITY_IN:
1429 case GDK_PROXIMITY_OUT:
1436 g_object_unref (event->any.window);
1437 event->any.window = g_object_ref (new_window);
1442 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1443 * then what X11 does is deliver the event normally if it was going to this
1444 * client, otherwise, delivers it in terms of the grab window. This function
1445 * rewrites events to the effect that events going to the same window group
1446 * are delivered normally, otherwise, the event is delivered in terms of the
1450 rewrite_event_for_grabs (GdkEvent *event)
1452 GdkWindow *grab_window;
1453 GtkWidget *event_widget, *grab_widget;
1454 gpointer grab_widget_ptr;
1455 gboolean owner_events;
1456 GdkDisplay *display;
1459 switch (event->type)
1462 case GDK_BUTTON_PRESS:
1463 case GDK_2BUTTON_PRESS:
1464 case GDK_3BUTTON_PRESS:
1465 case GDK_BUTTON_RELEASE:
1466 case GDK_MOTION_NOTIFY:
1467 case GDK_PROXIMITY_IN:
1468 case GDK_PROXIMITY_OUT:
1470 case GDK_KEY_RELEASE:
1471 display = gdk_window_get_display (event->any.window);
1472 device = gdk_event_get_device (event);
1474 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1482 event_widget = gtk_get_event_widget (event);
1483 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1484 grab_widget = grab_widget_ptr;
1487 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1488 return rewrite_event_for_window (event, grab_window);
1494 gtk_main_do_event (GdkEvent *event)
1496 GtkWidget *event_widget;
1497 GtkWidget *grab_widget = NULL;
1498 GtkWindowGroup *window_group;
1499 GdkEvent *rewritten_event = NULL;
1503 if (event->type == GDK_SETTING)
1505 _gtk_settings_handle_event (&event->setting);
1509 if (event->type == GDK_OWNER_CHANGE)
1511 _gtk_clipboard_handle_event (&event->owner_change);
1515 /* Find the widget which got the event. We store the widget
1516 * in the user_data field of GdkWindow's.
1517 * Ignore the event if we don't have a widget for it, except
1518 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1519 * Though this happens rarely, bogus events can occour
1520 * for e.g. destroyed GdkWindows.
1522 event_widget = gtk_get_event_widget (event);
1525 /* To handle selection INCR transactions, we select
1526 * PropertyNotify events on the requestor window and create
1527 * a corresponding (fake) GdkWindow so that events get
1528 * here. There won't be a widget though, so we have to handle
1531 if (event->type == GDK_PROPERTY_NOTIFY)
1532 _gtk_selection_incr_event (event->any.window,
1538 /* If pointer or keyboard grabs are in effect, munge the events
1539 * so that each window group looks like a separate app.
1541 rewritten_event = rewrite_event_for_grabs (event);
1542 if (rewritten_event)
1544 event = rewritten_event;
1545 event_widget = gtk_get_event_widget (event);
1548 window_group = gtk_main_get_window_group (event_widget);
1549 device = gdk_event_get_device (event);
1551 /* check whether there is a (device) grab in effect...
1554 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1557 grab_widget = gtk_window_group_get_current_grab (window_group);
1559 /* If the grab widget is an ancestor of the event widget
1560 * then we send the event to the original event widget.
1561 * This is the key to implementing modality.
1564 (gtk_widget_is_sensitive (event_widget) &&
1565 gtk_widget_is_ancestor (event_widget, grab_widget)))
1566 grab_widget = event_widget;
1568 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1570 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1572 if (rewritten_event)
1573 gdk_event_free (rewritten_event);
1578 /* Push the event onto a stack of current events for
1579 * gtk_current_event_get().
1581 current_events = g_list_prepend (current_events, event);
1583 /* Not all events get sent to the grabbing widget.
1584 * The delete, destroy, expose, focus change and resize
1585 * events still get sent to the event widget because
1586 * 1) these events have no meaning for the grabbing widget
1587 * and 2) redirecting these events to the grabbing widget
1588 * could cause the display to be messed up.
1590 * Drag events are also not redirected, since it isn't
1591 * clear what the semantics of that would be.
1593 switch (event->type)
1599 g_object_ref (event_widget);
1600 if ((!gtk_window_group_get_current_grab (window_group) || gtk_widget_get_toplevel (gtk_window_group_get_current_grab (window_group)) == event_widget) &&
1601 !gtk_widget_event (event_widget, event))
1602 gtk_widget_destroy (event_widget);
1603 g_object_unref (event_widget);
1607 /* Unexpected GDK_DESTROY from the outside, ignore for
1608 * child windows, handle like a GDK_DELETE for toplevels
1610 if (!gtk_widget_get_parent (event_widget))
1612 g_object_ref (event_widget);
1613 if (!gtk_widget_event (event_widget, event) &&
1614 gtk_widget_get_realized (event_widget))
1615 gtk_widget_destroy (event_widget);
1616 g_object_unref (event_widget);
1621 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1623 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1624 gtk_widget_send_expose (event_widget, event);
1625 gdk_window_end_paint (event->any.window);
1629 /* The app may paint with a previously allocated cairo_t,
1630 which will draw directly to the window. We can't catch cairo
1631 draw operations to automatically flush the window, thus we
1632 need to explicitly flush any outstanding moves or double
1634 gdk_window_flush (event->any.window);
1635 gtk_widget_send_expose (event_widget, event);
1639 case GDK_PROPERTY_NOTIFY:
1640 case GDK_FOCUS_CHANGE:
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:
1652 gtk_widget_event (event_widget, event);
1656 case GDK_BUTTON_PRESS:
1657 case GDK_2BUTTON_PRESS:
1658 case GDK_3BUTTON_PRESS:
1659 gtk_propagate_event (grab_widget, event);
1663 case GDK_KEY_RELEASE:
1666 if (gtk_invoke_key_snoopers (grab_widget, event))
1669 /* Catch alt press to enable auto-mnemonics;
1670 * menus are handled elsewhere
1672 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1673 !GTK_IS_MENU_SHELL (grab_widget))
1675 gboolean auto_mnemonics;
1677 g_object_get (gtk_widget_get_settings (grab_widget),
1678 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1682 gboolean mnemonics_visible;
1685 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1687 window = gtk_widget_get_toplevel (grab_widget);
1689 if (GTK_IS_WINDOW (window))
1690 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1693 /* else fall through */
1694 case GDK_MOTION_NOTIFY:
1695 case GDK_BUTTON_RELEASE:
1696 case GDK_PROXIMITY_IN:
1697 case GDK_PROXIMITY_OUT:
1698 gtk_propagate_event (grab_widget, event);
1701 case GDK_ENTER_NOTIFY:
1702 _gtk_widget_set_device_window (event_widget,
1703 gdk_event_get_device (event),
1705 if (gtk_widget_is_sensitive (grab_widget))
1706 gtk_widget_event (grab_widget, event);
1709 case GDK_LEAVE_NOTIFY:
1710 _gtk_widget_set_device_window (event_widget,
1711 gdk_event_get_device (event),
1713 if (gtk_widget_is_sensitive (grab_widget))
1714 gtk_widget_event (grab_widget, event);
1717 case GDK_DRAG_STATUS:
1718 case GDK_DROP_FINISHED:
1719 _gtk_drag_source_handle_event (event_widget, event);
1721 case GDK_DRAG_ENTER:
1722 case GDK_DRAG_LEAVE:
1723 case GDK_DRAG_MOTION:
1724 case GDK_DROP_START:
1725 _gtk_drag_dest_handle_event (event_widget, event);
1728 g_assert_not_reached ();
1732 if (event->type == GDK_ENTER_NOTIFY
1733 || event->type == GDK_LEAVE_NOTIFY
1734 || event->type == GDK_BUTTON_PRESS
1735 || event->type == GDK_2BUTTON_PRESS
1736 || event->type == GDK_3BUTTON_PRESS
1737 || event->type == GDK_KEY_PRESS
1738 || event->type == GDK_DRAG_ENTER
1739 || event->type == GDK_GRAB_BROKEN
1740 || event->type == GDK_MOTION_NOTIFY
1741 || event->type == GDK_SCROLL)
1743 _gtk_tooltip_handle_event (event);
1746 tmp_list = current_events;
1747 current_events = g_list_remove_link (current_events, tmp_list);
1748 g_list_free_1 (tmp_list);
1750 if (rewritten_event)
1751 gdk_event_free (rewritten_event);
1766 static GtkWindowGroup *
1767 gtk_main_get_window_group (GtkWidget *widget)
1769 GtkWidget *toplevel = NULL;
1772 toplevel = gtk_widget_get_toplevel (widget);
1774 if (GTK_IS_WINDOW (toplevel))
1775 return gtk_window_get_group (GTK_WINDOW (toplevel));
1777 return gtk_window_get_group (NULL);
1782 GtkWidget *old_grab_widget;
1783 GtkWidget *new_grab_widget;
1784 gboolean was_grabbed;
1785 gboolean is_grabbed;
1787 GList *notified_windows;
1792 synth_crossing_for_grab_notify (GtkWidget *from,
1794 GrabNotifyInfo *info,
1796 GdkCrossingMode mode)
1800 GdkDevice *device = devices->data;
1801 GdkWindow *from_window, *to_window;
1803 /* Do not propagate events more than once to
1804 * the same windows if non-multidevice aware.
1810 from_window = _gtk_widget_get_device_window (from, device);
1813 !gdk_window_get_support_multidevice (from_window) &&
1814 g_list_find (info->notified_windows, from_window))
1822 to_window = _gtk_widget_get_device_window (to, device);
1825 !gdk_window_get_support_multidevice (to_window) &&
1826 g_list_find (info->notified_windows, to_window))
1830 if (from_window || to_window)
1832 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1833 (to_window) ? to : NULL,
1837 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1840 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1843 devices = devices->next;
1848 gtk_grab_notify_foreach (GtkWidget *child,
1851 GrabNotifyInfo *info = data;
1852 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1855 was_grabbed = info->was_grabbed;
1856 is_grabbed = info->is_grabbed;
1858 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1859 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1861 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1862 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1864 g_object_ref (child);
1866 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1867 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1870 _gtk_widget_get_device_window (child, info->device))
1872 /* Device specified and is on widget */
1873 devices = g_list_prepend (NULL, info->device);
1876 devices = _gtk_widget_list_devices (child);
1880 _gtk_widget_set_shadowed (child, TRUE);
1881 if (!was_shadowed && devices &&
1882 gtk_widget_is_sensitive (child))
1883 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1885 GDK_CROSSING_GTK_GRAB);
1889 _gtk_widget_set_shadowed (child, FALSE);
1890 if (was_shadowed && devices &&
1891 gtk_widget_is_sensitive (child))
1892 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1894 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1895 GDK_CROSSING_GTK_UNGRAB);
1898 if (was_shadowed != is_shadowed)
1899 _gtk_widget_grab_notify (child, was_shadowed);
1901 g_object_unref (child);
1902 g_list_free (devices);
1904 info->was_grabbed = was_grabbed;
1905 info->is_grabbed = is_grabbed;
1909 gtk_grab_notify (GtkWindowGroup *group,
1911 GtkWidget *old_grab_widget,
1912 GtkWidget *new_grab_widget,
1916 GrabNotifyInfo info = { 0 };
1918 if (old_grab_widget == new_grab_widget)
1921 info.old_grab_widget = old_grab_widget;
1922 info.new_grab_widget = new_grab_widget;
1923 info.from_grab = from_grab;
1924 info.device = device;
1926 g_object_ref (group);
1928 toplevels = gtk_window_list_toplevels ();
1929 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1933 GtkWindow *toplevel = toplevels->data;
1934 toplevels = g_list_delete_link (toplevels, toplevels);
1936 info.was_grabbed = FALSE;
1937 info.is_grabbed = FALSE;
1939 if (group == gtk_window_get_group (toplevel))
1940 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1941 g_object_unref (toplevel);
1944 g_list_free (info.notified_windows);
1945 g_object_unref (group);
1949 gtk_grab_add (GtkWidget *widget)
1951 GtkWindowGroup *group;
1952 GtkWidget *old_grab_widget;
1954 g_return_if_fail (widget != NULL);
1956 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1958 _gtk_widget_set_has_grab (widget, TRUE);
1960 group = gtk_main_get_window_group (widget);
1962 old_grab_widget = gtk_window_group_get_current_grab (group);
1964 g_object_ref (widget);
1965 _gtk_window_group_add_grab (group, widget);
1967 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1972 * gtk_grab_get_current:
1974 * Queries the current grab of the default window group.
1976 * Return value: (transfer none): The widget which currently
1977 * has the grab or %NULL if no grab is active
1980 gtk_grab_get_current (void)
1982 GtkWindowGroup *group;
1984 group = gtk_main_get_window_group (NULL);
1986 return gtk_window_group_get_current_grab (group);
1990 gtk_grab_remove (GtkWidget *widget)
1992 GtkWindowGroup *group;
1993 GtkWidget *new_grab_widget;
1995 g_return_if_fail (widget != NULL);
1997 if (gtk_widget_has_grab (widget))
1999 _gtk_widget_set_has_grab (widget, FALSE);
2001 group = gtk_main_get_window_group (widget);
2002 _gtk_window_group_remove_grab (group, widget);
2003 new_grab_widget = gtk_window_group_get_current_grab (group);
2005 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2007 g_object_unref (widget);
2012 * gtk_device_grab_add:
2013 * @widget: a #GtkWidget
2014 * @device: a #GtkDevice to grab on.
2015 * @block_others: %TRUE to prevent other devices to interact with @widget.
2017 * Adds a GTK+ grab on @device, so all the events on @device and its
2018 * associated pointer or keyboard (if any) are delivered to @widget.
2019 * If the @block_others parameter is %TRUE, any other devices will be
2020 * unable to interact with @widget during the grab.
2025 gtk_device_grab_add (GtkWidget *widget,
2027 gboolean block_others)
2029 GtkWindowGroup *group;
2030 GtkWidget *old_grab_widget;
2032 g_return_if_fail (GTK_IS_WIDGET (widget));
2033 g_return_if_fail (GDK_IS_DEVICE (device));
2035 group = gtk_main_get_window_group (widget);
2036 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2038 if (old_grab_widget != widget)
2039 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2041 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2045 * gtk_device_grab_remove:
2046 * @widget: a #GtkWidget
2047 * @device: a #GdkDevice
2049 * Removes a device grab from the given widget. You have to pair calls
2050 * to gtk_device_grab_add() and gtk_device_grab_remove().
2055 gtk_device_grab_remove (GtkWidget *widget,
2058 GtkWindowGroup *group;
2059 GtkWidget *new_grab_widget;
2061 g_return_if_fail (GTK_IS_WIDGET (widget));
2062 g_return_if_fail (GDK_IS_DEVICE (device));
2064 group = gtk_main_get_window_group (widget);
2065 _gtk_window_group_remove_device_grab (group, widget, device);
2066 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2068 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2072 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2075 GtkKeySnooperData *data;
2076 static guint snooper_id = 1;
2078 g_return_val_if_fail (snooper != NULL, 0);
2080 data = g_new (GtkKeySnooperData, 1);
2081 data->func = snooper;
2082 data->func_data = func_data;
2083 data->id = snooper_id++;
2084 key_snoopers = g_slist_prepend (key_snoopers, data);
2090 gtk_key_snooper_remove (guint snooper_id)
2092 GtkKeySnooperData *data = NULL;
2095 slist = key_snoopers;
2099 if (data->id == snooper_id)
2102 slist = slist->next;
2107 key_snoopers = g_slist_remove (key_snoopers, data);
2113 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2117 gint return_val = FALSE;
2119 slist = key_snoopers;
2120 while (slist && !return_val)
2122 GtkKeySnooperData *data;
2125 slist = slist->next;
2126 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2133 gtk_quit_add_full (guint main_level,
2134 GtkFunction function,
2135 GtkCallbackMarshal marshal,
2137 GDestroyNotify destroy)
2139 static guint quit_id = 1;
2140 GtkQuitFunction *quitf;
2142 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2144 quitf = g_slice_new (GtkQuitFunction);
2146 quitf->id = quit_id++;
2147 quitf->main_level = main_level;
2148 quitf->function = function;
2149 quitf->marshal = marshal;
2151 quitf->destroy = destroy;
2153 quit_functions = g_list_prepend (quit_functions, quitf);
2159 gtk_quit_destroy (GtkQuitFunction *quitf)
2162 quitf->destroy (quitf->data);
2163 g_slice_free (GtkQuitFunction, quitf);
2167 gtk_quit_destructor (GtkWidget **object_p)
2170 gtk_widget_destroy (*object_p);
2177 gtk_quit_add_destroy (guint main_level,
2180 GtkWidget **object_p;
2182 g_return_if_fail (main_level > 0);
2183 g_return_if_fail (GTK_IS_WIDGET (object));
2185 object_p = g_new (GtkWidget*, 1);
2187 g_signal_connect (object,
2189 G_CALLBACK (gtk_widget_destroyed),
2191 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2195 gtk_quit_add (guint main_level,
2196 GtkFunction function,
2199 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2203 gtk_quit_remove (guint id)
2205 GtkQuitFunction *quitf;
2208 tmp_list = quit_functions;
2211 quitf = tmp_list->data;
2213 if (quitf->id == id)
2215 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2216 g_list_free (tmp_list);
2217 gtk_quit_destroy (quitf);
2222 tmp_list = tmp_list->next;
2227 gtk_quit_remove_by_data (gpointer data)
2229 GtkQuitFunction *quitf;
2232 tmp_list = quit_functions;
2235 quitf = tmp_list->data;
2237 if (quitf->data == data)
2239 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2240 g_list_free (tmp_list);
2241 gtk_quit_destroy (quitf);
2246 tmp_list = tmp_list->next;
2251 * gtk_get_current_event:
2253 * Obtains a copy of the event currently being processed by GTK+. For
2254 * example, if you get a "clicked" signal from #GtkButton, the current
2255 * event will be the #GdkEventButton that triggered the "clicked"
2256 * signal. The returned event must be freed with gdk_event_free().
2257 * If there is no current event, the function returns %NULL.
2259 * Return value: a copy of the current event, or %NULL if no current event.
2262 gtk_get_current_event (void)
2265 return gdk_event_copy (current_events->data);
2271 * gtk_get_current_event_time:
2273 * If there is a current event and it has a timestamp, return that
2274 * timestamp, otherwise return %GDK_CURRENT_TIME.
2276 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2279 gtk_get_current_event_time (void)
2282 return gdk_event_get_time (current_events->data);
2284 return GDK_CURRENT_TIME;
2288 * gtk_get_current_event_state:
2289 * @state: a location to store the state of the current event
2291 * If there is a current event and it has a state field, place
2292 * that state field in @state and return %TRUE, otherwise return
2295 * Return value: %TRUE if there was a current event and it had a state field
2298 gtk_get_current_event_state (GdkModifierType *state)
2300 g_return_val_if_fail (state != NULL, FALSE);
2303 return gdk_event_get_state (current_events->data, state);
2312 * gtk_get_current_event_device:
2314 * If there is a current event and it has a device, return that
2315 * device, otherwise return %NULL.
2317 * Returns: (transfer none): a #GdkDevice, or %NULL
2320 gtk_get_current_event_device (void)
2323 return gdk_event_get_device (current_events->data);
2329 * gtk_get_event_widget:
2330 * @event: a #GdkEvent
2332 * If @event is %NULL or the event was not associated with any widget,
2333 * returns %NULL, otherwise returns the widget that received the event
2336 * Return value: (transfer none): the widget that originally
2337 * received @event, or %NULL
2340 gtk_get_event_widget (GdkEvent *event)
2343 gpointer widget_ptr;
2346 if (event && event->any.window &&
2347 (event->type == GDK_DESTROY || !gdk_window_is_destroyed (event->any.window)))
2349 gdk_window_get_user_data (event->any.window, &widget_ptr);
2350 widget = widget_ptr;
2357 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2359 if (!quitf->marshal)
2360 return quitf->function (quitf->data);
2364 gint ret_val = FALSE;
2366 args[0].name = NULL;
2367 args[0].type = G_TYPE_BOOLEAN;
2368 args[0].d.pointer_data = &ret_val;
2369 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2377 * gtk_propagate_event:
2378 * @widget: a #GtkWidget
2381 * Sends an event to a widget, propagating the event to parent widgets
2382 * if the event remains unhandled. Events received by GTK+ from GDK
2383 * normally begin in gtk_main_do_event(). Depending on the type of
2384 * event, existence of modal dialogs, grabs, etc., the event may be
2385 * propagated; if so, this function is used. gtk_propagate_event()
2386 * calls gtk_widget_event() on each widget it decides to send the
2387 * event to. So gtk_widget_event() is the lowest-level function; it
2388 * simply emits the "event" and possibly an event-specific signal on a
2389 * widget. gtk_propagate_event() is a bit higher-level, and
2390 * gtk_main_do_event() is the highest level.
2392 * All that said, you most likely don't want to use any of these
2393 * functions; synthesizing events is rarely needed. Consider asking on
2394 * the mailing list for better ways to achieve your goals. For
2395 * example, use gdk_window_invalidate_rect() or
2396 * gtk_widget_queue_draw() instead of making up expose events.
2400 gtk_propagate_event (GtkWidget *widget,
2405 g_return_if_fail (GTK_IS_WIDGET (widget));
2406 g_return_if_fail (event != NULL);
2408 handled_event = FALSE;
2410 g_object_ref (widget);
2412 if ((event->type == GDK_KEY_PRESS) ||
2413 (event->type == GDK_KEY_RELEASE))
2415 /* Only send key events within Window widgets to the Window
2416 * The Window widget will in turn pass the
2417 * key event on to the currently focused widget
2422 window = gtk_widget_get_toplevel (widget);
2423 if (GTK_IS_WINDOW (window))
2425 /* If there is a grab within the window, give the grab widget
2426 * a first crack at the key event
2428 if (widget != window && gtk_widget_has_grab (widget))
2429 handled_event = gtk_widget_event (widget, event);
2433 window = gtk_widget_get_toplevel (widget);
2434 if (GTK_IS_WINDOW (window))
2436 if (gtk_widget_is_sensitive (window))
2437 gtk_widget_event (window, event);
2441 handled_event = TRUE; /* don't send to widget */
2445 /* Other events get propagated up the widget tree
2446 * so that parents can see the button and motion
2447 * events of the children.
2455 /* Scroll events are special cased here because it
2456 * feels wrong when scrolling a GtkViewport, say,
2457 * to have children of the viewport eat the scroll
2460 if (!gtk_widget_is_sensitive (widget))
2461 handled_event = event->type != GDK_SCROLL;
2463 handled_event = gtk_widget_event (widget, event);
2465 tmp = gtk_widget_get_parent (widget);
2466 g_object_unref (widget);
2470 if (!handled_event && widget)
2471 g_object_ref (widget);
2477 g_object_unref (widget);
2481 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2482 GValue *return_accu,
2483 const GValue *handler_return,
2486 gboolean continue_emission;
2487 gboolean signal_handled;
2489 signal_handled = g_value_get_boolean (handler_return);
2490 g_value_set_boolean (return_accu, signal_handled);
2491 continue_emission = !signal_handled;
2493 return continue_emission;