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/.
30 #include "gdkconfig.h"
40 #include <sys/types.h> /* For uid_t, gid_t */
50 #include "gtkaccelmap.h"
52 #include "gtkclipboard.h"
54 #include "gtkversion.h"
56 #include "gtkmodules.h"
58 #include "gtkrecentmanager.h"
59 #include "gtkselection.h"
60 #include "gtksettings.h"
61 #include "gtkwidget.h"
62 #include "gtkwindow.h"
63 #include "gtktooltip.h"
66 #include "gdk/gdkkeysyms.h"
68 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
72 static HMODULE gtk_dll;
75 DllMain (HINSTANCE hinstDLL,
81 case DLL_PROCESS_ATTACH:
82 gtk_dll = (HMODULE) hinstDLL;
89 /* These here before inclusion of gtkprivate.h so that the original
90 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
94 _gtk_get_libdir (void)
96 static char *gtk_libdir = NULL;
97 if (gtk_libdir == NULL)
99 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
100 gchar *slash = strrchr (root, '\\');
101 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
102 gtk_libdir = GTK_LIBDIR;
104 gtk_libdir = g_build_filename (root, "lib", NULL);
112 _gtk_get_localedir (void)
114 static char *gtk_localedir = NULL;
115 if (gtk_localedir == NULL)
120 /* GTK_LOCALEDIR ends in either /lib/locale or
121 * /share/locale. Scan for that slash.
123 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
129 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
130 temp = g_build_filename (root, p, NULL);
133 /* gtk_localedir is passed to bindtextdomain() which isn't
136 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
139 return gtk_localedir;
144 #include "gtkprivate.h"
146 /* Private type definitions
148 typedef struct _GtkInitFunction GtkInitFunction;
149 typedef struct _GtkQuitFunction GtkQuitFunction;
150 typedef struct _GtkKeySnooperData GtkKeySnooperData;
152 struct _GtkInitFunction
154 GtkFunction function;
158 struct _GtkQuitFunction
162 GtkCallbackMarshal marshal;
163 GtkFunction function;
165 GDestroyNotify destroy;
168 struct _GtkKeySnooperData
170 GtkKeySnoopFunc func;
175 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
176 static void gtk_quit_destroy (GtkQuitFunction *quitf);
177 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
180 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
182 static guint gtk_main_loop_level = 0;
183 static gint pre_initialized = FALSE;
184 static gint gtk_initialized = FALSE;
185 static GList *current_events = NULL;
187 static GSList *main_loops = NULL; /* stack of currently executing main loops */
189 static GList *init_functions = NULL; /* A list of init functions.
191 static GList *quit_functions = NULL; /* A list of quit functions.
193 static GSList *key_snoopers = NULL;
195 guint gtk_debug_flags = 0; /* Global GTK debug flag */
197 #ifdef G_ENABLE_DEBUG
198 static const GDebugKey gtk_debug_keys[] = {
199 {"misc", GTK_DEBUG_MISC},
200 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
201 {"text", GTK_DEBUG_TEXT},
202 {"tree", GTK_DEBUG_TREE},
203 {"updates", GTK_DEBUG_UPDATES},
204 {"keybindings", GTK_DEBUG_KEYBINDINGS},
205 {"multihead", GTK_DEBUG_MULTIHEAD},
206 {"modules", GTK_DEBUG_MODULES},
207 {"geometry", GTK_DEBUG_GEOMETRY},
208 {"icontheme", GTK_DEBUG_ICONTHEME},
209 {"printing", GTK_DEBUG_PRINTING},
210 {"builder", GTK_DEBUG_BUILDER},
211 {"size-request", GTK_DEBUG_SIZE_REQUEST},
213 #endif /* G_ENABLE_DEBUG */
218 * Returns the major version number of the GTK+ library. (e.g. in GTK+ version
221 * This function is in the library, so it represents the GTK+ library
222 * your code is running against. Contrast with the #GTK_MAJOR_VERSION
223 * macro, which represents the major version of the GTK+ headers you
224 * have included when compiling your code.
226 * Returns the major version number of the GTK+ library.
229 gtk_major_version (void)
231 return GTK_MAJOR_VERSION;
237 * Returns the minor version number of the GTK+ library. (e.g. in GTK+ version
240 * This function is in the library, so it represents the GTK+ library
241 * your code is are running against. Contrast with the
242 * #GTK_MINOR_VERSION macro, which represents the minor version of the
243 * GTK+ headers you have included when compiling your code.
245 * Returns the minor version number of the GTK+ library.
248 gtk_minor_version (void)
250 return GTK_MINOR_VERSION;
256 * Returns the micro version number of the GTK+ library. (e.g. in GTK+ version
259 * This function is in the library, so it represents the GTK+ library
260 * your code is are running against. Contrast with the
261 * #GTK_MICRO_VERSION macro, which represents the micro version of the
262 * GTK+ headers you have included when compiling your code.
264 * Returns the micro version number of the GTK+ library.
267 gtk_micro_version (void)
269 return GTK_MICRO_VERSION;
275 * Returns the binary age as passed to
276 * <application>libtool</application> when building the GTK+ library
277 * the process is running against. If
278 * <application>libtool</application> means nothing to you, don't
281 * Returns the binary age of the GTK+ library.
284 gtk_binary_age (void)
286 return GTK_BINARY_AGE;
292 * Returns the interface age as passed to
293 * <application>libtool</application> when building the GTK+ library
294 * the process is running against. If
295 * <application>libtool</application> means nothing to you, don't
298 * Returns the interface age of the GTK+ library.
301 gtk_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 * a 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 gtk_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 gtk_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 gtk_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 (gtk_debug_flags & GTK_DEBUG_UPDATES)
780 gdk_window_set_debug_updates (TRUE);
783 /* Translate to default:RTL if you want your widgets
784 * to be RTL, otherwise translate to default:LTR.
785 * Do *not* translate it to "predefinito:LTR", if it
786 * it isn't default:LTR or default:RTL it will not work
788 char *e = _("default:LTR");
789 if (strcmp (e, "default:RTL")==0)
790 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
791 else if (strcmp (e, "default:LTR"))
792 g_warning ("Whoever translated default:LTR did so wrongly.\n");
795 /* do what the call to gtk_type_init() used to do */
798 _gtk_accel_map_init ();
801 /* Set the 'initialized' flag.
803 gtk_initialized = TRUE;
805 /* load gtk modules */
806 if (gtk_modules_string)
808 _gtk_modules_init (argc, argv, gtk_modules_string->str);
809 g_string_free (gtk_modules_string, TRUE);
813 _gtk_modules_init (argc, argv, NULL);
820 gboolean open_default_display;
824 pre_parse_hook (GOptionContext *context,
829 do_pre_parse_initialization (NULL, NULL);
835 post_parse_hook (GOptionContext *context,
840 OptionGroupInfo *info = data;
843 do_post_parse_initialization (NULL, NULL);
845 if (info->open_default_display)
847 if (gdk_display_open_default_libgtk_only () == NULL)
849 const char *display_name = gdk_get_display_arg_name ();
852 G_OPTION_ERROR_FAILED,
853 _("Cannot open display: %s"),
854 display_name ? display_name : "" );
865 * gtk_get_option_group:
866 * @open_default_display: whether to open the default display
867 * when parsing the commandline arguments
869 * Returns a #GOptionGroup for the commandline arguments recognized
870 * by GTK+ and GDK. You should add this group to your #GOptionContext
871 * with g_option_context_add_group(), if you are using
872 * g_option_context_parse() to parse your commandline arguments.
874 * Returns: a #GOptionGroup for the commandline arguments recognized
880 gtk_get_option_group (gboolean open_default_display)
883 OptionGroupInfo *info;
885 gettext_initialization ();
887 info = g_new0 (OptionGroupInfo, 1);
888 info->open_default_display = open_default_display;
890 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
891 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
893 gdk_add_option_entries_libgtk_only (group);
894 g_option_group_add_entries (group, gtk_args);
895 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
901 * gtk_init_with_args:
902 * @argc: a pointer to the number of command line arguments.
903 * @argv: a pointer to the array of command line arguments.
904 * @parameter_string: a string which is displayed in
905 * the first line of <option>--help</option> output, after
906 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
907 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
908 * describing the options of your program
909 * @translation_domain: a translation domain to use for translating
910 * the <option>--help</option> output for the options in @entries
911 * and the @parameter_string with gettext(), or %NULL
912 * @error: a return location for errors
914 * This function does the same work as gtk_init_check().
915 * Additionally, it allows you to add your own commandline options,
916 * and it automatically generates nicely formatted
917 * <option>--help</option> output. Note that your program will
918 * be terminated after writing out the help output.
920 * Returns: %TRUE if the GUI has been successfully initialized,
926 gtk_init_with_args (gint *argc,
928 const gchar *parameter_string,
929 const GOptionEntry *entries,
930 const gchar *translation_domain,
933 GOptionContext *context;
934 GOptionGroup *gtk_group;
938 return gdk_display_open_default_libgtk_only () != NULL;
940 gettext_initialization ();
942 if (!check_setugid ())
945 gtk_group = gtk_get_option_group (TRUE);
947 context = g_option_context_new (parameter_string);
948 g_option_context_add_group (context, gtk_group);
949 g_option_context_set_translation_domain (context, translation_domain);
952 g_option_context_add_main_entries (context, entries, translation_domain);
953 retval = g_option_context_parse (context, argc, argv, error);
955 g_option_context_free (context);
963 * @argc: (inout): a pointer to the number of command line arguments.
964 * @argv: (array) (inout): a pointer to the array of command line arguments.
966 * Parses command line arguments, and initializes global
967 * attributes of GTK+, but does not actually open a connection
968 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
970 * Any arguments used by GTK+ or GDK are removed from the array and
971 * @argc and @argv are updated accordingly.
973 * You shouldn't call this function explicitely if you are using
974 * gtk_init(), or gtk_init_check().
976 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
979 gtk_parse_args (int *argc,
982 GOptionContext *option_context;
983 GOptionGroup *gtk_group;
984 GError *error = NULL;
989 gettext_initialization ();
991 if (!check_setugid ())
994 option_context = g_option_context_new (NULL);
995 g_option_context_set_ignore_unknown_options (option_context, TRUE);
996 g_option_context_set_help_enabled (option_context, FALSE);
997 gtk_group = gtk_get_option_group (FALSE);
998 g_option_context_set_main_group (option_context, gtk_group);
999 if (!g_option_context_parse (option_context, argc, argv, &error))
1001 g_warning ("%s", error->message);
1002 g_error_free (error);
1005 g_option_context_free (option_context);
1010 #ifdef G_PLATFORM_WIN32
1011 #undef gtk_init_check
1016 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1017 * main() function. Changed if any arguments were handled.
1018 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1019 * Any parameters understood by gtk_init() are stripped before return.
1021 * This function does the same work as gtk_init() with only
1022 * a single change: It does not terminate the program if the GUI can't be
1023 * initialized. Instead it returns %FALSE on failure.
1025 * This way the application can fall back to some other means of communication
1026 * with the user - for example a curses or command line interface.
1028 * Return value: %TRUE if the GUI has been successfully initialized,
1032 gtk_init_check (int *argc,
1035 if (!gtk_parse_args (argc, argv))
1038 return gdk_display_open_default_libgtk_only () != NULL;
1041 #ifdef G_PLATFORM_WIN32
1047 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1048 * main() function. Changed if any arguments were handled.
1049 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1050 * Any parameters understood by gtk_init() are stripped before return.
1052 * Call this function before using any other GTK+ functions in your GUI
1053 * applications. It will initialize everything needed to operate the
1054 * toolkit and parses some standard command line options. @argc and
1055 * @argv are adjusted accordingly so your own code will
1056 * never see those standard arguments.
1058 * Note that there are some alternative ways to initialize GTK+:
1059 * if you are calling gtk_parse_args(), gtk_init_check(),
1060 * gtk_init_with_args() or g_option_context_parse() with
1061 * the option group returned by gtk_get_option_group(), you
1062 * <emphasis>don't</emphasis> have to call gtk_init().
1065 * This function will terminate your program if it was unable to initialize
1066 * the GUI for some reason. If you want your program to fall back to a
1067 * textual interface you want to call gtk_init_check() instead.
1071 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1072 * during initialization, to ignore SIGPIPE signals, since these are
1073 * almost never wanted in graphical applications. If you do need to
1074 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1075 * but notice that other libraries (e.g. libdbus or gvfs) might do
1080 gtk_init (int *argc, char ***argv)
1082 if (!gtk_init_check (argc, argv))
1084 const char *display_name_arg = gdk_get_display_arg_name ();
1085 if (display_name_arg == NULL)
1086 display_name_arg = getenv("DISPLAY");
1087 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1092 #ifdef G_PLATFORM_WIN32
1095 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1097 if (sizeof_GtkWindow != sizeof (GtkWindow))
1098 g_error ("Incompatible build!\n"
1099 "The code using GTK+ thinks GtkWindow is of different\n"
1100 "size than it actually is in this build of GTK+.\n"
1101 "On Windows, this probably means that you have compiled\n"
1102 "your code with gcc without the -mms-bitfields switch,\n"
1103 "or that you are using an unsupported compiler.");
1106 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1107 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1108 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1109 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1110 * -fnative-struct still matters. GtkBox is one such.
1113 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1115 if (sizeof_GtkBox != sizeof (GtkBox))
1116 g_error ("Incompatible build!\n"
1117 "The code using GTK+ thinks GtkBox is of different\n"
1118 "size than it actually is in this build of GTK+.\n"
1119 "On Windows, this probably means that you have compiled\n"
1120 "your code with gcc without the -mms-bitfields switch,\n"
1121 "or that you are using an unsupported compiler.");
1124 /* These two functions might get more checks added later, thus pass
1125 * in the number of extra args.
1128 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1130 check_sizeof_GtkWindow (sizeof_GtkWindow);
1131 if (num_checks >= 2)
1132 check_sizeof_GtkBox (sizeof_GtkBox);
1133 gtk_init (argc, argv);
1137 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1139 check_sizeof_GtkWindow (sizeof_GtkWindow);
1140 if (num_checks >= 2)
1141 check_sizeof_GtkBox (sizeof_GtkBox);
1142 return gtk_init_check (argc, argv);
1150 * Initializes internationalization support for GTK+. gtk_init()
1151 * automatically does this, so there is typically no point
1152 * in calling this function.
1154 * If you are calling this function because you changed the locale
1155 * after GTK+ is was initialized, then calling this function
1156 * may help a bit. (Note, however, that changing the locale
1157 * after GTK+ is initialized may produce inconsistent results and
1158 * is not really supported.)
1160 * In detail - sets the current locale according to the
1161 * program environment. This is the same as calling the C library function
1162 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1163 * locale specific setup of the windowing system used by GDK.
1165 * Returns: a string corresponding to the locale set, typically in the
1166 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1167 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1168 * result of the setlocale(); it is also used on other machines, such as
1169 * Windows, where the C library returns a different result. The string is
1170 * owned by GTK+ and should not be modified or freed.
1173 gtk_set_locale (void)
1175 return gdk_set_locale ();
1179 * _gtk_get_lc_ctype:
1181 * Return the Unix-style locale string for the language currently in
1182 * effect. On Unix systems, this is the return value from
1183 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1184 * affect this through the environment variables LC_ALL, LC_CTYPE or
1185 * LANG (checked in that order). The locale strings typically is in
1186 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1187 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1188 * Swedish as written in Finland or pt_BR for Portuguese as written in
1191 * On Windows, the C library doesn't use any such environment
1192 * variables, and setting them won't affect the behaviour of functions
1193 * like ctime(). The user sets the locale through the Regional Options
1194 * in the Control Panel. The C library (in the setlocale() function)
1195 * does not use country and language codes, but country and language
1196 * names spelled out in English.
1197 * However, this function does check the above environment
1198 * variables, and does return a Unix-style locale string based on
1199 * either said environment variables or the thread's current locale.
1201 * Return value: a dynamically allocated string, free with g_free().
1205 _gtk_get_lc_ctype (void)
1208 /* Somebody might try to set the locale for this process using the
1209 * LANG or LC_ environment variables. The Microsoft C library
1210 * doesn't know anything about them. You set the locale in the
1211 * Control Panel. Setting these env vars won't have any affect on
1212 * locale-dependent C library functions like ctime(). But just for
1213 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1214 * it easier to test GTK and Pango in various default languages, you
1215 * don't have to clickety-click in the Control Panel, you can simply
1216 * start the program with LC_ALL=something on the command line.)
1220 p = getenv ("LC_ALL");
1222 return g_strdup (p);
1224 p = getenv ("LC_CTYPE");
1226 return g_strdup (p);
1228 p = getenv ("LANG");
1230 return g_strdup (p);
1232 return g_win32_getlocale ();
1234 return g_strdup (setlocale (LC_CTYPE, NULL));
1239 * gtk_get_default_language:
1241 * Returns the #PangoLanguage for the default language currently in
1242 * effect. (Note that this can change over the life of an
1243 * application.) The default language is derived from the current
1244 * locale. It determines, for example, whether GTK+ uses the
1245 * right-to-left or left-to-right text direction.
1247 * This function is equivalent to pango_language_get_default(). See
1248 * that function for details.
1250 * Return value: the default language as a #PangoLanguage, must not be
1254 gtk_get_default_language (void)
1256 return pango_language_get_default ();
1264 GtkInitFunction *init;
1267 gtk_main_loop_level++;
1269 loop = g_main_loop_new (NULL, TRUE);
1270 main_loops = g_slist_prepend (main_loops, loop);
1272 tmp_list = functions = init_functions;
1273 init_functions = NULL;
1277 init = tmp_list->data;
1278 tmp_list = tmp_list->next;
1280 (* init->function) (init->data);
1283 g_list_free (functions);
1285 if (g_main_loop_is_running (main_loops->data))
1287 GDK_THREADS_LEAVE ();
1288 g_main_loop_run (loop);
1289 GDK_THREADS_ENTER ();
1295 GList *reinvoke_list = NULL;
1296 GtkQuitFunction *quitf;
1298 while (quit_functions)
1300 quitf = quit_functions->data;
1302 tmp_list = quit_functions;
1303 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1304 g_list_free_1 (tmp_list);
1306 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1307 gtk_quit_invoke_function (quitf))
1309 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1313 gtk_quit_destroy (quitf);
1320 work = g_list_last (reinvoke_list);
1322 quit_functions->prev = work;
1323 work->next = quit_functions;
1324 quit_functions = work;
1330 main_loops = g_slist_remove (main_loops, loop);
1332 g_main_loop_unref (loop);
1334 gtk_main_loop_level--;
1336 if (gtk_main_loop_level == 0)
1338 /* Try storing all clipboard data we have */
1339 _gtk_clipboard_store_all ();
1341 /* Synchronize the recent manager singleton */
1342 _gtk_recent_manager_sync ();
1347 gtk_main_level (void)
1349 return gtk_main_loop_level;
1353 gtk_main_quit (void)
1355 g_return_if_fail (main_loops != NULL);
1357 g_main_loop_quit (main_loops->data);
1361 gtk_events_pending (void)
1365 GDK_THREADS_LEAVE ();
1366 result = g_main_context_pending (NULL);
1367 GDK_THREADS_ENTER ();
1373 gtk_main_iteration (void)
1375 GDK_THREADS_LEAVE ();
1376 g_main_context_iteration (NULL, TRUE);
1377 GDK_THREADS_ENTER ();
1380 return !g_main_loop_is_running (main_loops->data);
1386 gtk_main_iteration_do (gboolean blocking)
1388 GDK_THREADS_LEAVE ();
1389 g_main_context_iteration (NULL, blocking);
1390 GDK_THREADS_ENTER ();
1393 return !g_main_loop_is_running (main_loops->data);
1398 /* private libgtk to libgdk interfaces
1400 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1402 GdkWindow **grab_window,
1403 gboolean *owner_events);
1406 rewrite_events_translate (GdkWindow *old_window,
1407 GdkWindow *new_window,
1411 gint old_origin_x, old_origin_y;
1412 gint new_origin_x, new_origin_y;
1414 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1415 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1417 *x += old_origin_x - new_origin_x;
1418 *y += old_origin_y - new_origin_y;
1422 rewrite_event_for_window (GdkEvent *event,
1423 GdkWindow *new_window)
1425 event = gdk_event_copy (event);
1427 switch (event->type)
1430 rewrite_events_translate (event->any.window,
1432 &event->scroll.x, &event->scroll.y);
1434 case GDK_BUTTON_PRESS:
1435 case GDK_2BUTTON_PRESS:
1436 case GDK_3BUTTON_PRESS:
1437 case GDK_BUTTON_RELEASE:
1438 rewrite_events_translate (event->any.window,
1440 &event->button.x, &event->button.y);
1442 case GDK_MOTION_NOTIFY:
1443 rewrite_events_translate (event->any.window,
1445 &event->motion.x, &event->motion.y);
1448 case GDK_KEY_RELEASE:
1449 case GDK_PROXIMITY_IN:
1450 case GDK_PROXIMITY_OUT:
1457 g_object_unref (event->any.window);
1458 event->any.window = g_object_ref (new_window);
1463 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1464 * then what X11 does is deliver the event normally if it was going to this
1465 * client, otherwise, delivers it in terms of the grab window. This function
1466 * rewrites events to the effect that events going to the same window group
1467 * are delivered normally, otherwise, the event is delivered in terms of the
1471 rewrite_event_for_grabs (GdkEvent *event)
1473 GdkWindow *grab_window;
1474 GtkWidget *event_widget, *grab_widget;
1475 gpointer grab_widget_ptr;
1476 gboolean owner_events;
1477 GdkDisplay *display;
1480 switch (event->type)
1483 case GDK_BUTTON_PRESS:
1484 case GDK_2BUTTON_PRESS:
1485 case GDK_3BUTTON_PRESS:
1486 case GDK_BUTTON_RELEASE:
1487 case GDK_MOTION_NOTIFY:
1488 case GDK_PROXIMITY_IN:
1489 case GDK_PROXIMITY_OUT:
1491 case GDK_KEY_RELEASE:
1492 display = gdk_drawable_get_display (event->any.window);
1493 device = gdk_event_get_device (event);
1495 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1503 event_widget = gtk_get_event_widget (event);
1504 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1505 grab_widget = grab_widget_ptr;
1508 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1509 return rewrite_event_for_window (event, grab_window);
1515 gtk_main_do_event (GdkEvent *event)
1517 GtkWidget *event_widget;
1518 GtkWidget *grab_widget = NULL;
1519 GtkWindowGroup *window_group;
1520 GdkEvent *rewritten_event = NULL;
1524 if (event->type == GDK_SETTING)
1526 _gtk_settings_handle_event (&event->setting);
1530 if (event->type == GDK_OWNER_CHANGE)
1532 _gtk_clipboard_handle_event (&event->owner_change);
1536 /* Find the widget which got the event. We store the widget
1537 * in the user_data field of GdkWindow's.
1538 * Ignore the event if we don't have a widget for it, except
1539 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1540 * Though this happens rarely, bogus events can occour
1541 * for e.g. destroyed GdkWindows.
1543 event_widget = gtk_get_event_widget (event);
1546 /* To handle selection INCR transactions, we select
1547 * PropertyNotify events on the requestor window and create
1548 * a corresponding (fake) GdkWindow so that events get
1549 * here. There won't be a widget though, so we have to handle
1552 if (event->type == GDK_PROPERTY_NOTIFY)
1553 _gtk_selection_incr_event (event->any.window,
1559 /* If pointer or keyboard grabs are in effect, munge the events
1560 * so that each window group looks like a separate app.
1562 rewritten_event = rewrite_event_for_grabs (event);
1563 if (rewritten_event)
1565 event = rewritten_event;
1566 event_widget = gtk_get_event_widget (event);
1569 window_group = gtk_main_get_window_group (event_widget);
1570 device = gdk_event_get_device (event);
1572 /* check whether there is a (device) grab in effect...
1575 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1577 if (!grab_widget && window_group->grabs)
1578 grab_widget = window_group->grabs->data;
1580 /* If the grab widget is an ancestor of the event widget
1581 * then we send the event to the original event widget.
1582 * This is the key to implementing modality.
1585 (gtk_widget_is_sensitive (event_widget) &&
1586 gtk_widget_is_ancestor (event_widget, grab_widget)))
1587 grab_widget = event_widget;
1589 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1591 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1593 if (rewritten_event)
1594 gdk_event_free (rewritten_event);
1599 /* Push the event onto a stack of current events for
1600 * gtk_current_event_get().
1602 current_events = g_list_prepend (current_events, event);
1604 /* Not all events get sent to the grabbing widget.
1605 * The delete, destroy, expose, focus change and resize
1606 * events still get sent to the event widget because
1607 * 1) these events have no meaning for the grabbing widget
1608 * and 2) redirecting these events to the grabbing widget
1609 * could cause the display to be messed up.
1611 * Drag events are also not redirected, since it isn't
1612 * clear what the semantics of that would be.
1614 switch (event->type)
1620 g_object_ref (event_widget);
1621 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1622 !gtk_widget_event (event_widget, event))
1623 gtk_widget_destroy (event_widget);
1624 g_object_unref (event_widget);
1628 /* Unexpected GDK_DESTROY from the outside, ignore for
1629 * child windows, handle like a GDK_DELETE for toplevels
1631 if (!gtk_widget_get_parent (event_widget))
1633 g_object_ref (event_widget);
1634 if (!gtk_widget_event (event_widget, event) &&
1635 gtk_widget_get_realized (event_widget))
1636 gtk_widget_destroy (event_widget);
1637 g_object_unref (event_widget);
1642 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1644 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1645 gtk_widget_send_expose (event_widget, event);
1646 gdk_window_end_paint (event->any.window);
1650 /* The app may paint with a previously allocated cairo_t,
1651 which will draw directly to the window. We can't catch cairo
1652 drap operatoins to automatically flush the window, thus we
1653 need to explicitly flush any outstanding moves or double
1655 gdk_window_flush (event->any.window);
1656 gtk_widget_send_expose (event_widget, event);
1660 case GDK_PROPERTY_NOTIFY:
1662 case GDK_FOCUS_CHANGE:
1666 case GDK_SELECTION_CLEAR:
1667 case GDK_SELECTION_REQUEST:
1668 case GDK_SELECTION_NOTIFY:
1669 case GDK_CLIENT_EVENT:
1670 case GDK_VISIBILITY_NOTIFY:
1671 case GDK_WINDOW_STATE:
1672 case GDK_GRAB_BROKEN:
1674 gtk_widget_event (event_widget, event);
1678 case GDK_BUTTON_PRESS:
1679 case GDK_2BUTTON_PRESS:
1680 case GDK_3BUTTON_PRESS:
1681 gtk_propagate_event (grab_widget, event);
1685 case GDK_KEY_RELEASE:
1688 if (gtk_invoke_key_snoopers (grab_widget, event))
1691 /* Catch alt press to enable auto-mnemonics;
1692 * menus are handled elsewhere
1694 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1695 !GTK_IS_MENU_SHELL (grab_widget))
1697 gboolean auto_mnemonics;
1699 g_object_get (gtk_widget_get_settings (grab_widget),
1700 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1704 gboolean mnemonics_visible;
1707 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1709 window = gtk_widget_get_toplevel (grab_widget);
1711 if (GTK_IS_WINDOW (window))
1712 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1715 /* else fall through */
1716 case GDK_MOTION_NOTIFY:
1717 case GDK_BUTTON_RELEASE:
1718 case GDK_PROXIMITY_IN:
1719 case GDK_PROXIMITY_OUT:
1720 gtk_propagate_event (grab_widget, event);
1723 case GDK_ENTER_NOTIFY:
1724 _gtk_widget_set_device_window (event_widget,
1725 gdk_event_get_device (event),
1727 if (gtk_widget_is_sensitive (grab_widget))
1728 gtk_widget_event (grab_widget, event);
1731 case GDK_LEAVE_NOTIFY:
1732 _gtk_widget_set_device_window (event_widget,
1733 gdk_event_get_device (event),
1735 if (gtk_widget_is_sensitive (grab_widget))
1736 gtk_widget_event (grab_widget, event);
1739 case GDK_DRAG_STATUS:
1740 case GDK_DROP_FINISHED:
1741 _gtk_drag_source_handle_event (event_widget, event);
1743 case GDK_DRAG_ENTER:
1744 case GDK_DRAG_LEAVE:
1745 case GDK_DRAG_MOTION:
1746 case GDK_DROP_START:
1747 _gtk_drag_dest_handle_event (event_widget, event);
1750 g_assert_not_reached ();
1754 if (event->type == GDK_ENTER_NOTIFY
1755 || event->type == GDK_LEAVE_NOTIFY
1756 || event->type == GDK_BUTTON_PRESS
1757 || event->type == GDK_2BUTTON_PRESS
1758 || event->type == GDK_3BUTTON_PRESS
1759 || event->type == GDK_KEY_PRESS
1760 || event->type == GDK_DRAG_ENTER
1761 || event->type == GDK_GRAB_BROKEN
1762 || event->type == GDK_MOTION_NOTIFY
1763 || event->type == GDK_SCROLL)
1765 _gtk_tooltip_handle_event (event);
1768 tmp_list = current_events;
1769 current_events = g_list_remove_link (current_events, tmp_list);
1770 g_list_free_1 (tmp_list);
1772 if (rewritten_event)
1773 gdk_event_free (rewritten_event);
1788 static GtkWindowGroup *
1789 gtk_main_get_window_group (GtkWidget *widget)
1791 GtkWidget *toplevel = NULL;
1794 toplevel = gtk_widget_get_toplevel (widget);
1796 if (GTK_IS_WINDOW (toplevel))
1797 return gtk_window_get_group (GTK_WINDOW (toplevel));
1799 return gtk_window_get_group (NULL);
1804 GtkWidget *old_grab_widget;
1805 GtkWidget *new_grab_widget;
1806 gboolean was_grabbed;
1807 gboolean is_grabbed;
1809 GList *notified_windows;
1814 synth_crossing_for_grab_notify (GtkWidget *from,
1816 GrabNotifyInfo *info,
1818 GdkCrossingMode mode)
1822 GdkDevice *device = devices->data;
1823 GdkWindow *from_window, *to_window;
1825 /* Do not propagate events more than once to
1826 * the same windows if non-multidevice aware.
1832 from_window = _gtk_widget_get_device_window (from, device);
1835 !gdk_window_get_support_multidevice (from_window) &&
1836 g_list_find (info->notified_windows, from_window))
1844 to_window = _gtk_widget_get_device_window (to, device);
1847 !gdk_window_get_support_multidevice (to_window) &&
1848 g_list_find (info->notified_windows, to_window))
1852 if (from_window || to_window)
1854 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1855 (to_window) ? to : NULL,
1859 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1862 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1865 devices = devices->next;
1870 gtk_grab_notify_foreach (GtkWidget *child,
1873 GrabNotifyInfo *info = data;
1874 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1877 was_grabbed = info->was_grabbed;
1878 is_grabbed = info->is_grabbed;
1880 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1881 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1883 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1884 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1886 g_object_ref (child);
1888 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1889 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1892 _gtk_widget_get_device_window (child, info->device))
1894 /* Device specified and is on widget */
1895 devices = g_list_prepend (NULL, info->device);
1898 devices = _gtk_widget_list_devices (child);
1902 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1903 if (!was_shadowed && devices &&
1904 gtk_widget_is_sensitive (child))
1905 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1907 GDK_CROSSING_GTK_GRAB);
1911 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1912 if (was_shadowed && devices &&
1913 gtk_widget_is_sensitive (child))
1914 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1916 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1917 GDK_CROSSING_GTK_UNGRAB);
1920 if (was_shadowed != is_shadowed)
1921 _gtk_widget_grab_notify (child, was_shadowed);
1923 g_object_unref (child);
1924 g_list_free (devices);
1926 info->was_grabbed = was_grabbed;
1927 info->is_grabbed = is_grabbed;
1931 gtk_grab_notify (GtkWindowGroup *group,
1933 GtkWidget *old_grab_widget,
1934 GtkWidget *new_grab_widget,
1938 GrabNotifyInfo info = { 0 };
1940 if (old_grab_widget == new_grab_widget)
1943 info.old_grab_widget = old_grab_widget;
1944 info.new_grab_widget = new_grab_widget;
1945 info.from_grab = from_grab;
1946 info.device = device;
1948 g_object_ref (group);
1950 toplevels = gtk_window_list_toplevels ();
1951 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1955 GtkWindow *toplevel = toplevels->data;
1956 toplevels = g_list_delete_link (toplevels, toplevels);
1958 info.was_grabbed = FALSE;
1959 info.is_grabbed = FALSE;
1961 if (group == gtk_window_get_group (toplevel))
1962 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1963 g_object_unref (toplevel);
1966 g_list_free (info.notified_windows);
1967 g_object_unref (group);
1971 gtk_grab_add (GtkWidget *widget)
1973 GtkWindowGroup *group;
1974 GtkWidget *old_grab_widget;
1976 g_return_if_fail (widget != NULL);
1978 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1980 _gtk_widget_set_has_grab (widget, TRUE);
1982 group = gtk_main_get_window_group (widget);
1985 old_grab_widget = (GtkWidget *)group->grabs->data;
1987 old_grab_widget = NULL;
1989 g_object_ref (widget);
1990 group->grabs = g_slist_prepend (group->grabs, widget);
1992 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1997 gtk_grab_get_current (void)
1999 GtkWindowGroup *group;
2001 group = gtk_main_get_window_group (NULL);
2004 return GTK_WIDGET (group->grabs->data);
2009 gtk_grab_remove (GtkWidget *widget)
2011 GtkWindowGroup *group;
2012 GtkWidget *new_grab_widget;
2014 g_return_if_fail (widget != NULL);
2016 if (gtk_widget_has_grab (widget))
2018 _gtk_widget_set_has_grab (widget, FALSE);
2020 group = gtk_main_get_window_group (widget);
2021 group->grabs = g_slist_remove (group->grabs, widget);
2024 new_grab_widget = (GtkWidget *)group->grabs->data;
2026 new_grab_widget = NULL;
2028 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2030 g_object_unref (widget);
2035 * gtk_device_grab_add:
2036 * @widget: a #GtkWidget
2037 * @device: a #GtkDevice to grab on.
2038 * @block_others: %TRUE to prevent other devices to interact with @widget.
2040 * Adds a GTK+ grab on @device, so all the events on @device and its
2041 * associated pointer or keyboard (if any) are delivered to @widget.
2042 * If the @block_others parameter is %TRUE, any other devices will be
2043 * unable to interact with @widget during the grab.
2048 gtk_device_grab_add (GtkWidget *widget,
2050 gboolean block_others)
2052 GtkWindowGroup *group;
2053 GtkWidget *old_grab_widget;
2055 g_return_if_fail (GTK_IS_WIDGET (widget));
2056 g_return_if_fail (GDK_IS_DEVICE (device));
2058 group = gtk_main_get_window_group (widget);
2059 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2061 if (old_grab_widget != widget)
2062 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2064 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2068 * gtk_device_grab_remove:
2069 * @widget: a #GtkWidget
2070 * @device: a #GdkDevice
2072 * Removes a device grab from the given widget. You have to pair calls
2073 * to gtk_device_grab_add() and gtk_device_grab_remove().
2078 gtk_device_grab_remove (GtkWidget *widget,
2081 GtkWindowGroup *group;
2082 GtkWidget *new_grab_widget;
2084 g_return_if_fail (GTK_IS_WIDGET (widget));
2085 g_return_if_fail (GDK_IS_DEVICE (device));
2087 group = gtk_main_get_window_group (widget);
2088 _gtk_window_group_remove_device_grab (group, widget, device);
2089 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2091 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2095 gtk_init_add (GtkFunction function,
2098 GtkInitFunction *init;
2100 init = g_new (GtkInitFunction, 1);
2101 init->function = function;
2104 init_functions = g_list_prepend (init_functions, init);
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 (GtkObject **object_p)
2206 gtk_object_destroy (*object_p);
2213 gtk_quit_add_destroy (guint main_level,
2216 GtkObject **object_p;
2218 g_return_if_fail (main_level > 0);
2219 g_return_if_fail (GTK_IS_OBJECT (object));
2221 object_p = g_new (GtkObject*, 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: 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: the widget that originally received @event, or %NULL
2375 gtk_get_event_widget (GdkEvent *event)
2378 gpointer widget_ptr;
2381 if (event && event->any.window &&
2382 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2384 gdk_window_get_user_data (event->any.window, &widget_ptr);
2385 widget = widget_ptr;
2392 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2394 if (!quitf->marshal)
2395 return quitf->function (quitf->data);
2399 gint ret_val = FALSE;
2401 args[0].name = NULL;
2402 args[0].type = G_TYPE_BOOLEAN;
2403 args[0].d.pointer_data = &ret_val;
2404 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2412 * gtk_propagate_event:
2413 * @widget: a #GtkWidget
2416 * Sends an event to a widget, propagating the event to parent widgets
2417 * if the event remains unhandled. Events received by GTK+ from GDK
2418 * normally begin in gtk_main_do_event(). Depending on the type of
2419 * event, existence of modal dialogs, grabs, etc., the event may be
2420 * propagated; if so, this function is used. gtk_propagate_event()
2421 * calls gtk_widget_event() on each widget it decides to send the
2422 * event to. So gtk_widget_event() is the lowest-level function; it
2423 * simply emits the "event" and possibly an event-specific signal on a
2424 * widget. gtk_propagate_event() is a bit higher-level, and
2425 * gtk_main_do_event() is the highest level.
2427 * All that said, you most likely don't want to use any of these
2428 * functions; synthesizing events is rarely needed. Consider asking on
2429 * the mailing list for better ways to achieve your goals. For
2430 * example, use gdk_window_invalidate_rect() or
2431 * gtk_widget_queue_draw() instead of making up expose events.
2435 gtk_propagate_event (GtkWidget *widget,
2440 g_return_if_fail (GTK_IS_WIDGET (widget));
2441 g_return_if_fail (event != NULL);
2443 handled_event = FALSE;
2445 g_object_ref (widget);
2447 if ((event->type == GDK_KEY_PRESS) ||
2448 (event->type == GDK_KEY_RELEASE))
2450 /* Only send key events within Window widgets to the Window
2451 * The Window widget will in turn pass the
2452 * key event on to the currently focused widget
2457 window = gtk_widget_get_toplevel (widget);
2458 if (GTK_IS_WINDOW (window))
2460 /* If there is a grab within the window, give the grab widget
2461 * a first crack at the key event
2463 if (widget != window && gtk_widget_has_grab (widget))
2464 handled_event = gtk_widget_event (widget, event);
2468 window = gtk_widget_get_toplevel (widget);
2469 if (GTK_IS_WINDOW (window))
2471 if (gtk_widget_is_sensitive (window))
2472 gtk_widget_event (window, event);
2476 handled_event = TRUE; /* don't send to widget */
2480 /* Other events get propagated up the widget tree
2481 * so that parents can see the button and motion
2482 * events of the children.
2490 /* Scroll events are special cased here because it
2491 * feels wrong when scrolling a GtkViewport, say,
2492 * to have children of the viewport eat the scroll
2495 if (!gtk_widget_is_sensitive (widget))
2496 handled_event = event->type != GDK_SCROLL;
2498 handled_event = gtk_widget_event (widget, event);
2500 tmp = gtk_widget_get_parent (widget);
2501 g_object_unref (widget);
2505 if (!handled_event && widget)
2506 g_object_ref (widget);
2512 g_object_unref (widget);
2516 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2517 GValue *return_accu,
2518 const GValue *handler_return,
2521 gboolean continue_emission;
2522 gboolean signal_handled;
2524 signal_handled = g_value_get_boolean (handler_return);
2525 g_value_set_boolean (return_accu, signal_handled);
2526 continue_emission = !signal_handled;
2528 return continue_emission;