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 "gtkwindowprivate.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.
868 * This function is intended for GTK+ modules that want
869 * to adjust their debug output based on GTK+ debug flags.
871 * Returns: the GTK+ debug flags.
874 gtk_get_debug_flags (void)
880 * gtk_set_debug_flags:
882 * Sets the GTK+ debug flags.
885 gtk_set_debug_flags (guint flags)
891 * gtk_get_option_group:
892 * @open_default_display: whether to open the default display
893 * when parsing the commandline arguments
895 * Returns a #GOptionGroup for the commandline arguments recognized
896 * by GTK+ and GDK. You should add this group to your #GOptionContext
897 * with g_option_context_add_group(), if you are using
898 * g_option_context_parse() to parse your commandline arguments.
900 * Returns: a #GOptionGroup for the commandline arguments recognized
906 gtk_get_option_group (gboolean open_default_display)
909 OptionGroupInfo *info;
911 gettext_initialization ();
913 info = g_new0 (OptionGroupInfo, 1);
914 info->open_default_display = open_default_display;
916 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
917 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
919 gdk_add_option_entries_libgtk_only (group);
920 g_option_group_add_entries (group, gtk_args);
921 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
927 * gtk_init_with_args:
928 * @argc: a pointer to the number of command line arguments.
929 * @argv: a pointer to the array of command line arguments.
930 * @parameter_string: a string which is displayed in
931 * the first line of <option>--help</option> output, after
932 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
933 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
934 * describing the options of your program
935 * @translation_domain: a translation domain to use for translating
936 * the <option>--help</option> output for the options in @entries
937 * and the @parameter_string with gettext(), or %NULL
938 * @error: a return location for errors
940 * This function does the same work as gtk_init_check().
941 * Additionally, it allows you to add your own commandline options,
942 * and it automatically generates nicely formatted
943 * <option>--help</option> output. Note that your program will
944 * be terminated after writing out the help output.
946 * Returns: %TRUE if the GUI has been successfully initialized,
952 gtk_init_with_args (gint *argc,
954 const gchar *parameter_string,
955 const GOptionEntry *entries,
956 const gchar *translation_domain,
959 GOptionContext *context;
960 GOptionGroup *gtk_group;
964 return gdk_display_open_default_libgtk_only () != NULL;
966 gettext_initialization ();
968 if (!check_setugid ())
971 gtk_group = gtk_get_option_group (TRUE);
973 context = g_option_context_new (parameter_string);
974 g_option_context_add_group (context, gtk_group);
975 g_option_context_set_translation_domain (context, translation_domain);
978 g_option_context_add_main_entries (context, entries, translation_domain);
979 retval = g_option_context_parse (context, argc, argv, error);
981 g_option_context_free (context);
989 * @argc: (inout): a pointer to the number of command line arguments.
990 * @argv: (array) (inout): a pointer to the array of command line arguments.
992 * Parses command line arguments, and initializes global
993 * attributes of GTK+, but does not actually open a connection
994 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
996 * Any arguments used by GTK+ or GDK are removed from the array and
997 * @argc and @argv are updated accordingly.
999 * You shouldn't call this function explicitely if you are using
1000 * gtk_init(), or gtk_init_check().
1002 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1005 gtk_parse_args (int *argc,
1008 GOptionContext *option_context;
1009 GOptionGroup *gtk_group;
1010 GError *error = NULL;
1012 if (gtk_initialized)
1015 gettext_initialization ();
1017 if (!check_setugid ())
1020 option_context = g_option_context_new (NULL);
1021 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1022 g_option_context_set_help_enabled (option_context, FALSE);
1023 gtk_group = gtk_get_option_group (FALSE);
1024 g_option_context_set_main_group (option_context, gtk_group);
1025 if (!g_option_context_parse (option_context, argc, argv, &error))
1027 g_warning ("%s", error->message);
1028 g_error_free (error);
1031 g_option_context_free (option_context);
1036 #ifdef G_PLATFORM_WIN32
1037 #undef gtk_init_check
1042 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1043 * main() function. Changed if any arguments were handled.
1044 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1045 * Any parameters understood by gtk_init() are stripped before return.
1047 * This function does the same work as gtk_init() with only
1048 * a single change: It does not terminate the program if the GUI can't be
1049 * initialized. Instead it returns %FALSE on failure.
1051 * This way the application can fall back to some other means of communication
1052 * with the user - for example a curses or command line interface.
1054 * Return value: %TRUE if the GUI has been successfully initialized,
1058 gtk_init_check (int *argc,
1061 if (!gtk_parse_args (argc, argv))
1064 return gdk_display_open_default_libgtk_only () != NULL;
1067 #ifdef G_PLATFORM_WIN32
1073 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1074 * main() function. Changed if any arguments were handled.
1075 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1076 * Any parameters understood by gtk_init() are stripped before return.
1078 * Call this function before using any other GTK+ functions in your GUI
1079 * applications. It will initialize everything needed to operate the
1080 * toolkit and parses some standard command line options. @argc and
1081 * @argv are adjusted accordingly so your own code will
1082 * never see those standard arguments.
1084 * Note that there are some alternative ways to initialize GTK+:
1085 * if you are calling gtk_parse_args(), gtk_init_check(),
1086 * gtk_init_with_args() or g_option_context_parse() with
1087 * the option group returned by gtk_get_option_group(), you
1088 * <emphasis>don't</emphasis> have to call gtk_init().
1091 * This function will terminate your program if it was unable to initialize
1092 * the GUI for some reason. If you want your program to fall back to a
1093 * textual interface you want to call gtk_init_check() instead.
1097 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1098 * during initialization, to ignore SIGPIPE signals, since these are
1099 * almost never wanted in graphical applications. If you do need to
1100 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1101 * but notice that other libraries (e.g. libdbus or gvfs) might do
1106 gtk_init (int *argc, char ***argv)
1108 if (!gtk_init_check (argc, argv))
1110 const char *display_name_arg = gdk_get_display_arg_name ();
1111 if (display_name_arg == NULL)
1112 display_name_arg = getenv("DISPLAY");
1113 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1118 #ifdef G_PLATFORM_WIN32
1121 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1123 if (sizeof_GtkWindow != sizeof (GtkWindow))
1124 g_error ("Incompatible build!\n"
1125 "The code using GTK+ thinks GtkWindow is of different\n"
1126 "size than it actually is in this build of GTK+.\n"
1127 "On Windows, this probably means that you have compiled\n"
1128 "your code with gcc without the -mms-bitfields switch,\n"
1129 "or that you are using an unsupported compiler.");
1132 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1133 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1134 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1135 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1136 * -fnative-struct still matters. GtkBox is one such.
1139 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1141 if (sizeof_GtkBox != sizeof (GtkBox))
1142 g_error ("Incompatible build!\n"
1143 "The code using GTK+ thinks GtkBox is of different\n"
1144 "size than it actually is in this build of GTK+.\n"
1145 "On Windows, this probably means that you have compiled\n"
1146 "your code with gcc without the -mms-bitfields switch,\n"
1147 "or that you are using an unsupported compiler.");
1150 /* These two functions might get more checks added later, thus pass
1151 * in the number of extra args.
1154 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1156 check_sizeof_GtkWindow (sizeof_GtkWindow);
1157 if (num_checks >= 2)
1158 check_sizeof_GtkBox (sizeof_GtkBox);
1159 gtk_init (argc, argv);
1163 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1165 check_sizeof_GtkWindow (sizeof_GtkWindow);
1166 if (num_checks >= 2)
1167 check_sizeof_GtkBox (sizeof_GtkBox);
1168 return gtk_init_check (argc, argv);
1176 * Initializes internationalization support for GTK+. gtk_init()
1177 * automatically does this, so there is typically no point
1178 * in calling this function.
1180 * If you are calling this function because you changed the locale
1181 * after GTK+ is was initialized, then calling this function
1182 * may help a bit. (Note, however, that changing the locale
1183 * after GTK+ is initialized may produce inconsistent results and
1184 * is not really supported.)
1186 * In detail - sets the current locale according to the
1187 * program environment. This is the same as calling the C library function
1188 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1189 * locale specific setup of the windowing system used by GDK.
1191 * Returns: a string corresponding to the locale set, typically in the
1192 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1193 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1194 * result of the setlocale(); it is also used on other machines, such as
1195 * Windows, where the C library returns a different result. The string is
1196 * owned by GTK+ and should not be modified or freed.
1199 gtk_set_locale (void)
1201 return gdk_set_locale ();
1205 * _gtk_get_lc_ctype:
1207 * Return the Unix-style locale string for the language currently in
1208 * effect. On Unix systems, this is the return value from
1209 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1210 * affect this through the environment variables LC_ALL, LC_CTYPE or
1211 * LANG (checked in that order). The locale strings typically is in
1212 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1213 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1214 * Swedish as written in Finland or pt_BR for Portuguese as written in
1217 * On Windows, the C library doesn't use any such environment
1218 * variables, and setting them won't affect the behaviour of functions
1219 * like ctime(). The user sets the locale through the Regional Options
1220 * in the Control Panel. The C library (in the setlocale() function)
1221 * does not use country and language codes, but country and language
1222 * names spelled out in English.
1223 * However, this function does check the above environment
1224 * variables, and does return a Unix-style locale string based on
1225 * either said environment variables or the thread's current locale.
1227 * Return value: a dynamically allocated string, free with g_free().
1231 _gtk_get_lc_ctype (void)
1234 /* Somebody might try to set the locale for this process using the
1235 * LANG or LC_ environment variables. The Microsoft C library
1236 * doesn't know anything about them. You set the locale in the
1237 * Control Panel. Setting these env vars won't have any affect on
1238 * locale-dependent C library functions like ctime(). But just for
1239 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1240 * it easier to test GTK and Pango in various default languages, you
1241 * don't have to clickety-click in the Control Panel, you can simply
1242 * start the program with LC_ALL=something on the command line.)
1246 p = getenv ("LC_ALL");
1248 return g_strdup (p);
1250 p = getenv ("LC_CTYPE");
1252 return g_strdup (p);
1254 p = getenv ("LANG");
1256 return g_strdup (p);
1258 return g_win32_getlocale ();
1260 return g_strdup (setlocale (LC_CTYPE, NULL));
1265 * gtk_get_default_language:
1267 * Returns the #PangoLanguage for the default language currently in
1268 * effect. (Note that this can change over the life of an
1269 * application.) The default language is derived from the current
1270 * locale. It determines, for example, whether GTK+ uses the
1271 * right-to-left or left-to-right text direction.
1273 * This function is equivalent to pango_language_get_default(). See
1274 * that function for details.
1276 * Return value: the default language as a #PangoLanguage, must not be
1280 gtk_get_default_language (void)
1282 return pango_language_get_default ();
1291 gtk_main_loop_level++;
1293 loop = g_main_loop_new (NULL, TRUE);
1294 main_loops = g_slist_prepend (main_loops, loop);
1296 if (g_main_loop_is_running (main_loops->data))
1298 GDK_THREADS_LEAVE ();
1299 g_main_loop_run (loop);
1300 GDK_THREADS_ENTER ();
1306 GList *reinvoke_list = NULL;
1307 GtkQuitFunction *quitf;
1309 while (quit_functions)
1311 quitf = quit_functions->data;
1313 tmp_list = quit_functions;
1314 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1315 g_list_free_1 (tmp_list);
1317 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1318 gtk_quit_invoke_function (quitf))
1320 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1324 gtk_quit_destroy (quitf);
1331 work = g_list_last (reinvoke_list);
1333 quit_functions->prev = work;
1334 work->next = quit_functions;
1335 quit_functions = work;
1341 main_loops = g_slist_remove (main_loops, loop);
1343 g_main_loop_unref (loop);
1345 gtk_main_loop_level--;
1347 if (gtk_main_loop_level == 0)
1349 /* Try storing all clipboard data we have */
1350 _gtk_clipboard_store_all ();
1352 /* Synchronize the recent manager singleton */
1353 _gtk_recent_manager_sync ();
1358 gtk_main_level (void)
1360 return gtk_main_loop_level;
1364 gtk_main_quit (void)
1366 g_return_if_fail (main_loops != NULL);
1368 g_main_loop_quit (main_loops->data);
1372 gtk_events_pending (void)
1376 GDK_THREADS_LEAVE ();
1377 result = g_main_context_pending (NULL);
1378 GDK_THREADS_ENTER ();
1384 gtk_main_iteration (void)
1386 GDK_THREADS_LEAVE ();
1387 g_main_context_iteration (NULL, TRUE);
1388 GDK_THREADS_ENTER ();
1391 return !g_main_loop_is_running (main_loops->data);
1397 gtk_main_iteration_do (gboolean blocking)
1399 GDK_THREADS_LEAVE ();
1400 g_main_context_iteration (NULL, blocking);
1401 GDK_THREADS_ENTER ();
1404 return !g_main_loop_is_running (main_loops->data);
1409 /* private libgtk to libgdk interfaces
1411 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1413 GdkWindow **grab_window,
1414 gboolean *owner_events);
1417 rewrite_events_translate (GdkWindow *old_window,
1418 GdkWindow *new_window,
1422 gint old_origin_x, old_origin_y;
1423 gint new_origin_x, new_origin_y;
1425 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1426 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1428 *x += old_origin_x - new_origin_x;
1429 *y += old_origin_y - new_origin_y;
1433 rewrite_event_for_window (GdkEvent *event,
1434 GdkWindow *new_window)
1436 event = gdk_event_copy (event);
1438 switch (event->type)
1441 rewrite_events_translate (event->any.window,
1443 &event->scroll.x, &event->scroll.y);
1445 case GDK_BUTTON_PRESS:
1446 case GDK_2BUTTON_PRESS:
1447 case GDK_3BUTTON_PRESS:
1448 case GDK_BUTTON_RELEASE:
1449 rewrite_events_translate (event->any.window,
1451 &event->button.x, &event->button.y);
1453 case GDK_MOTION_NOTIFY:
1454 rewrite_events_translate (event->any.window,
1456 &event->motion.x, &event->motion.y);
1459 case GDK_KEY_RELEASE:
1460 case GDK_PROXIMITY_IN:
1461 case GDK_PROXIMITY_OUT:
1468 g_object_unref (event->any.window);
1469 event->any.window = g_object_ref (new_window);
1474 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1475 * then what X11 does is deliver the event normally if it was going to this
1476 * client, otherwise, delivers it in terms of the grab window. This function
1477 * rewrites events to the effect that events going to the same window group
1478 * are delivered normally, otherwise, the event is delivered in terms of the
1482 rewrite_event_for_grabs (GdkEvent *event)
1484 GdkWindow *grab_window;
1485 GtkWidget *event_widget, *grab_widget;
1486 gpointer grab_widget_ptr;
1487 gboolean owner_events;
1488 GdkDisplay *display;
1491 switch (event->type)
1494 case GDK_BUTTON_PRESS:
1495 case GDK_2BUTTON_PRESS:
1496 case GDK_3BUTTON_PRESS:
1497 case GDK_BUTTON_RELEASE:
1498 case GDK_MOTION_NOTIFY:
1499 case GDK_PROXIMITY_IN:
1500 case GDK_PROXIMITY_OUT:
1502 case GDK_KEY_RELEASE:
1503 display = gdk_window_get_display (event->any.window);
1504 device = gdk_event_get_device (event);
1506 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1514 event_widget = gtk_get_event_widget (event);
1515 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1516 grab_widget = grab_widget_ptr;
1519 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1520 return rewrite_event_for_window (event, grab_window);
1526 gtk_main_do_event (GdkEvent *event)
1528 GtkWidget *event_widget;
1529 GtkWidget *grab_widget = NULL;
1530 GtkWindowGroup *window_group;
1531 GdkEvent *rewritten_event = NULL;
1535 if (event->type == GDK_SETTING)
1537 _gtk_settings_handle_event (&event->setting);
1541 if (event->type == GDK_OWNER_CHANGE)
1543 _gtk_clipboard_handle_event (&event->owner_change);
1547 /* Find the widget which got the event. We store the widget
1548 * in the user_data field of GdkWindow's.
1549 * Ignore the event if we don't have a widget for it, except
1550 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1551 * Though this happens rarely, bogus events can occour
1552 * for e.g. destroyed GdkWindows.
1554 event_widget = gtk_get_event_widget (event);
1557 /* To handle selection INCR transactions, we select
1558 * PropertyNotify events on the requestor window and create
1559 * a corresponding (fake) GdkWindow so that events get
1560 * here. There won't be a widget though, so we have to handle
1563 if (event->type == GDK_PROPERTY_NOTIFY)
1564 _gtk_selection_incr_event (event->any.window,
1570 /* If pointer or keyboard grabs are in effect, munge the events
1571 * so that each window group looks like a separate app.
1573 rewritten_event = rewrite_event_for_grabs (event);
1574 if (rewritten_event)
1576 event = rewritten_event;
1577 event_widget = gtk_get_event_widget (event);
1580 window_group = gtk_main_get_window_group (event_widget);
1581 device = gdk_event_get_device (event);
1583 /* check whether there is a (device) grab in effect...
1586 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1589 grab_widget = gtk_window_group_get_current_grab (window_group);
1591 /* If the grab widget is an ancestor of the event widget
1592 * then we send the event to the original event widget.
1593 * This is the key to implementing modality.
1596 (gtk_widget_is_sensitive (event_widget) &&
1597 gtk_widget_is_ancestor (event_widget, grab_widget)))
1598 grab_widget = event_widget;
1600 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1602 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1604 if (rewritten_event)
1605 gdk_event_free (rewritten_event);
1610 /* Push the event onto a stack of current events for
1611 * gtk_current_event_get().
1613 current_events = g_list_prepend (current_events, event);
1615 /* Not all events get sent to the grabbing widget.
1616 * The delete, destroy, expose, focus change and resize
1617 * events still get sent to the event widget because
1618 * 1) these events have no meaning for the grabbing widget
1619 * and 2) redirecting these events to the grabbing widget
1620 * could cause the display to be messed up.
1622 * Drag events are also not redirected, since it isn't
1623 * clear what the semantics of that would be.
1625 switch (event->type)
1631 g_object_ref (event_widget);
1632 if ((!gtk_window_group_get_current_grab (window_group) || gtk_widget_get_toplevel (gtk_window_group_get_current_grab (window_group)) == event_widget) &&
1633 !gtk_widget_event (event_widget, event))
1634 gtk_widget_destroy (event_widget);
1635 g_object_unref (event_widget);
1639 /* Unexpected GDK_DESTROY from the outside, ignore for
1640 * child windows, handle like a GDK_DELETE for toplevels
1642 if (!gtk_widget_get_parent (event_widget))
1644 g_object_ref (event_widget);
1645 if (!gtk_widget_event (event_widget, event) &&
1646 gtk_widget_get_realized (event_widget))
1647 gtk_widget_destroy (event_widget);
1648 g_object_unref (event_widget);
1653 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1655 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1656 gtk_widget_send_expose (event_widget, event);
1657 gdk_window_end_paint (event->any.window);
1661 /* The app may paint with a previously allocated cairo_t,
1662 which will draw directly to the window. We can't catch cairo
1663 draw operations to automatically flush the window, thus we
1664 need to explicitly flush any outstanding moves or double
1666 gdk_window_flush (event->any.window);
1667 gtk_widget_send_expose (event_widget, event);
1671 case GDK_PROPERTY_NOTIFY:
1672 case GDK_FOCUS_CHANGE:
1676 case GDK_SELECTION_CLEAR:
1677 case GDK_SELECTION_REQUEST:
1678 case GDK_SELECTION_NOTIFY:
1679 case GDK_CLIENT_EVENT:
1680 case GDK_VISIBILITY_NOTIFY:
1681 case GDK_WINDOW_STATE:
1682 case GDK_GRAB_BROKEN:
1684 gtk_widget_event (event_widget, event);
1688 case GDK_BUTTON_PRESS:
1689 case GDK_2BUTTON_PRESS:
1690 case GDK_3BUTTON_PRESS:
1691 gtk_propagate_event (grab_widget, event);
1695 case GDK_KEY_RELEASE:
1698 if (gtk_invoke_key_snoopers (grab_widget, event))
1701 /* Catch alt press to enable auto-mnemonics;
1702 * menus are handled elsewhere
1704 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1705 !GTK_IS_MENU_SHELL (grab_widget))
1707 gboolean auto_mnemonics;
1709 g_object_get (gtk_widget_get_settings (grab_widget),
1710 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1714 gboolean mnemonics_visible;
1717 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1719 window = gtk_widget_get_toplevel (grab_widget);
1721 if (GTK_IS_WINDOW (window))
1722 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1725 /* else fall through */
1726 case GDK_MOTION_NOTIFY:
1727 case GDK_BUTTON_RELEASE:
1728 case GDK_PROXIMITY_IN:
1729 case GDK_PROXIMITY_OUT:
1730 gtk_propagate_event (grab_widget, event);
1733 case GDK_ENTER_NOTIFY:
1734 _gtk_widget_set_device_window (event_widget,
1735 gdk_event_get_device (event),
1737 if (gtk_widget_is_sensitive (grab_widget))
1738 gtk_widget_event (grab_widget, event);
1741 case GDK_LEAVE_NOTIFY:
1742 _gtk_widget_set_device_window (event_widget,
1743 gdk_event_get_device (event),
1745 if (gtk_widget_is_sensitive (grab_widget))
1746 gtk_widget_event (grab_widget, event);
1749 case GDK_DRAG_STATUS:
1750 case GDK_DROP_FINISHED:
1751 _gtk_drag_source_handle_event (event_widget, event);
1753 case GDK_DRAG_ENTER:
1754 case GDK_DRAG_LEAVE:
1755 case GDK_DRAG_MOTION:
1756 case GDK_DROP_START:
1757 _gtk_drag_dest_handle_event (event_widget, event);
1760 g_assert_not_reached ();
1764 if (event->type == GDK_ENTER_NOTIFY
1765 || event->type == GDK_LEAVE_NOTIFY
1766 || event->type == GDK_BUTTON_PRESS
1767 || event->type == GDK_2BUTTON_PRESS
1768 || event->type == GDK_3BUTTON_PRESS
1769 || event->type == GDK_KEY_PRESS
1770 || event->type == GDK_DRAG_ENTER
1771 || event->type == GDK_GRAB_BROKEN
1772 || event->type == GDK_MOTION_NOTIFY
1773 || event->type == GDK_SCROLL)
1775 _gtk_tooltip_handle_event (event);
1778 tmp_list = current_events;
1779 current_events = g_list_remove_link (current_events, tmp_list);
1780 g_list_free_1 (tmp_list);
1782 if (rewritten_event)
1783 gdk_event_free (rewritten_event);
1798 static GtkWindowGroup *
1799 gtk_main_get_window_group (GtkWidget *widget)
1801 GtkWidget *toplevel = NULL;
1804 toplevel = gtk_widget_get_toplevel (widget);
1806 if (GTK_IS_WINDOW (toplevel))
1807 return gtk_window_get_group (GTK_WINDOW (toplevel));
1809 return gtk_window_get_group (NULL);
1814 GtkWidget *old_grab_widget;
1815 GtkWidget *new_grab_widget;
1816 gboolean was_grabbed;
1817 gboolean is_grabbed;
1819 GList *notified_windows;
1824 synth_crossing_for_grab_notify (GtkWidget *from,
1826 GrabNotifyInfo *info,
1828 GdkCrossingMode mode)
1832 GdkDevice *device = devices->data;
1833 GdkWindow *from_window, *to_window;
1835 /* Do not propagate events more than once to
1836 * the same windows if non-multidevice aware.
1842 from_window = _gtk_widget_get_device_window (from, device);
1845 !gdk_window_get_support_multidevice (from_window) &&
1846 g_list_find (info->notified_windows, from_window))
1854 to_window = _gtk_widget_get_device_window (to, device);
1857 !gdk_window_get_support_multidevice (to_window) &&
1858 g_list_find (info->notified_windows, to_window))
1862 if (from_window || to_window)
1864 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1865 (to_window) ? to : NULL,
1869 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1872 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1875 devices = devices->next;
1880 gtk_grab_notify_foreach (GtkWidget *child,
1883 GrabNotifyInfo *info = data;
1884 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1887 was_grabbed = info->was_grabbed;
1888 is_grabbed = info->is_grabbed;
1890 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1891 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1893 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1894 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1896 g_object_ref (child);
1898 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1899 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1902 _gtk_widget_get_device_window (child, info->device))
1904 /* Device specified and is on widget */
1905 devices = g_list_prepend (NULL, info->device);
1908 devices = _gtk_widget_list_devices (child);
1912 _gtk_widget_set_shadowed (child, TRUE);
1913 if (!was_shadowed && devices &&
1914 gtk_widget_is_sensitive (child))
1915 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1917 GDK_CROSSING_GTK_GRAB);
1921 _gtk_widget_set_shadowed (child, FALSE);
1922 if (was_shadowed && devices &&
1923 gtk_widget_is_sensitive (child))
1924 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1926 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1927 GDK_CROSSING_GTK_UNGRAB);
1930 if (was_shadowed != is_shadowed)
1931 _gtk_widget_grab_notify (child, was_shadowed);
1933 g_object_unref (child);
1934 g_list_free (devices);
1936 info->was_grabbed = was_grabbed;
1937 info->is_grabbed = is_grabbed;
1941 gtk_grab_notify (GtkWindowGroup *group,
1943 GtkWidget *old_grab_widget,
1944 GtkWidget *new_grab_widget,
1948 GrabNotifyInfo info = { 0 };
1950 if (old_grab_widget == new_grab_widget)
1953 info.old_grab_widget = old_grab_widget;
1954 info.new_grab_widget = new_grab_widget;
1955 info.from_grab = from_grab;
1956 info.device = device;
1958 g_object_ref (group);
1960 toplevels = gtk_window_list_toplevels ();
1961 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1965 GtkWindow *toplevel = toplevels->data;
1966 toplevels = g_list_delete_link (toplevels, toplevels);
1968 info.was_grabbed = FALSE;
1969 info.is_grabbed = FALSE;
1971 if (group == gtk_window_get_group (toplevel))
1972 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1973 g_object_unref (toplevel);
1976 g_list_free (info.notified_windows);
1977 g_object_unref (group);
1981 gtk_grab_add (GtkWidget *widget)
1983 GtkWindowGroup *group;
1984 GtkWidget *old_grab_widget;
1986 g_return_if_fail (widget != NULL);
1988 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1990 _gtk_widget_set_has_grab (widget, TRUE);
1992 group = gtk_main_get_window_group (widget);
1994 old_grab_widget = gtk_window_group_get_current_grab (group);
1996 g_object_ref (widget);
1997 _gtk_window_group_add_grab (group, widget);
1999 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
2004 * gtk_grab_get_current:
2006 * Queries the current grab of the default window group.
2008 * Return value: (transfer none): The widget which currently
2009 * has the grab or %NULL if no grab is active
2012 gtk_grab_get_current (void)
2014 GtkWindowGroup *group;
2016 group = gtk_main_get_window_group (NULL);
2018 return gtk_window_group_get_current_grab (group);
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 _gtk_window_group_remove_grab (group, widget);
2035 new_grab_widget = gtk_window_group_get_current_grab (group);
2037 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2039 g_object_unref (widget);
2044 * gtk_device_grab_add:
2045 * @widget: a #GtkWidget
2046 * @device: a #GtkDevice to grab on.
2047 * @block_others: %TRUE to prevent other devices to interact with @widget.
2049 * Adds a GTK+ grab on @device, so all the events on @device and its
2050 * associated pointer or keyboard (if any) are delivered to @widget.
2051 * If the @block_others parameter is %TRUE, any other devices will be
2052 * unable to interact with @widget during the grab.
2057 gtk_device_grab_add (GtkWidget *widget,
2059 gboolean block_others)
2061 GtkWindowGroup *group;
2062 GtkWidget *old_grab_widget;
2064 g_return_if_fail (GTK_IS_WIDGET (widget));
2065 g_return_if_fail (GDK_IS_DEVICE (device));
2067 group = gtk_main_get_window_group (widget);
2068 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2070 if (old_grab_widget != widget)
2071 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2073 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2077 * gtk_device_grab_remove:
2078 * @widget: a #GtkWidget
2079 * @device: a #GdkDevice
2081 * Removes a device grab from the given widget. You have to pair calls
2082 * to gtk_device_grab_add() and gtk_device_grab_remove().
2087 gtk_device_grab_remove (GtkWidget *widget,
2090 GtkWindowGroup *group;
2091 GtkWidget *new_grab_widget;
2093 g_return_if_fail (GTK_IS_WIDGET (widget));
2094 g_return_if_fail (GDK_IS_DEVICE (device));
2096 group = gtk_main_get_window_group (widget);
2097 _gtk_window_group_remove_device_grab (group, widget, device);
2098 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2100 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2104 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2107 GtkKeySnooperData *data;
2108 static guint snooper_id = 1;
2110 g_return_val_if_fail (snooper != NULL, 0);
2112 data = g_new (GtkKeySnooperData, 1);
2113 data->func = snooper;
2114 data->func_data = func_data;
2115 data->id = snooper_id++;
2116 key_snoopers = g_slist_prepend (key_snoopers, data);
2122 gtk_key_snooper_remove (guint snooper_id)
2124 GtkKeySnooperData *data = NULL;
2127 slist = key_snoopers;
2131 if (data->id == snooper_id)
2134 slist = slist->next;
2139 key_snoopers = g_slist_remove (key_snoopers, data);
2145 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2149 gint return_val = FALSE;
2151 slist = key_snoopers;
2152 while (slist && !return_val)
2154 GtkKeySnooperData *data;
2157 slist = slist->next;
2158 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2165 gtk_quit_add_full (guint main_level,
2166 GtkFunction function,
2167 GtkCallbackMarshal marshal,
2169 GDestroyNotify destroy)
2171 static guint quit_id = 1;
2172 GtkQuitFunction *quitf;
2174 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2176 quitf = g_slice_new (GtkQuitFunction);
2178 quitf->id = quit_id++;
2179 quitf->main_level = main_level;
2180 quitf->function = function;
2181 quitf->marshal = marshal;
2183 quitf->destroy = destroy;
2185 quit_functions = g_list_prepend (quit_functions, quitf);
2191 gtk_quit_destroy (GtkQuitFunction *quitf)
2194 quitf->destroy (quitf->data);
2195 g_slice_free (GtkQuitFunction, quitf);
2199 gtk_quit_destructor (GtkWidget **object_p)
2202 gtk_widget_destroy (*object_p);
2209 gtk_quit_add_destroy (guint main_level,
2212 GtkWidget **object_p;
2214 g_return_if_fail (main_level > 0);
2215 g_return_if_fail (GTK_IS_WIDGET (object));
2217 object_p = g_new (GtkWidget*, 1);
2219 g_signal_connect (object,
2221 G_CALLBACK (gtk_widget_destroyed),
2223 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2227 gtk_quit_add (guint main_level,
2228 GtkFunction function,
2231 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2235 gtk_quit_remove (guint id)
2237 GtkQuitFunction *quitf;
2240 tmp_list = quit_functions;
2243 quitf = tmp_list->data;
2245 if (quitf->id == id)
2247 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2248 g_list_free (tmp_list);
2249 gtk_quit_destroy (quitf);
2254 tmp_list = tmp_list->next;
2259 gtk_quit_remove_by_data (gpointer data)
2261 GtkQuitFunction *quitf;
2264 tmp_list = quit_functions;
2267 quitf = tmp_list->data;
2269 if (quitf->data == data)
2271 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2272 g_list_free (tmp_list);
2273 gtk_quit_destroy (quitf);
2278 tmp_list = tmp_list->next;
2283 * gtk_get_current_event:
2285 * Obtains a copy of the event currently being processed by GTK+. For
2286 * example, if you get a "clicked" signal from #GtkButton, the current
2287 * event will be the #GdkEventButton that triggered the "clicked"
2288 * signal. The returned event must be freed with gdk_event_free().
2289 * If there is no current event, the function returns %NULL.
2291 * Return value: a copy of the current event, or %NULL if no current event.
2294 gtk_get_current_event (void)
2297 return gdk_event_copy (current_events->data);
2303 * gtk_get_current_event_time:
2305 * If there is a current event and it has a timestamp, return that
2306 * timestamp, otherwise return %GDK_CURRENT_TIME.
2308 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2311 gtk_get_current_event_time (void)
2314 return gdk_event_get_time (current_events->data);
2316 return GDK_CURRENT_TIME;
2320 * gtk_get_current_event_state:
2321 * @state: a location to store the state of the current event
2323 * If there is a current event and it has a state field, place
2324 * that state field in @state and return %TRUE, otherwise return
2327 * Return value: %TRUE if there was a current event and it had a state field
2330 gtk_get_current_event_state (GdkModifierType *state)
2332 g_return_val_if_fail (state != NULL, FALSE);
2335 return gdk_event_get_state (current_events->data, state);
2344 * gtk_get_current_event_device:
2346 * If there is a current event and it has a device, return that
2347 * device, otherwise return %NULL.
2349 * Returns: (transfer none): a #GdkDevice, or %NULL
2352 gtk_get_current_event_device (void)
2355 return gdk_event_get_device (current_events->data);
2361 * gtk_get_event_widget:
2362 * @event: a #GdkEvent
2364 * If @event is %NULL or the event was not associated with any widget,
2365 * returns %NULL, otherwise returns the widget that received the event
2368 * Return value: (transfer none): the widget that originally
2369 * received @event, or %NULL
2372 gtk_get_event_widget (GdkEvent *event)
2375 gpointer widget_ptr;
2378 if (event && event->any.window &&
2379 (event->type == GDK_DESTROY || !gdk_window_is_destroyed (event->any.window)))
2381 gdk_window_get_user_data (event->any.window, &widget_ptr);
2382 widget = widget_ptr;
2389 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2391 if (!quitf->marshal)
2392 return quitf->function (quitf->data);
2396 gint ret_val = FALSE;
2398 args[0].name = NULL;
2399 args[0].type = G_TYPE_BOOLEAN;
2400 args[0].d.pointer_data = &ret_val;
2401 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2409 * gtk_propagate_event:
2410 * @widget: a #GtkWidget
2413 * Sends an event to a widget, propagating the event to parent widgets
2414 * if the event remains unhandled. Events received by GTK+ from GDK
2415 * normally begin in gtk_main_do_event(). Depending on the type of
2416 * event, existence of modal dialogs, grabs, etc., the event may be
2417 * propagated; if so, this function is used. gtk_propagate_event()
2418 * calls gtk_widget_event() on each widget it decides to send the
2419 * event to. So gtk_widget_event() is the lowest-level function; it
2420 * simply emits the "event" and possibly an event-specific signal on a
2421 * widget. gtk_propagate_event() is a bit higher-level, and
2422 * gtk_main_do_event() is the highest level.
2424 * All that said, you most likely don't want to use any of these
2425 * functions; synthesizing events is rarely needed. Consider asking on
2426 * the mailing list for better ways to achieve your goals. For
2427 * example, use gdk_window_invalidate_rect() or
2428 * gtk_widget_queue_draw() instead of making up expose events.
2432 gtk_propagate_event (GtkWidget *widget,
2437 g_return_if_fail (GTK_IS_WIDGET (widget));
2438 g_return_if_fail (event != NULL);
2440 handled_event = FALSE;
2442 g_object_ref (widget);
2444 if ((event->type == GDK_KEY_PRESS) ||
2445 (event->type == GDK_KEY_RELEASE))
2447 /* Only send key events within Window widgets to the Window
2448 * The Window widget will in turn pass the
2449 * key event on to the currently focused widget
2454 window = gtk_widget_get_toplevel (widget);
2455 if (GTK_IS_WINDOW (window))
2457 /* If there is a grab within the window, give the grab widget
2458 * a first crack at the key event
2460 if (widget != window && gtk_widget_has_grab (widget))
2461 handled_event = gtk_widget_event (widget, event);
2465 window = gtk_widget_get_toplevel (widget);
2466 if (GTK_IS_WINDOW (window))
2468 if (gtk_widget_is_sensitive (window))
2469 gtk_widget_event (window, event);
2473 handled_event = TRUE; /* don't send to widget */
2477 /* Other events get propagated up the widget tree
2478 * so that parents can see the button and motion
2479 * events of the children.
2487 /* Scroll events are special cased here because it
2488 * feels wrong when scrolling a GtkViewport, say,
2489 * to have children of the viewport eat the scroll
2492 if (!gtk_widget_is_sensitive (widget))
2493 handled_event = event->type != GDK_SCROLL;
2495 handled_event = gtk_widget_event (widget, event);
2497 tmp = gtk_widget_get_parent (widget);
2498 g_object_unref (widget);
2502 if (!handled_event && widget)
2503 g_object_ref (widget);
2509 g_object_unref (widget);
2513 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2514 GValue *return_accu,
2515 const GValue *handler_return,
2518 gboolean continue_emission;
2519 gboolean signal_handled;
2521 signal_handled = g_value_get_boolean (handler_return);
2522 g_value_set_boolean (return_accu, signal_handled);
2523 continue_emission = !signal_handled;
2525 return continue_emission;