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/.
32 #include "gdkconfig.h"
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 "gtkwindow.h"
64 #include "gtktooltip.h"
67 #include "gdk/gdkkeysyms.h"
71 static HMODULE gtk_dll;
74 DllMain (HINSTANCE hinstDLL,
80 case DLL_PROCESS_ATTACH:
81 gtk_dll = (HMODULE) hinstDLL;
88 /* These here before inclusion of gtkprivate.h so that the original
89 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
93 _gtk_get_libdir (void)
95 static char *gtk_libdir = NULL;
96 if (gtk_libdir == NULL)
98 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
99 gchar *slash = strrchr (root, '\\');
100 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
101 gtk_libdir = GTK_LIBDIR;
103 gtk_libdir = g_build_filename (root, "lib", NULL);
111 _gtk_get_localedir (void)
113 static char *gtk_localedir = NULL;
114 if (gtk_localedir == NULL)
119 /* GTK_LOCALEDIR ends in either /lib/locale or
120 * /share/locale. Scan for that slash.
122 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
128 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
129 temp = g_build_filename (root, p, NULL);
132 /* gtk_localedir is passed to bindtextdomain() which isn't
135 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
138 return gtk_localedir;
143 #include "gtkprivate.h"
145 /* Private type definitions
147 typedef struct _GtkQuitFunction GtkQuitFunction;
148 typedef struct _GtkKeySnooperData GtkKeySnooperData;
150 struct _GtkQuitFunction
154 GtkCallbackMarshal marshal;
155 GtkFunction function;
157 GDestroyNotify destroy;
160 struct _GtkKeySnooperData
162 GtkKeySnoopFunc func;
167 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
168 static void gtk_quit_destroy (GtkQuitFunction *quitf);
169 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
172 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
174 static guint gtk_main_loop_level = 0;
175 static gint pre_initialized = FALSE;
176 static gint gtk_initialized = FALSE;
177 static GList *current_events = NULL;
179 static GSList *main_loops = NULL; /* stack of currently executing main loops */
181 static GList *quit_functions = NULL; /* A list of quit functions.
183 static GSList *key_snoopers = NULL;
185 static guint debug_flags = 0; /* Global GTK debug flag */
187 #ifdef G_ENABLE_DEBUG
188 static const GDebugKey gtk_debug_keys[] = {
189 {"misc", GTK_DEBUG_MISC},
190 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
191 {"text", GTK_DEBUG_TEXT},
192 {"tree", GTK_DEBUG_TREE},
193 {"updates", GTK_DEBUG_UPDATES},
194 {"keybindings", GTK_DEBUG_KEYBINDINGS},
195 {"multihead", GTK_DEBUG_MULTIHEAD},
196 {"modules", GTK_DEBUG_MODULES},
197 {"geometry", GTK_DEBUG_GEOMETRY},
198 {"icontheme", GTK_DEBUG_ICONTHEME},
199 {"printing", GTK_DEBUG_PRINTING},
200 {"builder", GTK_DEBUG_BUILDER},
201 {"size-request", GTK_DEBUG_SIZE_REQUEST},
203 #endif /* G_ENABLE_DEBUG */
206 * gtk_get_major_version:
208 * Returns the major version number of the GTK+ library. (e.g. in GTK+ version
211 * This function is in the library, so it represents the GTK+ library
212 * your code is running against. Contrast with the #GTK_MAJOR_VERSION
213 * macro, which represents the major version of the GTK+ headers you
214 * have included when compiling your code.
216 * Returns: the major version number of the GTK+ library.
221 gtk_get_major_version (void)
223 return GTK_MAJOR_VERSION;
227 * gtk_get_minor_version:
229 * Returns the minor version number of the GTK+ library. (e.g. in GTK+ version
232 * This function is in the library, so it represents the GTK+ library
233 * your code is are running against. Contrast with the
234 * #GTK_MINOR_VERSION macro, which represents the minor version of the
235 * GTK+ headers you have included when compiling your code.
237 * Returns: the minor version number of the GTK+ library.
242 gtk_get_minor_version (void)
244 return GTK_MINOR_VERSION;
248 * gtk_get_micro_version:
250 * Returns the micro version number of the GTK+ library. (e.g. in GTK+ version
253 * This function is in the library, so it represents the GTK+ library
254 * your code is are running against. Contrast with the
255 * #GTK_MICRO_VERSION macro, which represents the micro version of the
256 * GTK+ headers you have included when compiling your code.
258 * Returns: the micro version number of the GTK+ library.
263 gtk_get_micro_version (void)
265 return GTK_MICRO_VERSION;
269 * gtk_get_binary_age:
271 * Returns the binary age as passed to
272 * <application>libtool</application> when building the GTK+ library
273 * the process is running against. If
274 * <application>libtool</application> means nothing to you, don't
277 * Returns: the binary age of the GTK+ library.
282 gtk_get_binary_age (void)
284 return GTK_BINARY_AGE;
288 * gtk_get_interface_age:
290 * Returns the interface age as passed to
291 * <application>libtool</application> when building the GTK+ library
292 * the process is running against. If
293 * <application>libtool</application> means nothing to you, don't
296 * Returns: the interface age of the GTK+ library.
301 gtk_get_interface_age (void)
303 return GTK_INTERFACE_AGE;
308 * @required_major: the required major version.
309 * @required_minor: the required minor version.
310 * @required_micro: the required micro version.
312 * Checks that the GTK+ library in use is compatible with the
313 * given version. Generally you would pass in the constants
314 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
315 * as the three arguments to this function; that produces
316 * a check that the library in use is compatible with
317 * the version of GTK+ the application or module was compiled
320 * Compatibility is defined by two things: first the version
321 * of the running library is newer than the version
322 * @required_major.required_minor.@required_micro. Second
323 * the running library must be binary compatible with the
324 * version @required_major.required_minor.@required_micro
325 * (same major version.)
327 * This function is primarily for GTK+ modules; the module
328 * can call this function to check that it wasn't loaded
329 * into an incompatible version of GTK+. However, such a
330 * check isn't completely reliable, since the module may be
331 * linked against an old version of GTK+ and calling the
332 * old version of gtk_check_version(), but still get loaded
333 * into an application using a newer version of GTK+.
335 * Return value: %NULL if the GTK+ library is compatible with the
336 * given version, or a string describing the version mismatch.
337 * The returned string is owned by GTK+ and should not be modified
341 gtk_check_version (guint required_major,
342 guint required_minor,
343 guint required_micro)
345 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
346 gint required_effective_micro = 100 * required_minor + required_micro;
348 if (required_major > GTK_MAJOR_VERSION)
349 return "Gtk+ version too old (major mismatch)";
350 if (required_major < GTK_MAJOR_VERSION)
351 return "Gtk+ version too new (major mismatch)";
352 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
353 return "Gtk+ version too new (micro mismatch)";
354 if (required_effective_micro > gtk_effective_micro)
355 return "Gtk+ version too old (micro mismatch)";
359 /* This checks to see if the process is running suid or sgid
360 * at the current time. If so, we don't allow GTK+ to be initialized.
361 * This is meant to be a mild check - we only error out if we
362 * can prove the programmer is doing something wrong, not if
363 * they could be doing something wrong. For this reason, we
364 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
369 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
371 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
372 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
374 #ifdef HAVE_GETRESUID
375 /* These aren't in the header files, so we prototype them here.
377 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
378 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
380 if (getresuid (&ruid, &euid, &suid) != 0 ||
381 getresgid (&rgid, &egid, &sgid) != 0)
382 #endif /* HAVE_GETRESUID */
384 suid = ruid = getuid ();
385 sgid = rgid = getgid ();
390 if (ruid != euid || ruid != suid ||
391 rgid != egid || rgid != sgid)
393 g_warning ("This process is currently running setuid or setgid.\n"
394 "This is not a supported use of GTK+. You must create a helper\n"
395 "program instead. For further details, see:\n\n"
396 " http://www.gtk.org/setuid.html\n\n"
397 "Refusing to initialize GTK+.");
407 _gtk_get_datadir (void)
409 static char *gtk_datadir = NULL;
410 if (gtk_datadir == NULL)
412 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
413 gtk_datadir = g_build_filename (root, "share", NULL);
421 _gtk_get_sysconfdir (void)
423 static char *gtk_sysconfdir = NULL;
424 if (gtk_sysconfdir == NULL)
426 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
427 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
431 return gtk_sysconfdir;
435 _gtk_get_data_prefix (void)
437 static char *gtk_data_prefix = NULL;
438 if (gtk_data_prefix == NULL)
439 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
441 return gtk_data_prefix;
444 #endif /* G_OS_WIN32 */
446 static gboolean do_setlocale = TRUE;
449 * gtk_disable_setlocale:
451 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
452 * gtk_parse_args() from automatically
453 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
454 * want to use this function if you wanted to set the locale for
455 * your program to something other than the user's locale, or if
456 * you wanted to set different values for different locale categories.
458 * Most programs should not need to call this function.
461 gtk_disable_setlocale (void)
464 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
466 do_setlocale = FALSE;
469 #ifdef G_PLATFORM_WIN32
470 #undef gtk_init_check
473 static GString *gtk_modules_string = NULL;
474 static gboolean g_fatal_warnings = FALSE;
476 #ifdef G_ENABLE_DEBUG
478 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
480 debug_flags |= g_parse_debug_string (value,
482 G_N_ELEMENTS (gtk_debug_keys));
488 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
490 debug_flags &= ~g_parse_debug_string (value,
492 G_N_ELEMENTS (gtk_debug_keys));
496 #endif /* G_ENABLE_DEBUG */
499 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
503 if (gtk_modules_string)
504 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
506 gtk_modules_string = g_string_new (NULL);
508 g_string_append (gtk_modules_string, value);
514 static const GOptionEntry gtk_args[] = {
515 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
516 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
517 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
518 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
519 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
520 #ifdef G_ENABLE_DEBUG
521 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
522 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
523 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
524 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
525 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
526 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
533 static char *iso639_to_check = NULL;
534 static char *iso3166_to_check = NULL;
535 static char *script_to_check = NULL;
536 static gboolean setlocale_called = FALSE;
539 enum_locale_proc (LPTSTR locale)
547 lcid = strtoul (locale, &endptr, 16);
548 if (*endptr == '\0' &&
549 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
550 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
552 if (strcmp (iso639, iso639_to_check) == 0 &&
553 ((iso3166_to_check != NULL &&
554 strcmp (iso3166, iso3166_to_check) == 0) ||
555 (iso3166_to_check == NULL &&
556 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
558 char language[100], country[100];
561 if (script_to_check != NULL)
563 /* If lcid is the "other" script for this language,
564 * return TRUE, i.e. continue looking.
566 if (strcmp (script_to_check, "Latn") == 0)
568 switch (LANGIDFROMLCID (lcid))
570 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
572 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
574 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
576 case MAKELANGID (LANG_SERBIAN, 0x07):
577 /* Serbian in Bosnia and Herzegovina, Cyrillic */
581 else if (strcmp (script_to_check, "Cyrl") == 0)
583 switch (LANGIDFROMLCID (lcid))
585 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
587 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
589 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
591 case MAKELANGID (LANG_SERBIAN, 0x06):
592 /* Serbian in Bosnia and Herzegovina, Latin */
598 SetThreadLocale (lcid);
600 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
601 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
603 strcpy (locale, language);
604 strcat (locale, "_");
605 strcat (locale, country);
607 if (setlocale (LC_ALL, locale) != NULL)
608 setlocale_called = TRUE;
621 setlocale_initialization (void)
623 static gboolean initialized = FALSE;
632 /* If some of the POSIXish environment variables are set, set
633 * the Win32 thread locale correspondingly.
635 char *p = getenv ("LC_ALL");
642 if (strcmp (p, "C") == 0)
643 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
646 /* Check if one of the supported locales match the
647 * environment variable. If so, use that locale.
650 iso3166_to_check = strchr (iso639_to_check, '_');
651 if (iso3166_to_check != NULL)
653 *iso3166_to_check++ = '\0';
655 script_to_check = strchr (iso3166_to_check, '@');
656 if (script_to_check != NULL)
657 *script_to_check++ = '\0';
659 /* Handle special cases. */
661 /* The standard code for Serbia and Montenegro was
662 * "CS", but MSFT uses for some reason "SP". By now
663 * (October 2006), SP has split into two, "RS" and
664 * "ME", but don't bother trying to handle those
665 * yet. Do handle the even older "YU", though.
667 if (strcmp (iso3166_to_check, "CS") == 0 ||
668 strcmp (iso3166_to_check, "YU") == 0)
669 iso3166_to_check = "SP";
673 script_to_check = strchr (iso639_to_check, '@');
674 if (script_to_check != NULL)
675 *script_to_check++ = '\0';
676 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
677 if (strcmp (iso639_to_check, "sr") == 0)
678 iso3166_to_check = "SP";
681 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
685 if (!setlocale_called)
686 setlocale (LC_ALL, "");
688 if (!setlocale (LC_ALL, ""))
689 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
695 check_mixed_deps (void)
700 module = g_module_open (NULL, 0);
702 if (g_module_symbol (module, "gtk_progress_get_type", &func))
704 g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
707 g_module_close (module);
711 do_pre_parse_initialization (int *argc,
714 const gchar *env_string;
719 pre_initialized = TRUE;
723 gdk_pre_parse_libgtk_only ();
724 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
726 #ifdef G_ENABLE_DEBUG
727 env_string = g_getenv ("GTK_DEBUG");
728 if (env_string != NULL)
730 debug_flags = g_parse_debug_string (env_string,
732 G_N_ELEMENTS (gtk_debug_keys));
735 #endif /* G_ENABLE_DEBUG */
737 env_string = g_getenv ("GTK_MODULES");
739 gtk_modules_string = g_string_new (env_string);
743 gettext_initialization (void)
745 setlocale_initialization ();
748 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
749 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
750 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
751 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
752 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
758 do_post_parse_initialization (int *argc,
764 gettext_initialization ();
767 signal (SIGPIPE, SIG_IGN);
770 if (g_fatal_warnings)
772 GLogLevelFlags fatal_mask;
774 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
775 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
776 g_log_set_always_fatal (fatal_mask);
779 if (debug_flags & GTK_DEBUG_UPDATES)
780 gdk_window_set_debug_updates (TRUE);
783 /* Translate to default:RTL if you want your widgets
784 * to be RTL, otherwise translate to default:LTR.
785 * Do *not* translate it to "predefinito:LTR", if it
786 * it isn't default:LTR or default:RTL it will not work
788 char *e = _("default:LTR");
789 if (strcmp (e, "default:RTL")==0)
790 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
791 else if (strcmp (e, "default:LTR"))
792 g_warning ("Whoever translated default:LTR did so wrongly.\n");
795 /* do what the call to gtk_type_init() used to do */
798 _gtk_accel_map_init ();
801 /* Set the 'initialized' flag.
803 gtk_initialized = TRUE;
805 /* load gtk modules */
806 if (gtk_modules_string)
808 _gtk_modules_init (argc, argv, gtk_modules_string->str);
809 g_string_free (gtk_modules_string, TRUE);
813 _gtk_modules_init (argc, argv, NULL);
820 gboolean open_default_display;
824 pre_parse_hook (GOptionContext *context,
829 do_pre_parse_initialization (NULL, NULL);
835 post_parse_hook (GOptionContext *context,
840 OptionGroupInfo *info = data;
843 do_post_parse_initialization (NULL, NULL);
845 if (info->open_default_display)
847 if (gdk_display_open_default_libgtk_only () == NULL)
849 const char *display_name = gdk_get_display_arg_name ();
852 G_OPTION_ERROR_FAILED,
853 _("Cannot open display: %s"),
854 display_name ? display_name : "" );
865 * gtk_get_debug_flags:
867 * Returns the GTK+ debug flags setting.
870 gtk_get_debug_flags (void)
876 * gtk_set_debug_flags:
878 * Sets the GTK+ debug flags.
881 gtk_set_debug_flags (guint flags)
887 * gtk_get_option_group:
888 * @open_default_display: whether to open the default display
889 * when parsing the commandline arguments
891 * Returns a #GOptionGroup for the commandline arguments recognized
892 * by GTK+ and GDK. You should add this group to your #GOptionContext
893 * with g_option_context_add_group(), if you are using
894 * g_option_context_parse() to parse your commandline arguments.
896 * Returns: a #GOptionGroup for the commandline arguments recognized
902 gtk_get_option_group (gboolean open_default_display)
905 OptionGroupInfo *info;
907 gettext_initialization ();
909 info = g_new0 (OptionGroupInfo, 1);
910 info->open_default_display = open_default_display;
912 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
913 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
915 gdk_add_option_entries_libgtk_only (group);
916 g_option_group_add_entries (group, gtk_args);
917 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
923 * gtk_init_with_args:
924 * @argc: a pointer to the number of command line arguments.
925 * @argv: a pointer to the array of command line arguments.
926 * @parameter_string: a string which is displayed in
927 * the first line of <option>--help</option> output, after
928 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
929 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
930 * describing the options of your program
931 * @translation_domain: a translation domain to use for translating
932 * the <option>--help</option> output for the options in @entries
933 * and the @parameter_string with gettext(), or %NULL
934 * @error: a return location for errors
936 * This function does the same work as gtk_init_check().
937 * Additionally, it allows you to add your own commandline options,
938 * and it automatically generates nicely formatted
939 * <option>--help</option> output. Note that your program will
940 * be terminated after writing out the help output.
942 * Returns: %TRUE if the GUI has been successfully initialized,
948 gtk_init_with_args (gint *argc,
950 const gchar *parameter_string,
951 const GOptionEntry *entries,
952 const gchar *translation_domain,
955 GOptionContext *context;
956 GOptionGroup *gtk_group;
960 return gdk_display_open_default_libgtk_only () != NULL;
962 gettext_initialization ();
964 if (!check_setugid ())
967 gtk_group = gtk_get_option_group (TRUE);
969 context = g_option_context_new (parameter_string);
970 g_option_context_add_group (context, gtk_group);
971 g_option_context_set_translation_domain (context, translation_domain);
974 g_option_context_add_main_entries (context, entries, translation_domain);
975 retval = g_option_context_parse (context, argc, argv, error);
977 g_option_context_free (context);
985 * @argc: (inout): a pointer to the number of command line arguments.
986 * @argv: (array) (inout): a pointer to the array of command line arguments.
988 * Parses command line arguments, and initializes global
989 * attributes of GTK+, but does not actually open a connection
990 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
992 * Any arguments used by GTK+ or GDK are removed from the array and
993 * @argc and @argv are updated accordingly.
995 * You shouldn't call this function explicitely if you are using
996 * gtk_init(), or gtk_init_check().
998 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1001 gtk_parse_args (int *argc,
1004 GOptionContext *option_context;
1005 GOptionGroup *gtk_group;
1006 GError *error = NULL;
1008 if (gtk_initialized)
1011 gettext_initialization ();
1013 if (!check_setugid ())
1016 option_context = g_option_context_new (NULL);
1017 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1018 g_option_context_set_help_enabled (option_context, FALSE);
1019 gtk_group = gtk_get_option_group (FALSE);
1020 g_option_context_set_main_group (option_context, gtk_group);
1021 if (!g_option_context_parse (option_context, argc, argv, &error))
1023 g_warning ("%s", error->message);
1024 g_error_free (error);
1027 g_option_context_free (option_context);
1032 #ifdef G_PLATFORM_WIN32
1033 #undef gtk_init_check
1038 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1039 * main() function. Changed if any arguments were handled.
1040 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1041 * Any parameters understood by gtk_init() are stripped before return.
1043 * This function does the same work as gtk_init() with only
1044 * a single change: It does not terminate the program if the GUI can't be
1045 * initialized. Instead it returns %FALSE on failure.
1047 * This way the application can fall back to some other means of communication
1048 * with the user - for example a curses or command line interface.
1050 * Return value: %TRUE if the GUI has been successfully initialized,
1054 gtk_init_check (int *argc,
1057 if (!gtk_parse_args (argc, argv))
1060 return gdk_display_open_default_libgtk_only () != NULL;
1063 #ifdef G_PLATFORM_WIN32
1069 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1070 * main() function. Changed if any arguments were handled.
1071 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1072 * Any parameters understood by gtk_init() are stripped before return.
1074 * Call this function before using any other GTK+ functions in your GUI
1075 * applications. It will initialize everything needed to operate the
1076 * toolkit and parses some standard command line options. @argc and
1077 * @argv are adjusted accordingly so your own code will
1078 * never see those standard arguments.
1080 * Note that there are some alternative ways to initialize GTK+:
1081 * if you are calling gtk_parse_args(), gtk_init_check(),
1082 * gtk_init_with_args() or g_option_context_parse() with
1083 * the option group returned by gtk_get_option_group(), you
1084 * <emphasis>don't</emphasis> have to call gtk_init().
1087 * This function will terminate your program if it was unable to initialize
1088 * the GUI for some reason. If you want your program to fall back to a
1089 * textual interface you want to call gtk_init_check() instead.
1093 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1094 * during initialization, to ignore SIGPIPE signals, since these are
1095 * almost never wanted in graphical applications. If you do need to
1096 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1097 * but notice that other libraries (e.g. libdbus or gvfs) might do
1102 gtk_init (int *argc, char ***argv)
1104 if (!gtk_init_check (argc, argv))
1106 const char *display_name_arg = gdk_get_display_arg_name ();
1107 if (display_name_arg == NULL)
1108 display_name_arg = getenv("DISPLAY");
1109 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1114 #ifdef G_PLATFORM_WIN32
1117 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1119 if (sizeof_GtkWindow != sizeof (GtkWindow))
1120 g_error ("Incompatible build!\n"
1121 "The code using GTK+ thinks GtkWindow is of different\n"
1122 "size than it actually is in this build of GTK+.\n"
1123 "On Windows, this probably means that you have compiled\n"
1124 "your code with gcc without the -mms-bitfields switch,\n"
1125 "or that you are using an unsupported compiler.");
1128 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1129 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1130 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1131 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1132 * -fnative-struct still matters. GtkBox is one such.
1135 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1137 if (sizeof_GtkBox != sizeof (GtkBox))
1138 g_error ("Incompatible build!\n"
1139 "The code using GTK+ thinks GtkBox is of different\n"
1140 "size than it actually is in this build of GTK+.\n"
1141 "On Windows, this probably means that you have compiled\n"
1142 "your code with gcc without the -mms-bitfields switch,\n"
1143 "or that you are using an unsupported compiler.");
1146 /* These two functions might get more checks added later, thus pass
1147 * in the number of extra args.
1150 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1152 check_sizeof_GtkWindow (sizeof_GtkWindow);
1153 if (num_checks >= 2)
1154 check_sizeof_GtkBox (sizeof_GtkBox);
1155 gtk_init (argc, argv);
1159 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1161 check_sizeof_GtkWindow (sizeof_GtkWindow);
1162 if (num_checks >= 2)
1163 check_sizeof_GtkBox (sizeof_GtkBox);
1164 return gtk_init_check (argc, argv);
1172 * Initializes internationalization support for GTK+. gtk_init()
1173 * automatically does this, so there is typically no point
1174 * in calling this function.
1176 * If you are calling this function because you changed the locale
1177 * after GTK+ is was initialized, then calling this function
1178 * may help a bit. (Note, however, that changing the locale
1179 * after GTK+ is initialized may produce inconsistent results and
1180 * is not really supported.)
1182 * In detail - sets the current locale according to the
1183 * program environment. This is the same as calling the C library function
1184 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1185 * locale specific setup of the windowing system used by GDK.
1187 * Returns: a string corresponding to the locale set, typically in the
1188 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1189 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1190 * result of the setlocale(); it is also used on other machines, such as
1191 * Windows, where the C library returns a different result. The string is
1192 * owned by GTK+ and should not be modified or freed.
1195 gtk_set_locale (void)
1197 return gdk_set_locale ();
1201 * _gtk_get_lc_ctype:
1203 * Return the Unix-style locale string for the language currently in
1204 * effect. On Unix systems, this is the return value from
1205 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1206 * affect this through the environment variables LC_ALL, LC_CTYPE or
1207 * LANG (checked in that order). The locale strings typically is in
1208 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1209 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1210 * Swedish as written in Finland or pt_BR for Portuguese as written in
1213 * On Windows, the C library doesn't use any such environment
1214 * variables, and setting them won't affect the behaviour of functions
1215 * like ctime(). The user sets the locale through the Regional Options
1216 * in the Control Panel. The C library (in the setlocale() function)
1217 * does not use country and language codes, but country and language
1218 * names spelled out in English.
1219 * However, this function does check the above environment
1220 * variables, and does return a Unix-style locale string based on
1221 * either said environment variables or the thread's current locale.
1223 * Return value: a dynamically allocated string, free with g_free().
1227 _gtk_get_lc_ctype (void)
1230 /* Somebody might try to set the locale for this process using the
1231 * LANG or LC_ environment variables. The Microsoft C library
1232 * doesn't know anything about them. You set the locale in the
1233 * Control Panel. Setting these env vars won't have any affect on
1234 * locale-dependent C library functions like ctime(). But just for
1235 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1236 * it easier to test GTK and Pango in various default languages, you
1237 * don't have to clickety-click in the Control Panel, you can simply
1238 * start the program with LC_ALL=something on the command line.)
1242 p = getenv ("LC_ALL");
1244 return g_strdup (p);
1246 p = getenv ("LC_CTYPE");
1248 return g_strdup (p);
1250 p = getenv ("LANG");
1252 return g_strdup (p);
1254 return g_win32_getlocale ();
1256 return g_strdup (setlocale (LC_CTYPE, NULL));
1261 * gtk_get_default_language:
1263 * Returns the #PangoLanguage for the default language currently in
1264 * effect. (Note that this can change over the life of an
1265 * application.) The default language is derived from the current
1266 * locale. It determines, for example, whether GTK+ uses the
1267 * right-to-left or left-to-right text direction.
1269 * This function is equivalent to pango_language_get_default(). See
1270 * that function for details.
1272 * Return value: the default language as a #PangoLanguage, must not be
1276 gtk_get_default_language (void)
1278 return pango_language_get_default ();
1287 gtk_main_loop_level++;
1289 loop = g_main_loop_new (NULL, TRUE);
1290 main_loops = g_slist_prepend (main_loops, loop);
1292 if (g_main_loop_is_running (main_loops->data))
1294 GDK_THREADS_LEAVE ();
1295 g_main_loop_run (loop);
1296 GDK_THREADS_ENTER ();
1302 GList *reinvoke_list = NULL;
1303 GtkQuitFunction *quitf;
1305 while (quit_functions)
1307 quitf = quit_functions->data;
1309 tmp_list = quit_functions;
1310 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1311 g_list_free_1 (tmp_list);
1313 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1314 gtk_quit_invoke_function (quitf))
1316 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1320 gtk_quit_destroy (quitf);
1327 work = g_list_last (reinvoke_list);
1329 quit_functions->prev = work;
1330 work->next = quit_functions;
1331 quit_functions = work;
1337 main_loops = g_slist_remove (main_loops, loop);
1339 g_main_loop_unref (loop);
1341 gtk_main_loop_level--;
1343 if (gtk_main_loop_level == 0)
1345 /* Try storing all clipboard data we have */
1346 _gtk_clipboard_store_all ();
1348 /* Synchronize the recent manager singleton */
1349 _gtk_recent_manager_sync ();
1354 gtk_main_level (void)
1356 return gtk_main_loop_level;
1360 gtk_main_quit (void)
1362 g_return_if_fail (main_loops != NULL);
1364 g_main_loop_quit (main_loops->data);
1368 gtk_events_pending (void)
1372 GDK_THREADS_LEAVE ();
1373 result = g_main_context_pending (NULL);
1374 GDK_THREADS_ENTER ();
1380 gtk_main_iteration (void)
1382 GDK_THREADS_LEAVE ();
1383 g_main_context_iteration (NULL, TRUE);
1384 GDK_THREADS_ENTER ();
1387 return !g_main_loop_is_running (main_loops->data);
1393 gtk_main_iteration_do (gboolean blocking)
1395 GDK_THREADS_LEAVE ();
1396 g_main_context_iteration (NULL, blocking);
1397 GDK_THREADS_ENTER ();
1400 return !g_main_loop_is_running (main_loops->data);
1405 /* private libgtk to libgdk interfaces
1407 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1409 GdkWindow **grab_window,
1410 gboolean *owner_events);
1413 rewrite_events_translate (GdkWindow *old_window,
1414 GdkWindow *new_window,
1418 gint old_origin_x, old_origin_y;
1419 gint new_origin_x, new_origin_y;
1421 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1422 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1424 *x += old_origin_x - new_origin_x;
1425 *y += old_origin_y - new_origin_y;
1429 rewrite_event_for_window (GdkEvent *event,
1430 GdkWindow *new_window)
1432 event = gdk_event_copy (event);
1434 switch (event->type)
1437 rewrite_events_translate (event->any.window,
1439 &event->scroll.x, &event->scroll.y);
1441 case GDK_BUTTON_PRESS:
1442 case GDK_2BUTTON_PRESS:
1443 case GDK_3BUTTON_PRESS:
1444 case GDK_BUTTON_RELEASE:
1445 rewrite_events_translate (event->any.window,
1447 &event->button.x, &event->button.y);
1449 case GDK_MOTION_NOTIFY:
1450 rewrite_events_translate (event->any.window,
1452 &event->motion.x, &event->motion.y);
1455 case GDK_KEY_RELEASE:
1456 case GDK_PROXIMITY_IN:
1457 case GDK_PROXIMITY_OUT:
1464 g_object_unref (event->any.window);
1465 event->any.window = g_object_ref (new_window);
1470 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1471 * then what X11 does is deliver the event normally if it was going to this
1472 * client, otherwise, delivers it in terms of the grab window. This function
1473 * rewrites events to the effect that events going to the same window group
1474 * are delivered normally, otherwise, the event is delivered in terms of the
1478 rewrite_event_for_grabs (GdkEvent *event)
1480 GdkWindow *grab_window;
1481 GtkWidget *event_widget, *grab_widget;
1482 gpointer grab_widget_ptr;
1483 gboolean owner_events;
1484 GdkDisplay *display;
1487 switch (event->type)
1490 case GDK_BUTTON_PRESS:
1491 case GDK_2BUTTON_PRESS:
1492 case GDK_3BUTTON_PRESS:
1493 case GDK_BUTTON_RELEASE:
1494 case GDK_MOTION_NOTIFY:
1495 case GDK_PROXIMITY_IN:
1496 case GDK_PROXIMITY_OUT:
1498 case GDK_KEY_RELEASE:
1499 display = gdk_window_get_display (event->any.window);
1500 device = gdk_event_get_device (event);
1502 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1510 event_widget = gtk_get_event_widget (event);
1511 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1512 grab_widget = grab_widget_ptr;
1515 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1516 return rewrite_event_for_window (event, grab_window);
1522 gtk_main_do_event (GdkEvent *event)
1524 GtkWidget *event_widget;
1525 GtkWidget *grab_widget = NULL;
1526 GtkWindowGroup *window_group;
1527 GdkEvent *rewritten_event = NULL;
1531 if (event->type == GDK_SETTING)
1533 _gtk_settings_handle_event (&event->setting);
1537 if (event->type == GDK_OWNER_CHANGE)
1539 _gtk_clipboard_handle_event (&event->owner_change);
1543 /* Find the widget which got the event. We store the widget
1544 * in the user_data field of GdkWindow's.
1545 * Ignore the event if we don't have a widget for it, except
1546 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1547 * Though this happens rarely, bogus events can occour
1548 * for e.g. destroyed GdkWindows.
1550 event_widget = gtk_get_event_widget (event);
1553 /* To handle selection INCR transactions, we select
1554 * PropertyNotify events on the requestor window and create
1555 * a corresponding (fake) GdkWindow so that events get
1556 * here. There won't be a widget though, so we have to handle
1559 if (event->type == GDK_PROPERTY_NOTIFY)
1560 _gtk_selection_incr_event (event->any.window,
1566 /* If pointer or keyboard grabs are in effect, munge the events
1567 * so that each window group looks like a separate app.
1569 rewritten_event = rewrite_event_for_grabs (event);
1570 if (rewritten_event)
1572 event = rewritten_event;
1573 event_widget = gtk_get_event_widget (event);
1576 window_group = gtk_main_get_window_group (event_widget);
1577 device = gdk_event_get_device (event);
1579 /* check whether there is a (device) grab in effect...
1582 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1584 if (!grab_widget && window_group->grabs)
1585 grab_widget = window_group->grabs->data;
1587 /* If the grab widget is an ancestor of the event widget
1588 * then we send the event to the original event widget.
1589 * This is the key to implementing modality.
1592 (gtk_widget_is_sensitive (event_widget) &&
1593 gtk_widget_is_ancestor (event_widget, grab_widget)))
1594 grab_widget = event_widget;
1596 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1598 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1600 if (rewritten_event)
1601 gdk_event_free (rewritten_event);
1606 /* Push the event onto a stack of current events for
1607 * gtk_current_event_get().
1609 current_events = g_list_prepend (current_events, event);
1611 /* Not all events get sent to the grabbing widget.
1612 * The delete, destroy, expose, focus change and resize
1613 * events still get sent to the event widget because
1614 * 1) these events have no meaning for the grabbing widget
1615 * and 2) redirecting these events to the grabbing widget
1616 * could cause the display to be messed up.
1618 * Drag events are also not redirected, since it isn't
1619 * clear what the semantics of that would be.
1621 switch (event->type)
1627 g_object_ref (event_widget);
1628 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1629 !gtk_widget_event (event_widget, event))
1630 gtk_widget_destroy (event_widget);
1631 g_object_unref (event_widget);
1635 /* Unexpected GDK_DESTROY from the outside, ignore for
1636 * child windows, handle like a GDK_DELETE for toplevels
1638 if (!gtk_widget_get_parent (event_widget))
1640 g_object_ref (event_widget);
1641 if (!gtk_widget_event (event_widget, event) &&
1642 gtk_widget_get_realized (event_widget))
1643 gtk_widget_destroy (event_widget);
1644 g_object_unref (event_widget);
1649 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1651 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1652 gtk_widget_send_expose (event_widget, event);
1653 gdk_window_end_paint (event->any.window);
1657 /* The app may paint with a previously allocated cairo_t,
1658 which will draw directly to the window. We can't catch cairo
1659 drap operatoins to automatically flush the window, thus we
1660 need to explicitly flush any outstanding moves or double
1662 gdk_window_flush (event->any.window);
1663 gtk_widget_send_expose (event_widget, event);
1667 case GDK_PROPERTY_NOTIFY:
1668 case GDK_FOCUS_CHANGE:
1672 case GDK_SELECTION_CLEAR:
1673 case GDK_SELECTION_REQUEST:
1674 case GDK_SELECTION_NOTIFY:
1675 case GDK_CLIENT_EVENT:
1676 case GDK_VISIBILITY_NOTIFY:
1677 case GDK_WINDOW_STATE:
1678 case GDK_GRAB_BROKEN:
1680 gtk_widget_event (event_widget, event);
1684 case GDK_BUTTON_PRESS:
1685 case GDK_2BUTTON_PRESS:
1686 case GDK_3BUTTON_PRESS:
1687 gtk_propagate_event (grab_widget, event);
1691 case GDK_KEY_RELEASE:
1694 if (gtk_invoke_key_snoopers (grab_widget, event))
1697 /* Catch alt press to enable auto-mnemonics;
1698 * menus are handled elsewhere
1700 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1701 !GTK_IS_MENU_SHELL (grab_widget))
1703 gboolean auto_mnemonics;
1705 g_object_get (gtk_widget_get_settings (grab_widget),
1706 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1710 gboolean mnemonics_visible;
1713 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1715 window = gtk_widget_get_toplevel (grab_widget);
1717 if (GTK_IS_WINDOW (window))
1718 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1721 /* else fall through */
1722 case GDK_MOTION_NOTIFY:
1723 case GDK_BUTTON_RELEASE:
1724 case GDK_PROXIMITY_IN:
1725 case GDK_PROXIMITY_OUT:
1726 gtk_propagate_event (grab_widget, event);
1729 case GDK_ENTER_NOTIFY:
1730 _gtk_widget_set_device_window (event_widget,
1731 gdk_event_get_device (event),
1733 if (gtk_widget_is_sensitive (grab_widget))
1734 gtk_widget_event (grab_widget, event);
1737 case GDK_LEAVE_NOTIFY:
1738 _gtk_widget_set_device_window (event_widget,
1739 gdk_event_get_device (event),
1741 if (gtk_widget_is_sensitive (grab_widget))
1742 gtk_widget_event (grab_widget, event);
1745 case GDK_DRAG_STATUS:
1746 case GDK_DROP_FINISHED:
1747 _gtk_drag_source_handle_event (event_widget, event);
1749 case GDK_DRAG_ENTER:
1750 case GDK_DRAG_LEAVE:
1751 case GDK_DRAG_MOTION:
1752 case GDK_DROP_START:
1753 _gtk_drag_dest_handle_event (event_widget, event);
1756 g_assert_not_reached ();
1760 if (event->type == GDK_ENTER_NOTIFY
1761 || event->type == GDK_LEAVE_NOTIFY
1762 || event->type == GDK_BUTTON_PRESS
1763 || event->type == GDK_2BUTTON_PRESS
1764 || event->type == GDK_3BUTTON_PRESS
1765 || event->type == GDK_KEY_PRESS
1766 || event->type == GDK_DRAG_ENTER
1767 || event->type == GDK_GRAB_BROKEN
1768 || event->type == GDK_MOTION_NOTIFY
1769 || event->type == GDK_SCROLL)
1771 _gtk_tooltip_handle_event (event);
1774 tmp_list = current_events;
1775 current_events = g_list_remove_link (current_events, tmp_list);
1776 g_list_free_1 (tmp_list);
1778 if (rewritten_event)
1779 gdk_event_free (rewritten_event);
1794 static GtkWindowGroup *
1795 gtk_main_get_window_group (GtkWidget *widget)
1797 GtkWidget *toplevel = NULL;
1800 toplevel = gtk_widget_get_toplevel (widget);
1802 if (GTK_IS_WINDOW (toplevel))
1803 return gtk_window_get_group (GTK_WINDOW (toplevel));
1805 return gtk_window_get_group (NULL);
1810 GtkWidget *old_grab_widget;
1811 GtkWidget *new_grab_widget;
1812 gboolean was_grabbed;
1813 gboolean is_grabbed;
1815 GList *notified_windows;
1820 synth_crossing_for_grab_notify (GtkWidget *from,
1822 GrabNotifyInfo *info,
1824 GdkCrossingMode mode)
1828 GdkDevice *device = devices->data;
1829 GdkWindow *from_window, *to_window;
1831 /* Do not propagate events more than once to
1832 * the same windows if non-multidevice aware.
1838 from_window = _gtk_widget_get_device_window (from, device);
1841 !gdk_window_get_support_multidevice (from_window) &&
1842 g_list_find (info->notified_windows, from_window))
1850 to_window = _gtk_widget_get_device_window (to, device);
1853 !gdk_window_get_support_multidevice (to_window) &&
1854 g_list_find (info->notified_windows, to_window))
1858 if (from_window || to_window)
1860 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1861 (to_window) ? to : NULL,
1865 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1868 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1871 devices = devices->next;
1876 gtk_grab_notify_foreach (GtkWidget *child,
1879 GrabNotifyInfo *info = data;
1880 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1883 was_grabbed = info->was_grabbed;
1884 is_grabbed = info->is_grabbed;
1886 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1887 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1889 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1890 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1892 g_object_ref (child);
1894 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1895 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1898 _gtk_widget_get_device_window (child, info->device))
1900 /* Device specified and is on widget */
1901 devices = g_list_prepend (NULL, info->device);
1904 devices = _gtk_widget_list_devices (child);
1908 _gtk_widget_set_shadowed (child, TRUE);
1909 if (!was_shadowed && devices &&
1910 gtk_widget_is_sensitive (child))
1911 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1913 GDK_CROSSING_GTK_GRAB);
1917 _gtk_widget_set_shadowed (child, FALSE);
1918 if (was_shadowed && devices &&
1919 gtk_widget_is_sensitive (child))
1920 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1922 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1923 GDK_CROSSING_GTK_UNGRAB);
1926 if (was_shadowed != is_shadowed)
1927 _gtk_widget_grab_notify (child, was_shadowed);
1929 g_object_unref (child);
1930 g_list_free (devices);
1932 info->was_grabbed = was_grabbed;
1933 info->is_grabbed = is_grabbed;
1937 gtk_grab_notify (GtkWindowGroup *group,
1939 GtkWidget *old_grab_widget,
1940 GtkWidget *new_grab_widget,
1944 GrabNotifyInfo info = { 0 };
1946 if (old_grab_widget == new_grab_widget)
1949 info.old_grab_widget = old_grab_widget;
1950 info.new_grab_widget = new_grab_widget;
1951 info.from_grab = from_grab;
1952 info.device = device;
1954 g_object_ref (group);
1956 toplevels = gtk_window_list_toplevels ();
1957 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1961 GtkWindow *toplevel = toplevels->data;
1962 toplevels = g_list_delete_link (toplevels, toplevels);
1964 info.was_grabbed = FALSE;
1965 info.is_grabbed = FALSE;
1967 if (group == gtk_window_get_group (toplevel))
1968 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1969 g_object_unref (toplevel);
1972 g_list_free (info.notified_windows);
1973 g_object_unref (group);
1977 gtk_grab_add (GtkWidget *widget)
1979 GtkWindowGroup *group;
1980 GtkWidget *old_grab_widget;
1982 g_return_if_fail (widget != NULL);
1984 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1986 _gtk_widget_set_has_grab (widget, TRUE);
1988 group = gtk_main_get_window_group (widget);
1991 old_grab_widget = (GtkWidget *)group->grabs->data;
1993 old_grab_widget = NULL;
1995 g_object_ref (widget);
1996 group->grabs = g_slist_prepend (group->grabs, 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);
2018 return GTK_WIDGET (group->grabs->data);
2023 gtk_grab_remove (GtkWidget *widget)
2025 GtkWindowGroup *group;
2026 GtkWidget *new_grab_widget;
2028 g_return_if_fail (widget != NULL);
2030 if (gtk_widget_has_grab (widget))
2032 _gtk_widget_set_has_grab (widget, FALSE);
2034 group = gtk_main_get_window_group (widget);
2035 group->grabs = g_slist_remove (group->grabs, widget);
2038 new_grab_widget = (GtkWidget *)group->grabs->data;
2040 new_grab_widget = NULL;
2042 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2044 g_object_unref (widget);
2049 * gtk_device_grab_add:
2050 * @widget: a #GtkWidget
2051 * @device: a #GtkDevice to grab on.
2052 * @block_others: %TRUE to prevent other devices to interact with @widget.
2054 * Adds a GTK+ grab on @device, so all the events on @device and its
2055 * associated pointer or keyboard (if any) are delivered to @widget.
2056 * If the @block_others parameter is %TRUE, any other devices will be
2057 * unable to interact with @widget during the grab.
2062 gtk_device_grab_add (GtkWidget *widget,
2064 gboolean block_others)
2066 GtkWindowGroup *group;
2067 GtkWidget *old_grab_widget;
2069 g_return_if_fail (GTK_IS_WIDGET (widget));
2070 g_return_if_fail (GDK_IS_DEVICE (device));
2072 group = gtk_main_get_window_group (widget);
2073 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2075 if (old_grab_widget != widget)
2076 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2078 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2082 * gtk_device_grab_remove:
2083 * @widget: a #GtkWidget
2084 * @device: a #GdkDevice
2086 * Removes a device grab from the given widget. You have to pair calls
2087 * to gtk_device_grab_add() and gtk_device_grab_remove().
2092 gtk_device_grab_remove (GtkWidget *widget,
2095 GtkWindowGroup *group;
2096 GtkWidget *new_grab_widget;
2098 g_return_if_fail (GTK_IS_WIDGET (widget));
2099 g_return_if_fail (GDK_IS_DEVICE (device));
2101 group = gtk_main_get_window_group (widget);
2102 _gtk_window_group_remove_device_grab (group, widget, device);
2103 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2105 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2109 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2112 GtkKeySnooperData *data;
2113 static guint snooper_id = 1;
2115 g_return_val_if_fail (snooper != NULL, 0);
2117 data = g_new (GtkKeySnooperData, 1);
2118 data->func = snooper;
2119 data->func_data = func_data;
2120 data->id = snooper_id++;
2121 key_snoopers = g_slist_prepend (key_snoopers, data);
2127 gtk_key_snooper_remove (guint snooper_id)
2129 GtkKeySnooperData *data = NULL;
2132 slist = key_snoopers;
2136 if (data->id == snooper_id)
2139 slist = slist->next;
2144 key_snoopers = g_slist_remove (key_snoopers, data);
2150 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2154 gint return_val = FALSE;
2156 slist = key_snoopers;
2157 while (slist && !return_val)
2159 GtkKeySnooperData *data;
2162 slist = slist->next;
2163 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2170 gtk_quit_add_full (guint main_level,
2171 GtkFunction function,
2172 GtkCallbackMarshal marshal,
2174 GDestroyNotify destroy)
2176 static guint quit_id = 1;
2177 GtkQuitFunction *quitf;
2179 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2181 quitf = g_slice_new (GtkQuitFunction);
2183 quitf->id = quit_id++;
2184 quitf->main_level = main_level;
2185 quitf->function = function;
2186 quitf->marshal = marshal;
2188 quitf->destroy = destroy;
2190 quit_functions = g_list_prepend (quit_functions, quitf);
2196 gtk_quit_destroy (GtkQuitFunction *quitf)
2199 quitf->destroy (quitf->data);
2200 g_slice_free (GtkQuitFunction, quitf);
2204 gtk_quit_destructor (GtkWidget **object_p)
2207 gtk_widget_destroy (*object_p);
2214 gtk_quit_add_destroy (guint main_level,
2217 GtkWidget **object_p;
2219 g_return_if_fail (main_level > 0);
2220 g_return_if_fail (GTK_IS_WIDGET (object));
2222 object_p = g_new (GtkWidget*, 1);
2224 g_signal_connect (object,
2226 G_CALLBACK (gtk_widget_destroyed),
2228 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2232 gtk_quit_add (guint main_level,
2233 GtkFunction function,
2236 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2240 gtk_quit_remove (guint id)
2242 GtkQuitFunction *quitf;
2245 tmp_list = quit_functions;
2248 quitf = tmp_list->data;
2250 if (quitf->id == id)
2252 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2253 g_list_free (tmp_list);
2254 gtk_quit_destroy (quitf);
2259 tmp_list = tmp_list->next;
2264 gtk_quit_remove_by_data (gpointer data)
2266 GtkQuitFunction *quitf;
2269 tmp_list = quit_functions;
2272 quitf = tmp_list->data;
2274 if (quitf->data == data)
2276 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2277 g_list_free (tmp_list);
2278 gtk_quit_destroy (quitf);
2283 tmp_list = tmp_list->next;
2288 * gtk_get_current_event:
2290 * Obtains a copy of the event currently being processed by GTK+. For
2291 * example, if you get a "clicked" signal from #GtkButton, the current
2292 * event will be the #GdkEventButton that triggered the "clicked"
2293 * signal. The returned event must be freed with gdk_event_free().
2294 * If there is no current event, the function returns %NULL.
2296 * Return value: a copy of the current event, or %NULL if no current event.
2299 gtk_get_current_event (void)
2302 return gdk_event_copy (current_events->data);
2308 * gtk_get_current_event_time:
2310 * If there is a current event and it has a timestamp, return that
2311 * timestamp, otherwise return %GDK_CURRENT_TIME.
2313 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2316 gtk_get_current_event_time (void)
2319 return gdk_event_get_time (current_events->data);
2321 return GDK_CURRENT_TIME;
2325 * gtk_get_current_event_state:
2326 * @state: a location to store the state of the current event
2328 * If there is a current event and it has a state field, place
2329 * that state field in @state and return %TRUE, otherwise return
2332 * Return value: %TRUE if there was a current event and it had a state field
2335 gtk_get_current_event_state (GdkModifierType *state)
2337 g_return_val_if_fail (state != NULL, FALSE);
2340 return gdk_event_get_state (current_events->data, state);
2349 * gtk_get_current_event_device:
2351 * If there is a current event and it has a device, return that
2352 * device, otherwise return %NULL.
2354 * Returns: (transfer none): a #GdkDevice, or %NULL
2357 gtk_get_current_event_device (void)
2360 return gdk_event_get_device (current_events->data);
2366 * gtk_get_event_widget:
2367 * @event: a #GdkEvent
2369 * If @event is %NULL or the event was not associated with any widget,
2370 * returns %NULL, otherwise returns the widget that received the event
2373 * Return value: (transfer none): the widget that originally
2374 * received @event, or %NULL
2377 gtk_get_event_widget (GdkEvent *event)
2380 gpointer widget_ptr;
2383 if (event && event->any.window &&
2384 (event->type == GDK_DESTROY || !gdk_window_is_destroyed (event->any.window)))
2386 gdk_window_get_user_data (event->any.window, &widget_ptr);
2387 widget = widget_ptr;
2394 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2396 if (!quitf->marshal)
2397 return quitf->function (quitf->data);
2401 gint ret_val = FALSE;
2403 args[0].name = NULL;
2404 args[0].type = G_TYPE_BOOLEAN;
2405 args[0].d.pointer_data = &ret_val;
2406 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2414 * gtk_propagate_event:
2415 * @widget: a #GtkWidget
2418 * Sends an event to a widget, propagating the event to parent widgets
2419 * if the event remains unhandled. Events received by GTK+ from GDK
2420 * normally begin in gtk_main_do_event(). Depending on the type of
2421 * event, existence of modal dialogs, grabs, etc., the event may be
2422 * propagated; if so, this function is used. gtk_propagate_event()
2423 * calls gtk_widget_event() on each widget it decides to send the
2424 * event to. So gtk_widget_event() is the lowest-level function; it
2425 * simply emits the "event" and possibly an event-specific signal on a
2426 * widget. gtk_propagate_event() is a bit higher-level, and
2427 * gtk_main_do_event() is the highest level.
2429 * All that said, you most likely don't want to use any of these
2430 * functions; synthesizing events is rarely needed. Consider asking on
2431 * the mailing list for better ways to achieve your goals. For
2432 * example, use gdk_window_invalidate_rect() or
2433 * gtk_widget_queue_draw() instead of making up expose events.
2437 gtk_propagate_event (GtkWidget *widget,
2442 g_return_if_fail (GTK_IS_WIDGET (widget));
2443 g_return_if_fail (event != NULL);
2445 handled_event = FALSE;
2447 g_object_ref (widget);
2449 if ((event->type == GDK_KEY_PRESS) ||
2450 (event->type == GDK_KEY_RELEASE))
2452 /* Only send key events within Window widgets to the Window
2453 * The Window widget will in turn pass the
2454 * key event on to the currently focused widget
2459 window = gtk_widget_get_toplevel (widget);
2460 if (GTK_IS_WINDOW (window))
2462 /* If there is a grab within the window, give the grab widget
2463 * a first crack at the key event
2465 if (widget != window && gtk_widget_has_grab (widget))
2466 handled_event = gtk_widget_event (widget, event);
2470 window = gtk_widget_get_toplevel (widget);
2471 if (GTK_IS_WINDOW (window))
2473 if (gtk_widget_is_sensitive (window))
2474 gtk_widget_event (window, event);
2478 handled_event = TRUE; /* don't send to widget */
2482 /* Other events get propagated up the widget tree
2483 * so that parents can see the button and motion
2484 * events of the children.
2492 /* Scroll events are special cased here because it
2493 * feels wrong when scrolling a GtkViewport, say,
2494 * to have children of the viewport eat the scroll
2497 if (!gtk_widget_is_sensitive (widget))
2498 handled_event = event->type != GDK_SCROLL;
2500 handled_event = gtk_widget_event (widget, event);
2502 tmp = gtk_widget_get_parent (widget);
2503 g_object_unref (widget);
2507 if (!handled_event && widget)
2508 g_object_ref (widget);
2514 g_object_unref (widget);
2518 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2519 GValue *return_accu,
2520 const GValue *handler_return,
2523 gboolean continue_emission;
2524 gboolean signal_handled;
2526 signal_handled = g_value_get_boolean (handler_return);
2527 g_value_set_boolean (return_accu, signal_handled);
2528 continue_emission = !signal_handled;
2530 return continue_emission;