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 ();
800 /* Set the 'initialized' flag.
802 gtk_initialized = TRUE;
804 /* load gtk modules */
805 if (gtk_modules_string)
807 _gtk_modules_init (argc, argv, gtk_modules_string->str);
808 g_string_free (gtk_modules_string, TRUE);
812 _gtk_modules_init (argc, argv, NULL);
819 gboolean open_default_display;
823 pre_parse_hook (GOptionContext *context,
828 do_pre_parse_initialization (NULL, NULL);
834 post_parse_hook (GOptionContext *context,
839 OptionGroupInfo *info = data;
842 do_post_parse_initialization (NULL, NULL);
844 if (info->open_default_display)
846 if (gdk_display_open_default_libgtk_only () == NULL)
848 const char *display_name = gdk_get_display_arg_name ();
851 G_OPTION_ERROR_FAILED,
852 _("Cannot open display: %s"),
853 display_name ? display_name : "" );
864 * gtk_get_debug_flags:
866 * Returns the GTK+ debug flags setting.
869 gtk_get_debug_flags (void)
875 * gtk_set_debug_flags:
877 * Sets the GTK+ debug flags.
880 gtk_set_debug_flags (guint flags)
886 * gtk_get_option_group:
887 * @open_default_display: whether to open the default display
888 * when parsing the commandline arguments
890 * Returns a #GOptionGroup for the commandline arguments recognized
891 * by GTK+ and GDK. You should add this group to your #GOptionContext
892 * with g_option_context_add_group(), if you are using
893 * g_option_context_parse() to parse your commandline arguments.
895 * Returns: a #GOptionGroup for the commandline arguments recognized
901 gtk_get_option_group (gboolean open_default_display)
904 OptionGroupInfo *info;
906 gettext_initialization ();
908 info = g_new0 (OptionGroupInfo, 1);
909 info->open_default_display = open_default_display;
911 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
912 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
914 gdk_add_option_entries_libgtk_only (group);
915 g_option_group_add_entries (group, gtk_args);
916 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
922 * gtk_init_with_args:
923 * @argc: a pointer to the number of command line arguments.
924 * @argv: a pointer to the array of command line arguments.
925 * @parameter_string: a string which is displayed in
926 * the first line of <option>--help</option> output, after
927 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
928 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
929 * describing the options of your program
930 * @translation_domain: a translation domain to use for translating
931 * the <option>--help</option> output for the options in @entries
932 * and the @parameter_string with gettext(), or %NULL
933 * @error: a return location for errors
935 * This function does the same work as gtk_init_check().
936 * Additionally, it allows you to add your own commandline options,
937 * and it automatically generates nicely formatted
938 * <option>--help</option> output. Note that your program will
939 * be terminated after writing out the help output.
941 * Returns: %TRUE if the GUI has been successfully initialized,
947 gtk_init_with_args (gint *argc,
949 const gchar *parameter_string,
950 const GOptionEntry *entries,
951 const gchar *translation_domain,
954 GOptionContext *context;
955 GOptionGroup *gtk_group;
959 return gdk_display_open_default_libgtk_only () != NULL;
961 gettext_initialization ();
963 if (!check_setugid ())
966 gtk_group = gtk_get_option_group (TRUE);
968 context = g_option_context_new (parameter_string);
969 g_option_context_add_group (context, gtk_group);
970 g_option_context_set_translation_domain (context, translation_domain);
973 g_option_context_add_main_entries (context, entries, translation_domain);
974 retval = g_option_context_parse (context, argc, argv, error);
976 g_option_context_free (context);
984 * @argc: (inout): a pointer to the number of command line arguments.
985 * @argv: (array) (inout): a pointer to the array of command line arguments.
987 * Parses command line arguments, and initializes global
988 * attributes of GTK+, but does not actually open a connection
989 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
991 * Any arguments used by GTK+ or GDK are removed from the array and
992 * @argc and @argv are updated accordingly.
994 * You shouldn't call this function explicitely if you are using
995 * gtk_init(), or gtk_init_check().
997 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1000 gtk_parse_args (int *argc,
1003 GOptionContext *option_context;
1004 GOptionGroup *gtk_group;
1005 GError *error = NULL;
1007 if (gtk_initialized)
1010 gettext_initialization ();
1012 if (!check_setugid ())
1015 option_context = g_option_context_new (NULL);
1016 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1017 g_option_context_set_help_enabled (option_context, FALSE);
1018 gtk_group = gtk_get_option_group (FALSE);
1019 g_option_context_set_main_group (option_context, gtk_group);
1020 if (!g_option_context_parse (option_context, argc, argv, &error))
1022 g_warning ("%s", error->message);
1023 g_error_free (error);
1026 g_option_context_free (option_context);
1031 #ifdef G_PLATFORM_WIN32
1032 #undef gtk_init_check
1037 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1038 * main() function. Changed if any arguments were handled.
1039 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1040 * Any parameters understood by gtk_init() are stripped before return.
1042 * This function does the same work as gtk_init() with only
1043 * a single change: It does not terminate the program if the GUI can't be
1044 * initialized. Instead it returns %FALSE on failure.
1046 * This way the application can fall back to some other means of communication
1047 * with the user - for example a curses or command line interface.
1049 * Return value: %TRUE if the GUI has been successfully initialized,
1053 gtk_init_check (int *argc,
1056 if (!gtk_parse_args (argc, argv))
1059 return gdk_display_open_default_libgtk_only () != NULL;
1062 #ifdef G_PLATFORM_WIN32
1068 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1069 * main() function. Changed if any arguments were handled.
1070 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1071 * Any parameters understood by gtk_init() are stripped before return.
1073 * Call this function before using any other GTK+ functions in your GUI
1074 * applications. It will initialize everything needed to operate the
1075 * toolkit and parses some standard command line options. @argc and
1076 * @argv are adjusted accordingly so your own code will
1077 * never see those standard arguments.
1079 * Note that there are some alternative ways to initialize GTK+:
1080 * if you are calling gtk_parse_args(), gtk_init_check(),
1081 * gtk_init_with_args() or g_option_context_parse() with
1082 * the option group returned by gtk_get_option_group(), you
1083 * <emphasis>don't</emphasis> have to call gtk_init().
1086 * This function will terminate your program if it was unable to initialize
1087 * the GUI for some reason. If you want your program to fall back to a
1088 * textual interface you want to call gtk_init_check() instead.
1092 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1093 * during initialization, to ignore SIGPIPE signals, since these are
1094 * almost never wanted in graphical applications. If you do need to
1095 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1096 * but notice that other libraries (e.g. libdbus or gvfs) might do
1101 gtk_init (int *argc, char ***argv)
1103 if (!gtk_init_check (argc, argv))
1105 const char *display_name_arg = gdk_get_display_arg_name ();
1106 if (display_name_arg == NULL)
1107 display_name_arg = getenv("DISPLAY");
1108 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1113 #ifdef G_PLATFORM_WIN32
1116 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1118 if (sizeof_GtkWindow != sizeof (GtkWindow))
1119 g_error ("Incompatible build!\n"
1120 "The code using GTK+ thinks GtkWindow is of different\n"
1121 "size than it actually is in this build of GTK+.\n"
1122 "On Windows, this probably means that you have compiled\n"
1123 "your code with gcc without the -mms-bitfields switch,\n"
1124 "or that you are using an unsupported compiler.");
1127 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1128 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1129 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1130 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1131 * -fnative-struct still matters. GtkBox is one such.
1134 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1136 if (sizeof_GtkBox != sizeof (GtkBox))
1137 g_error ("Incompatible build!\n"
1138 "The code using GTK+ thinks GtkBox is of different\n"
1139 "size than it actually is in this build of GTK+.\n"
1140 "On Windows, this probably means that you have compiled\n"
1141 "your code with gcc without the -mms-bitfields switch,\n"
1142 "or that you are using an unsupported compiler.");
1145 /* These two functions might get more checks added later, thus pass
1146 * in the number of extra args.
1149 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1151 check_sizeof_GtkWindow (sizeof_GtkWindow);
1152 if (num_checks >= 2)
1153 check_sizeof_GtkBox (sizeof_GtkBox);
1154 gtk_init (argc, argv);
1158 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1160 check_sizeof_GtkWindow (sizeof_GtkWindow);
1161 if (num_checks >= 2)
1162 check_sizeof_GtkBox (sizeof_GtkBox);
1163 return gtk_init_check (argc, argv);
1171 * Initializes internationalization support for GTK+. gtk_init()
1172 * automatically does this, so there is typically no point
1173 * in calling this function.
1175 * If you are calling this function because you changed the locale
1176 * after GTK+ is was initialized, then calling this function
1177 * may help a bit. (Note, however, that changing the locale
1178 * after GTK+ is initialized may produce inconsistent results and
1179 * is not really supported.)
1181 * In detail - sets the current locale according to the
1182 * program environment. This is the same as calling the C library function
1183 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1184 * locale specific setup of the windowing system used by GDK.
1186 * Returns: a string corresponding to the locale set, typically in the
1187 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1188 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1189 * result of the setlocale(); it is also used on other machines, such as
1190 * Windows, where the C library returns a different result. The string is
1191 * owned by GTK+ and should not be modified or freed.
1194 gtk_set_locale (void)
1196 return gdk_set_locale ();
1200 * _gtk_get_lc_ctype:
1202 * Return the Unix-style locale string for the language currently in
1203 * effect. On Unix systems, this is the return value from
1204 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1205 * affect this through the environment variables LC_ALL, LC_CTYPE or
1206 * LANG (checked in that order). The locale strings typically is in
1207 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1208 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1209 * Swedish as written in Finland or pt_BR for Portuguese as written in
1212 * On Windows, the C library doesn't use any such environment
1213 * variables, and setting them won't affect the behaviour of functions
1214 * like ctime(). The user sets the locale through the Regional Options
1215 * in the Control Panel. The C library (in the setlocale() function)
1216 * does not use country and language codes, but country and language
1217 * names spelled out in English.
1218 * However, this function does check the above environment
1219 * variables, and does return a Unix-style locale string based on
1220 * either said environment variables or the thread's current locale.
1222 * Return value: a dynamically allocated string, free with g_free().
1226 _gtk_get_lc_ctype (void)
1229 /* Somebody might try to set the locale for this process using the
1230 * LANG or LC_ environment variables. The Microsoft C library
1231 * doesn't know anything about them. You set the locale in the
1232 * Control Panel. Setting these env vars won't have any affect on
1233 * locale-dependent C library functions like ctime(). But just for
1234 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1235 * it easier to test GTK and Pango in various default languages, you
1236 * don't have to clickety-click in the Control Panel, you can simply
1237 * start the program with LC_ALL=something on the command line.)
1241 p = getenv ("LC_ALL");
1243 return g_strdup (p);
1245 p = getenv ("LC_CTYPE");
1247 return g_strdup (p);
1249 p = getenv ("LANG");
1251 return g_strdup (p);
1253 return g_win32_getlocale ();
1255 return g_strdup (setlocale (LC_CTYPE, NULL));
1260 * gtk_get_default_language:
1262 * Returns the #PangoLanguage for the default language currently in
1263 * effect. (Note that this can change over the life of an
1264 * application.) The default language is derived from the current
1265 * locale. It determines, for example, whether GTK+ uses the
1266 * right-to-left or left-to-right text direction.
1268 * This function is equivalent to pango_language_get_default(). See
1269 * that function for details.
1271 * Return value: the default language as a #PangoLanguage, must not be
1275 gtk_get_default_language (void)
1277 return pango_language_get_default ();
1286 gtk_main_loop_level++;
1288 loop = g_main_loop_new (NULL, TRUE);
1289 main_loops = g_slist_prepend (main_loops, loop);
1291 if (g_main_loop_is_running (main_loops->data))
1293 GDK_THREADS_LEAVE ();
1294 g_main_loop_run (loop);
1295 GDK_THREADS_ENTER ();
1301 GList *reinvoke_list = NULL;
1302 GtkQuitFunction *quitf;
1304 while (quit_functions)
1306 quitf = quit_functions->data;
1308 tmp_list = quit_functions;
1309 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1310 g_list_free_1 (tmp_list);
1312 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1313 gtk_quit_invoke_function (quitf))
1315 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1319 gtk_quit_destroy (quitf);
1326 work = g_list_last (reinvoke_list);
1328 quit_functions->prev = work;
1329 work->next = quit_functions;
1330 quit_functions = work;
1336 main_loops = g_slist_remove (main_loops, loop);
1338 g_main_loop_unref (loop);
1340 gtk_main_loop_level--;
1342 if (gtk_main_loop_level == 0)
1344 /* Try storing all clipboard data we have */
1345 _gtk_clipboard_store_all ();
1347 /* Synchronize the recent manager singleton */
1348 _gtk_recent_manager_sync ();
1353 gtk_main_level (void)
1355 return gtk_main_loop_level;
1359 gtk_main_quit (void)
1361 g_return_if_fail (main_loops != NULL);
1363 g_main_loop_quit (main_loops->data);
1367 gtk_events_pending (void)
1371 GDK_THREADS_LEAVE ();
1372 result = g_main_context_pending (NULL);
1373 GDK_THREADS_ENTER ();
1379 gtk_main_iteration (void)
1381 GDK_THREADS_LEAVE ();
1382 g_main_context_iteration (NULL, TRUE);
1383 GDK_THREADS_ENTER ();
1386 return !g_main_loop_is_running (main_loops->data);
1392 gtk_main_iteration_do (gboolean blocking)
1394 GDK_THREADS_LEAVE ();
1395 g_main_context_iteration (NULL, blocking);
1396 GDK_THREADS_ENTER ();
1399 return !g_main_loop_is_running (main_loops->data);
1404 /* private libgtk to libgdk interfaces
1406 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1408 GdkWindow **grab_window,
1409 gboolean *owner_events);
1412 rewrite_events_translate (GdkWindow *old_window,
1413 GdkWindow *new_window,
1417 gint old_origin_x, old_origin_y;
1418 gint new_origin_x, new_origin_y;
1420 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1421 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1423 *x += old_origin_x - new_origin_x;
1424 *y += old_origin_y - new_origin_y;
1428 rewrite_event_for_window (GdkEvent *event,
1429 GdkWindow *new_window)
1431 event = gdk_event_copy (event);
1433 switch (event->type)
1436 rewrite_events_translate (event->any.window,
1438 &event->scroll.x, &event->scroll.y);
1440 case GDK_BUTTON_PRESS:
1441 case GDK_2BUTTON_PRESS:
1442 case GDK_3BUTTON_PRESS:
1443 case GDK_BUTTON_RELEASE:
1444 rewrite_events_translate (event->any.window,
1446 &event->button.x, &event->button.y);
1448 case GDK_MOTION_NOTIFY:
1449 rewrite_events_translate (event->any.window,
1451 &event->motion.x, &event->motion.y);
1454 case GDK_KEY_RELEASE:
1455 case GDK_PROXIMITY_IN:
1456 case GDK_PROXIMITY_OUT:
1463 g_object_unref (event->any.window);
1464 event->any.window = g_object_ref (new_window);
1469 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1470 * then what X11 does is deliver the event normally if it was going to this
1471 * client, otherwise, delivers it in terms of the grab window. This function
1472 * rewrites events to the effect that events going to the same window group
1473 * are delivered normally, otherwise, the event is delivered in terms of the
1477 rewrite_event_for_grabs (GdkEvent *event)
1479 GdkWindow *grab_window;
1480 GtkWidget *event_widget, *grab_widget;
1481 gpointer grab_widget_ptr;
1482 gboolean owner_events;
1483 GdkDisplay *display;
1486 switch (event->type)
1489 case GDK_BUTTON_PRESS:
1490 case GDK_2BUTTON_PRESS:
1491 case GDK_3BUTTON_PRESS:
1492 case GDK_BUTTON_RELEASE:
1493 case GDK_MOTION_NOTIFY:
1494 case GDK_PROXIMITY_IN:
1495 case GDK_PROXIMITY_OUT:
1497 case GDK_KEY_RELEASE:
1498 display = gdk_window_get_display (event->any.window);
1499 device = gdk_event_get_device (event);
1501 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1509 event_widget = gtk_get_event_widget (event);
1510 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1511 grab_widget = grab_widget_ptr;
1514 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1515 return rewrite_event_for_window (event, grab_window);
1521 gtk_main_do_event (GdkEvent *event)
1523 GtkWidget *event_widget;
1524 GtkWidget *grab_widget = NULL;
1525 GtkWindowGroup *window_group;
1526 GdkEvent *rewritten_event = NULL;
1530 if (event->type == GDK_SETTING)
1532 _gtk_settings_handle_event (&event->setting);
1536 if (event->type == GDK_OWNER_CHANGE)
1538 _gtk_clipboard_handle_event (&event->owner_change);
1542 /* Find the widget which got the event. We store the widget
1543 * in the user_data field of GdkWindow's.
1544 * Ignore the event if we don't have a widget for it, except
1545 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1546 * Though this happens rarely, bogus events can occour
1547 * for e.g. destroyed GdkWindows.
1549 event_widget = gtk_get_event_widget (event);
1552 /* To handle selection INCR transactions, we select
1553 * PropertyNotify events on the requestor window and create
1554 * a corresponding (fake) GdkWindow so that events get
1555 * here. There won't be a widget though, so we have to handle
1558 if (event->type == GDK_PROPERTY_NOTIFY)
1559 _gtk_selection_incr_event (event->any.window,
1565 /* If pointer or keyboard grabs are in effect, munge the events
1566 * so that each window group looks like a separate app.
1568 rewritten_event = rewrite_event_for_grabs (event);
1569 if (rewritten_event)
1571 event = rewritten_event;
1572 event_widget = gtk_get_event_widget (event);
1575 window_group = gtk_main_get_window_group (event_widget);
1576 device = gdk_event_get_device (event);
1578 /* check whether there is a (device) grab in effect...
1581 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1583 if (!grab_widget && window_group->grabs)
1584 grab_widget = window_group->grabs->data;
1586 /* If the grab widget is an ancestor of the event widget
1587 * then we send the event to the original event widget.
1588 * This is the key to implementing modality.
1591 (gtk_widget_is_sensitive (event_widget) &&
1592 gtk_widget_is_ancestor (event_widget, grab_widget)))
1593 grab_widget = event_widget;
1595 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1597 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1599 if (rewritten_event)
1600 gdk_event_free (rewritten_event);
1605 /* Push the event onto a stack of current events for
1606 * gtk_current_event_get().
1608 current_events = g_list_prepend (current_events, event);
1610 /* Not all events get sent to the grabbing widget.
1611 * The delete, destroy, expose, focus change and resize
1612 * events still get sent to the event widget because
1613 * 1) these events have no meaning for the grabbing widget
1614 * and 2) redirecting these events to the grabbing widget
1615 * could cause the display to be messed up.
1617 * Drag events are also not redirected, since it isn't
1618 * clear what the semantics of that would be.
1620 switch (event->type)
1626 g_object_ref (event_widget);
1627 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1628 !gtk_widget_event (event_widget, event))
1629 gtk_widget_destroy (event_widget);
1630 g_object_unref (event_widget);
1634 /* Unexpected GDK_DESTROY from the outside, ignore for
1635 * child windows, handle like a GDK_DELETE for toplevels
1637 if (!gtk_widget_get_parent (event_widget))
1639 g_object_ref (event_widget);
1640 if (!gtk_widget_event (event_widget, event) &&
1641 gtk_widget_get_realized (event_widget))
1642 gtk_widget_destroy (event_widget);
1643 g_object_unref (event_widget);
1648 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1650 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1651 gtk_widget_send_expose (event_widget, event);
1652 gdk_window_end_paint (event->any.window);
1656 /* The app may paint with a previously allocated cairo_t,
1657 which will draw directly to the window. We can't catch cairo
1658 draw operations to automatically flush the window, thus we
1659 need to explicitly flush any outstanding moves or double
1661 gdk_window_flush (event->any.window);
1662 gtk_widget_send_expose (event_widget, event);
1666 case GDK_PROPERTY_NOTIFY:
1667 case GDK_FOCUS_CHANGE:
1671 case GDK_SELECTION_CLEAR:
1672 case GDK_SELECTION_REQUEST:
1673 case GDK_SELECTION_NOTIFY:
1674 case GDK_CLIENT_EVENT:
1675 case GDK_VISIBILITY_NOTIFY:
1676 case GDK_WINDOW_STATE:
1677 case GDK_GRAB_BROKEN:
1679 gtk_widget_event (event_widget, event);
1683 case GDK_BUTTON_PRESS:
1684 case GDK_2BUTTON_PRESS:
1685 case GDK_3BUTTON_PRESS:
1686 gtk_propagate_event (grab_widget, event);
1690 case GDK_KEY_RELEASE:
1693 if (gtk_invoke_key_snoopers (grab_widget, event))
1696 /* Catch alt press to enable auto-mnemonics;
1697 * menus are handled elsewhere
1699 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1700 !GTK_IS_MENU_SHELL (grab_widget))
1702 gboolean auto_mnemonics;
1704 g_object_get (gtk_widget_get_settings (grab_widget),
1705 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1709 gboolean mnemonics_visible;
1712 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1714 window = gtk_widget_get_toplevel (grab_widget);
1716 if (GTK_IS_WINDOW (window))
1717 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1720 /* else fall through */
1721 case GDK_MOTION_NOTIFY:
1722 case GDK_BUTTON_RELEASE:
1723 case GDK_PROXIMITY_IN:
1724 case GDK_PROXIMITY_OUT:
1725 gtk_propagate_event (grab_widget, event);
1728 case GDK_ENTER_NOTIFY:
1729 _gtk_widget_set_device_window (event_widget,
1730 gdk_event_get_device (event),
1732 if (gtk_widget_is_sensitive (grab_widget))
1733 gtk_widget_event (grab_widget, event);
1736 case GDK_LEAVE_NOTIFY:
1737 _gtk_widget_set_device_window (event_widget,
1738 gdk_event_get_device (event),
1740 if (gtk_widget_is_sensitive (grab_widget))
1741 gtk_widget_event (grab_widget, event);
1744 case GDK_DRAG_STATUS:
1745 case GDK_DROP_FINISHED:
1746 _gtk_drag_source_handle_event (event_widget, event);
1748 case GDK_DRAG_ENTER:
1749 case GDK_DRAG_LEAVE:
1750 case GDK_DRAG_MOTION:
1751 case GDK_DROP_START:
1752 _gtk_drag_dest_handle_event (event_widget, event);
1755 g_assert_not_reached ();
1759 if (event->type == GDK_ENTER_NOTIFY
1760 || event->type == GDK_LEAVE_NOTIFY
1761 || event->type == GDK_BUTTON_PRESS
1762 || event->type == GDK_2BUTTON_PRESS
1763 || event->type == GDK_3BUTTON_PRESS
1764 || event->type == GDK_KEY_PRESS
1765 || event->type == GDK_DRAG_ENTER
1766 || event->type == GDK_GRAB_BROKEN
1767 || event->type == GDK_MOTION_NOTIFY
1768 || event->type == GDK_SCROLL)
1770 _gtk_tooltip_handle_event (event);
1773 tmp_list = current_events;
1774 current_events = g_list_remove_link (current_events, tmp_list);
1775 g_list_free_1 (tmp_list);
1777 if (rewritten_event)
1778 gdk_event_free (rewritten_event);
1793 static GtkWindowGroup *
1794 gtk_main_get_window_group (GtkWidget *widget)
1796 GtkWidget *toplevel = NULL;
1799 toplevel = gtk_widget_get_toplevel (widget);
1801 if (GTK_IS_WINDOW (toplevel))
1802 return gtk_window_get_group (GTK_WINDOW (toplevel));
1804 return gtk_window_get_group (NULL);
1809 GtkWidget *old_grab_widget;
1810 GtkWidget *new_grab_widget;
1811 gboolean was_grabbed;
1812 gboolean is_grabbed;
1814 GList *notified_windows;
1819 synth_crossing_for_grab_notify (GtkWidget *from,
1821 GrabNotifyInfo *info,
1823 GdkCrossingMode mode)
1827 GdkDevice *device = devices->data;
1828 GdkWindow *from_window, *to_window;
1830 /* Do not propagate events more than once to
1831 * the same windows if non-multidevice aware.
1837 from_window = _gtk_widget_get_device_window (from, device);
1840 !gdk_window_get_support_multidevice (from_window) &&
1841 g_list_find (info->notified_windows, from_window))
1849 to_window = _gtk_widget_get_device_window (to, device);
1852 !gdk_window_get_support_multidevice (to_window) &&
1853 g_list_find (info->notified_windows, to_window))
1857 if (from_window || to_window)
1859 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1860 (to_window) ? to : NULL,
1864 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1867 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1870 devices = devices->next;
1875 gtk_grab_notify_foreach (GtkWidget *child,
1878 GrabNotifyInfo *info = data;
1879 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1882 was_grabbed = info->was_grabbed;
1883 is_grabbed = info->is_grabbed;
1885 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1886 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1888 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1889 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1891 g_object_ref (child);
1893 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1894 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1897 _gtk_widget_get_device_window (child, info->device))
1899 /* Device specified and is on widget */
1900 devices = g_list_prepend (NULL, info->device);
1903 devices = _gtk_widget_list_devices (child);
1907 _gtk_widget_set_shadowed (child, TRUE);
1908 if (!was_shadowed && devices &&
1909 gtk_widget_is_sensitive (child))
1910 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1912 GDK_CROSSING_GTK_GRAB);
1916 _gtk_widget_set_shadowed (child, FALSE);
1917 if (was_shadowed && devices &&
1918 gtk_widget_is_sensitive (child))
1919 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1921 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1922 GDK_CROSSING_GTK_UNGRAB);
1925 if (was_shadowed != is_shadowed)
1926 _gtk_widget_grab_notify (child, was_shadowed);
1928 g_object_unref (child);
1929 g_list_free (devices);
1931 info->was_grabbed = was_grabbed;
1932 info->is_grabbed = is_grabbed;
1936 gtk_grab_notify (GtkWindowGroup *group,
1938 GtkWidget *old_grab_widget,
1939 GtkWidget *new_grab_widget,
1943 GrabNotifyInfo info = { 0 };
1945 if (old_grab_widget == new_grab_widget)
1948 info.old_grab_widget = old_grab_widget;
1949 info.new_grab_widget = new_grab_widget;
1950 info.from_grab = from_grab;
1951 info.device = device;
1953 g_object_ref (group);
1955 toplevels = gtk_window_list_toplevels ();
1956 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1960 GtkWindow *toplevel = toplevels->data;
1961 toplevels = g_list_delete_link (toplevels, toplevels);
1963 info.was_grabbed = FALSE;
1964 info.is_grabbed = FALSE;
1966 if (group == gtk_window_get_group (toplevel))
1967 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1968 g_object_unref (toplevel);
1971 g_list_free (info.notified_windows);
1972 g_object_unref (group);
1976 gtk_grab_add (GtkWidget *widget)
1978 GtkWindowGroup *group;
1979 GtkWidget *old_grab_widget;
1981 g_return_if_fail (widget != NULL);
1983 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1985 _gtk_widget_set_has_grab (widget, TRUE);
1987 group = gtk_main_get_window_group (widget);
1990 old_grab_widget = (GtkWidget *)group->grabs->data;
1992 old_grab_widget = NULL;
1994 g_object_ref (widget);
1995 group->grabs = g_slist_prepend (group->grabs, widget);
1997 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
2002 * gtk_grab_get_current:
2004 * Queries the current grab of the default window group.
2006 * Return value: (transfer none): The widget which currently
2007 * has the grab or %NULL if no grab is active
2010 gtk_grab_get_current (void)
2012 GtkWindowGroup *group;
2014 group = gtk_main_get_window_group (NULL);
2017 return GTK_WIDGET (group->grabs->data);
2022 gtk_grab_remove (GtkWidget *widget)
2024 GtkWindowGroup *group;
2025 GtkWidget *new_grab_widget;
2027 g_return_if_fail (widget != NULL);
2029 if (gtk_widget_has_grab (widget))
2031 _gtk_widget_set_has_grab (widget, FALSE);
2033 group = gtk_main_get_window_group (widget);
2034 group->grabs = g_slist_remove (group->grabs, widget);
2037 new_grab_widget = (GtkWidget *)group->grabs->data;
2039 new_grab_widget = NULL;
2041 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2043 g_object_unref (widget);
2048 * gtk_device_grab_add:
2049 * @widget: a #GtkWidget
2050 * @device: a #GtkDevice to grab on.
2051 * @block_others: %TRUE to prevent other devices to interact with @widget.
2053 * Adds a GTK+ grab on @device, so all the events on @device and its
2054 * associated pointer or keyboard (if any) are delivered to @widget.
2055 * If the @block_others parameter is %TRUE, any other devices will be
2056 * unable to interact with @widget during the grab.
2061 gtk_device_grab_add (GtkWidget *widget,
2063 gboolean block_others)
2065 GtkWindowGroup *group;
2066 GtkWidget *old_grab_widget;
2068 g_return_if_fail (GTK_IS_WIDGET (widget));
2069 g_return_if_fail (GDK_IS_DEVICE (device));
2071 group = gtk_main_get_window_group (widget);
2072 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2074 if (old_grab_widget != widget)
2075 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2077 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2081 * gtk_device_grab_remove:
2082 * @widget: a #GtkWidget
2083 * @device: a #GdkDevice
2085 * Removes a device grab from the given widget. You have to pair calls
2086 * to gtk_device_grab_add() and gtk_device_grab_remove().
2091 gtk_device_grab_remove (GtkWidget *widget,
2094 GtkWindowGroup *group;
2095 GtkWidget *new_grab_widget;
2097 g_return_if_fail (GTK_IS_WIDGET (widget));
2098 g_return_if_fail (GDK_IS_DEVICE (device));
2100 group = gtk_main_get_window_group (widget);
2101 _gtk_window_group_remove_device_grab (group, widget, device);
2102 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2104 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2108 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2111 GtkKeySnooperData *data;
2112 static guint snooper_id = 1;
2114 g_return_val_if_fail (snooper != NULL, 0);
2116 data = g_new (GtkKeySnooperData, 1);
2117 data->func = snooper;
2118 data->func_data = func_data;
2119 data->id = snooper_id++;
2120 key_snoopers = g_slist_prepend (key_snoopers, data);
2126 gtk_key_snooper_remove (guint snooper_id)
2128 GtkKeySnooperData *data = NULL;
2131 slist = key_snoopers;
2135 if (data->id == snooper_id)
2138 slist = slist->next;
2143 key_snoopers = g_slist_remove (key_snoopers, data);
2149 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2153 gint return_val = FALSE;
2155 slist = key_snoopers;
2156 while (slist && !return_val)
2158 GtkKeySnooperData *data;
2161 slist = slist->next;
2162 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2169 gtk_quit_add_full (guint main_level,
2170 GtkFunction function,
2171 GtkCallbackMarshal marshal,
2173 GDestroyNotify destroy)
2175 static guint quit_id = 1;
2176 GtkQuitFunction *quitf;
2178 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2180 quitf = g_slice_new (GtkQuitFunction);
2182 quitf->id = quit_id++;
2183 quitf->main_level = main_level;
2184 quitf->function = function;
2185 quitf->marshal = marshal;
2187 quitf->destroy = destroy;
2189 quit_functions = g_list_prepend (quit_functions, quitf);
2195 gtk_quit_destroy (GtkQuitFunction *quitf)
2198 quitf->destroy (quitf->data);
2199 g_slice_free (GtkQuitFunction, quitf);
2203 gtk_quit_destructor (GtkWidget **object_p)
2206 gtk_widget_destroy (*object_p);
2213 gtk_quit_add_destroy (guint main_level,
2216 GtkWidget **object_p;
2218 g_return_if_fail (main_level > 0);
2219 g_return_if_fail (GTK_IS_WIDGET (object));
2221 object_p = g_new (GtkWidget*, 1);
2223 g_signal_connect (object,
2225 G_CALLBACK (gtk_widget_destroyed),
2227 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2231 gtk_quit_add (guint main_level,
2232 GtkFunction function,
2235 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2239 gtk_quit_remove (guint id)
2241 GtkQuitFunction *quitf;
2244 tmp_list = quit_functions;
2247 quitf = tmp_list->data;
2249 if (quitf->id == id)
2251 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2252 g_list_free (tmp_list);
2253 gtk_quit_destroy (quitf);
2258 tmp_list = tmp_list->next;
2263 gtk_quit_remove_by_data (gpointer data)
2265 GtkQuitFunction *quitf;
2268 tmp_list = quit_functions;
2271 quitf = tmp_list->data;
2273 if (quitf->data == data)
2275 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2276 g_list_free (tmp_list);
2277 gtk_quit_destroy (quitf);
2282 tmp_list = tmp_list->next;
2287 * gtk_get_current_event:
2289 * Obtains a copy of the event currently being processed by GTK+. For
2290 * example, if you get a "clicked" signal from #GtkButton, the current
2291 * event will be the #GdkEventButton that triggered the "clicked"
2292 * signal. The returned event must be freed with gdk_event_free().
2293 * If there is no current event, the function returns %NULL.
2295 * Return value: a copy of the current event, or %NULL if no current event.
2298 gtk_get_current_event (void)
2301 return gdk_event_copy (current_events->data);
2307 * gtk_get_current_event_time:
2309 * If there is a current event and it has a timestamp, return that
2310 * timestamp, otherwise return %GDK_CURRENT_TIME.
2312 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2315 gtk_get_current_event_time (void)
2318 return gdk_event_get_time (current_events->data);
2320 return GDK_CURRENT_TIME;
2324 * gtk_get_current_event_state:
2325 * @state: a location to store the state of the current event
2327 * If there is a current event and it has a state field, place
2328 * that state field in @state and return %TRUE, otherwise return
2331 * Return value: %TRUE if there was a current event and it had a state field
2334 gtk_get_current_event_state (GdkModifierType *state)
2336 g_return_val_if_fail (state != NULL, FALSE);
2339 return gdk_event_get_state (current_events->data, state);
2348 * gtk_get_current_event_device:
2350 * If there is a current event and it has a device, return that
2351 * device, otherwise return %NULL.
2353 * Returns: (transfer none): a #GdkDevice, or %NULL
2356 gtk_get_current_event_device (void)
2359 return gdk_event_get_device (current_events->data);
2365 * gtk_get_event_widget:
2366 * @event: a #GdkEvent
2368 * If @event is %NULL or the event was not associated with any widget,
2369 * returns %NULL, otherwise returns the widget that received the event
2372 * Return value: (transfer none): the widget that originally
2373 * received @event, or %NULL
2376 gtk_get_event_widget (GdkEvent *event)
2379 gpointer widget_ptr;
2382 if (event && event->any.window &&
2383 (event->type == GDK_DESTROY || !gdk_window_is_destroyed (event->any.window)))
2385 gdk_window_get_user_data (event->any.window, &widget_ptr);
2386 widget = widget_ptr;
2393 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2395 if (!quitf->marshal)
2396 return quitf->function (quitf->data);
2400 gint ret_val = FALSE;
2402 args[0].name = NULL;
2403 args[0].type = G_TYPE_BOOLEAN;
2404 args[0].d.pointer_data = &ret_val;
2405 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2413 * gtk_propagate_event:
2414 * @widget: a #GtkWidget
2417 * Sends an event to a widget, propagating the event to parent widgets
2418 * if the event remains unhandled. Events received by GTK+ from GDK
2419 * normally begin in gtk_main_do_event(). Depending on the type of
2420 * event, existence of modal dialogs, grabs, etc., the event may be
2421 * propagated; if so, this function is used. gtk_propagate_event()
2422 * calls gtk_widget_event() on each widget it decides to send the
2423 * event to. So gtk_widget_event() is the lowest-level function; it
2424 * simply emits the "event" and possibly an event-specific signal on a
2425 * widget. gtk_propagate_event() is a bit higher-level, and
2426 * gtk_main_do_event() is the highest level.
2428 * All that said, you most likely don't want to use any of these
2429 * functions; synthesizing events is rarely needed. Consider asking on
2430 * the mailing list for better ways to achieve your goals. For
2431 * example, use gdk_window_invalidate_rect() or
2432 * gtk_widget_queue_draw() instead of making up expose events.
2436 gtk_propagate_event (GtkWidget *widget,
2441 g_return_if_fail (GTK_IS_WIDGET (widget));
2442 g_return_if_fail (event != NULL);
2444 handled_event = FALSE;
2446 g_object_ref (widget);
2448 if ((event->type == GDK_KEY_PRESS) ||
2449 (event->type == GDK_KEY_RELEASE))
2451 /* Only send key events within Window widgets to the Window
2452 * The Window widget will in turn pass the
2453 * key event on to the currently focused widget
2458 window = gtk_widget_get_toplevel (widget);
2459 if (GTK_IS_WINDOW (window))
2461 /* If there is a grab within the window, give the grab widget
2462 * a first crack at the key event
2464 if (widget != window && gtk_widget_has_grab (widget))
2465 handled_event = gtk_widget_event (widget, event);
2469 window = gtk_widget_get_toplevel (widget);
2470 if (GTK_IS_WINDOW (window))
2472 if (gtk_widget_is_sensitive (window))
2473 gtk_widget_event (window, event);
2477 handled_event = TRUE; /* don't send to widget */
2481 /* Other events get propagated up the widget tree
2482 * so that parents can see the button and motion
2483 * events of the children.
2491 /* Scroll events are special cased here because it
2492 * feels wrong when scrolling a GtkViewport, say,
2493 * to have children of the viewport eat the scroll
2496 if (!gtk_widget_is_sensitive (widget))
2497 handled_event = event->type != GDK_SCROLL;
2499 handled_event = gtk_widget_event (widget, event);
2501 tmp = gtk_widget_get_parent (widget);
2502 g_object_unref (widget);
2506 if (!handled_event && widget)
2507 g_object_ref (widget);
2513 g_object_unref (widget);
2517 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2518 GValue *return_accu,
2519 const GValue *handler_return,
2522 gboolean continue_emission;
2523 gboolean signal_handled;
2525 signal_handled = g_value_get_boolean (handler_return);
2526 g_value_set_boolean (return_accu, signal_handled);
2527 continue_emission = !signal_handled;
2529 return continue_emission;