1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #include "gdkconfig.h"
42 #include <sys/types.h> /* For uid_t, gid_t */
52 #include "gtkaccelmap.h"
54 #include "gtkclipboard.h"
56 #include "gtkversion.h"
57 #include "gtkmodules.h"
59 #include "gtkrecentmanager.h"
60 #include "gtkselection.h"
61 #include "gtksettings.h"
62 #include "gtkwidgetprivate.h"
63 #include "gtkwindow.h"
64 #include "gtktooltip.h"
67 #include "gdk/gdkkeysyms.h"
69 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
73 static HMODULE gtk_dll;
76 DllMain (HINSTANCE hinstDLL,
82 case DLL_PROCESS_ATTACH:
83 gtk_dll = (HMODULE) hinstDLL;
90 /* These here before inclusion of gtkprivate.h so that the original
91 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
95 _gtk_get_libdir (void)
97 static char *gtk_libdir = NULL;
98 if (gtk_libdir == NULL)
100 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
101 gchar *slash = strrchr (root, '\\');
102 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
103 gtk_libdir = GTK_LIBDIR;
105 gtk_libdir = g_build_filename (root, "lib", NULL);
113 _gtk_get_localedir (void)
115 static char *gtk_localedir = NULL;
116 if (gtk_localedir == NULL)
121 /* GTK_LOCALEDIR ends in either /lib/locale or
122 * /share/locale. Scan for that slash.
124 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
130 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
131 temp = g_build_filename (root, p, NULL);
134 /* gtk_localedir is passed to bindtextdomain() which isn't
137 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
140 return gtk_localedir;
145 #include "gtkprivate.h"
147 /* Private type definitions
149 typedef struct _GtkQuitFunction GtkQuitFunction;
150 typedef struct _GtkKeySnooperData GtkKeySnooperData;
152 struct _GtkQuitFunction
156 GtkCallbackMarshal marshal;
157 GtkFunction function;
159 GDestroyNotify destroy;
162 struct _GtkKeySnooperData
164 GtkKeySnoopFunc func;
169 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
170 static void gtk_quit_destroy (GtkQuitFunction *quitf);
171 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
174 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
176 static guint gtk_main_loop_level = 0;
177 static gint pre_initialized = FALSE;
178 static gint gtk_initialized = FALSE;
179 static GList *current_events = NULL;
181 static GSList *main_loops = NULL; /* stack of currently executing main loops */
183 static GList *quit_functions = NULL; /* A list of quit functions.
185 static GSList *key_snoopers = NULL;
187 static guint debug_flags = 0; /* Global GTK debug flag */
189 #ifdef G_ENABLE_DEBUG
190 static const GDebugKey gtk_debug_keys[] = {
191 {"misc", GTK_DEBUG_MISC},
192 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
193 {"text", GTK_DEBUG_TEXT},
194 {"tree", GTK_DEBUG_TREE},
195 {"updates", GTK_DEBUG_UPDATES},
196 {"keybindings", GTK_DEBUG_KEYBINDINGS},
197 {"multihead", GTK_DEBUG_MULTIHEAD},
198 {"modules", GTK_DEBUG_MODULES},
199 {"geometry", GTK_DEBUG_GEOMETRY},
200 {"icontheme", GTK_DEBUG_ICONTHEME},
201 {"printing", GTK_DEBUG_PRINTING},
202 {"builder", GTK_DEBUG_BUILDER},
203 {"size-request", GTK_DEBUG_SIZE_REQUEST},
205 #endif /* G_ENABLE_DEBUG */
208 * gtk_get_major_version:
210 * Returns the major version number of the GTK+ library. (e.g. in GTK+ version
213 * This function is in the library, so it represents the GTK+ library
214 * your code is running against. Contrast with the #GTK_MAJOR_VERSION
215 * macro, which represents the major version of the GTK+ headers you
216 * have included when compiling your code.
218 * Returns: the major version number of the GTK+ library.
223 gtk_get_major_version (void)
225 return GTK_MAJOR_VERSION;
229 * gtk_get_minor_version:
231 * Returns the minor version number of the GTK+ library. (e.g. in GTK+ version
234 * This function is in the library, so it represents the GTK+ library
235 * your code is are running against. Contrast with the
236 * #GTK_MINOR_VERSION macro, which represents the minor version of the
237 * GTK+ headers you have included when compiling your code.
239 * Returns: the minor version number of the GTK+ library.
244 gtk_get_minor_version (void)
246 return GTK_MINOR_VERSION;
250 * gtk_get_micro_version:
252 * Returns the micro version number of the GTK+ library. (e.g. in GTK+ version
255 * This function is in the library, so it represents the GTK+ library
256 * your code is are running against. Contrast with the
257 * #GTK_MICRO_VERSION macro, which represents the micro version of the
258 * GTK+ headers you have included when compiling your code.
260 * Returns: the micro version number of the GTK+ library.
265 gtk_get_micro_version (void)
267 return GTK_MICRO_VERSION;
271 * gtk_get_binary_age:
273 * Returns the binary age as passed to
274 * <application>libtool</application> when building the GTK+ library
275 * the process is running against. If
276 * <application>libtool</application> means nothing to you, don't
279 * Returns: the binary age of the GTK+ library.
284 gtk_get_binary_age (void)
286 return GTK_BINARY_AGE;
290 * gtk_get_interface_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.
303 gtk_get_interface_age (void)
305 return GTK_INTERFACE_AGE;
310 * @required_major: the required major version.
311 * @required_minor: the required minor version.
312 * @required_micro: the required micro version.
314 * Checks that the GTK+ library in use is compatible with the
315 * given version. Generally you would pass in the constants
316 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
317 * as the three arguments to this function; that produces
318 * a check that the library in use is compatible with
319 * the version of GTK+ the application or module was compiled
322 * Compatibility is defined by two things: first the version
323 * of the running library is newer than the version
324 * @required_major.required_minor.@required_micro. Second
325 * the running library must be binary compatible with the
326 * version @required_major.required_minor.@required_micro
327 * (same major version.)
329 * This function is primarily for GTK+ modules; the module
330 * can call this function to check that it wasn't loaded
331 * into an incompatible version of GTK+. However, such a
332 * check isn't completely reliable, since the module may be
333 * linked against an old version of GTK+ and calling the
334 * old version of gtk_check_version(), but still get loaded
335 * into an application using a newer version of GTK+.
337 * Return value: %NULL if the GTK+ library is compatible with the
338 * given version, or a string describing the version mismatch.
339 * The returned string is owned by GTK+ and should not be modified
343 gtk_check_version (guint required_major,
344 guint required_minor,
345 guint required_micro)
347 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
348 gint required_effective_micro = 100 * required_minor + required_micro;
350 if (required_major > GTK_MAJOR_VERSION)
351 return "Gtk+ version too old (major mismatch)";
352 if (required_major < GTK_MAJOR_VERSION)
353 return "Gtk+ version too new (major mismatch)";
354 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
355 return "Gtk+ version too new (micro mismatch)";
356 if (required_effective_micro > gtk_effective_micro)
357 return "Gtk+ version too old (micro mismatch)";
361 /* This checks to see if the process is running suid or sgid
362 * at the current time. If so, we don't allow GTK+ to be initialized.
363 * This is meant to be a mild check - we only error out if we
364 * can prove the programmer is doing something wrong, not if
365 * they could be doing something wrong. For this reason, we
366 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
371 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
373 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
374 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
376 #ifdef HAVE_GETRESUID
377 /* These aren't in the header files, so we prototype them here.
379 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
380 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
382 if (getresuid (&ruid, &euid, &suid) != 0 ||
383 getresgid (&rgid, &egid, &sgid) != 0)
384 #endif /* HAVE_GETRESUID */
386 suid = ruid = getuid ();
387 sgid = rgid = getgid ();
392 if (ruid != euid || ruid != suid ||
393 rgid != egid || rgid != sgid)
395 g_warning ("This process is currently running setuid or setgid.\n"
396 "This is not a supported use of GTK+. You must create a helper\n"
397 "program instead. For further details, see:\n\n"
398 " http://www.gtk.org/setuid.html\n\n"
399 "Refusing to initialize GTK+.");
409 _gtk_get_datadir (void)
411 static char *gtk_datadir = NULL;
412 if (gtk_datadir == NULL)
414 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
415 gtk_datadir = g_build_filename (root, "share", NULL);
423 _gtk_get_sysconfdir (void)
425 static char *gtk_sysconfdir = NULL;
426 if (gtk_sysconfdir == NULL)
428 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
429 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
433 return gtk_sysconfdir;
437 _gtk_get_data_prefix (void)
439 static char *gtk_data_prefix = NULL;
440 if (gtk_data_prefix == NULL)
441 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
443 return gtk_data_prefix;
446 #endif /* G_OS_WIN32 */
448 static gboolean do_setlocale = TRUE;
451 * gtk_disable_setlocale:
453 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
454 * gtk_parse_args() from automatically
455 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
456 * want to use this function if you wanted to set the locale for
457 * your program to something other than the user's locale, or if
458 * you wanted to set different values for different locale categories.
460 * Most programs should not need to call this function.
463 gtk_disable_setlocale (void)
466 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
468 do_setlocale = FALSE;
471 #ifdef G_PLATFORM_WIN32
472 #undef gtk_init_check
475 static GString *gtk_modules_string = NULL;
476 static gboolean g_fatal_warnings = FALSE;
478 #ifdef G_ENABLE_DEBUG
480 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
482 debug_flags |= g_parse_debug_string (value,
484 G_N_ELEMENTS (gtk_debug_keys));
490 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
492 debug_flags &= ~g_parse_debug_string (value,
494 G_N_ELEMENTS (gtk_debug_keys));
498 #endif /* G_ENABLE_DEBUG */
501 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
505 if (gtk_modules_string)
506 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
508 gtk_modules_string = g_string_new (NULL);
510 g_string_append (gtk_modules_string, value);
516 static const GOptionEntry gtk_args[] = {
517 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
518 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
519 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
520 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
521 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
522 #ifdef G_ENABLE_DEBUG
523 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
524 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
525 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
526 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
527 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
528 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
535 static char *iso639_to_check = NULL;
536 static char *iso3166_to_check = NULL;
537 static char *script_to_check = NULL;
538 static gboolean setlocale_called = FALSE;
541 enum_locale_proc (LPTSTR locale)
549 lcid = strtoul (locale, &endptr, 16);
550 if (*endptr == '\0' &&
551 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
552 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
554 if (strcmp (iso639, iso639_to_check) == 0 &&
555 ((iso3166_to_check != NULL &&
556 strcmp (iso3166, iso3166_to_check) == 0) ||
557 (iso3166_to_check == NULL &&
558 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
560 char language[100], country[100];
563 if (script_to_check != NULL)
565 /* If lcid is the "other" script for this language,
566 * return TRUE, i.e. continue looking.
568 if (strcmp (script_to_check, "Latn") == 0)
570 switch (LANGIDFROMLCID (lcid))
572 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
574 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
576 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
578 case MAKELANGID (LANG_SERBIAN, 0x07):
579 /* Serbian in Bosnia and Herzegovina, Cyrillic */
583 else if (strcmp (script_to_check, "Cyrl") == 0)
585 switch (LANGIDFROMLCID (lcid))
587 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
589 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
591 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
593 case MAKELANGID (LANG_SERBIAN, 0x06):
594 /* Serbian in Bosnia and Herzegovina, Latin */
600 SetThreadLocale (lcid);
602 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
603 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
605 strcpy (locale, language);
606 strcat (locale, "_");
607 strcat (locale, country);
609 if (setlocale (LC_ALL, locale) != NULL)
610 setlocale_called = TRUE;
623 setlocale_initialization (void)
625 static gboolean initialized = FALSE;
634 /* If some of the POSIXish environment variables are set, set
635 * the Win32 thread locale correspondingly.
637 char *p = getenv ("LC_ALL");
644 if (strcmp (p, "C") == 0)
645 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
648 /* Check if one of the supported locales match the
649 * environment variable. If so, use that locale.
652 iso3166_to_check = strchr (iso639_to_check, '_');
653 if (iso3166_to_check != NULL)
655 *iso3166_to_check++ = '\0';
657 script_to_check = strchr (iso3166_to_check, '@');
658 if (script_to_check != NULL)
659 *script_to_check++ = '\0';
661 /* Handle special cases. */
663 /* The standard code for Serbia and Montenegro was
664 * "CS", but MSFT uses for some reason "SP". By now
665 * (October 2006), SP has split into two, "RS" and
666 * "ME", but don't bother trying to handle those
667 * yet. Do handle the even older "YU", though.
669 if (strcmp (iso3166_to_check, "CS") == 0 ||
670 strcmp (iso3166_to_check, "YU") == 0)
671 iso3166_to_check = "SP";
675 script_to_check = strchr (iso639_to_check, '@');
676 if (script_to_check != NULL)
677 *script_to_check++ = '\0';
678 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
679 if (strcmp (iso639_to_check, "sr") == 0)
680 iso3166_to_check = "SP";
683 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
687 if (!setlocale_called)
688 setlocale (LC_ALL, "");
690 if (!setlocale (LC_ALL, ""))
691 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
697 check_mixed_deps (void)
702 module = g_module_open (NULL, 0);
704 if (g_module_symbol (module, "gtk_progress_get_type", &func))
706 g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
709 g_module_close (module);
713 do_pre_parse_initialization (int *argc,
716 const gchar *env_string;
721 pre_initialized = TRUE;
725 gdk_pre_parse_libgtk_only ();
726 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
728 #ifdef G_ENABLE_DEBUG
729 env_string = g_getenv ("GTK_DEBUG");
730 if (env_string != NULL)
732 debug_flags = g_parse_debug_string (env_string,
734 G_N_ELEMENTS (gtk_debug_keys));
737 #endif /* G_ENABLE_DEBUG */
739 env_string = g_getenv ("GTK_MODULES");
741 gtk_modules_string = g_string_new (env_string);
745 gettext_initialization (void)
747 setlocale_initialization ();
750 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
751 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
752 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
753 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
754 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
760 do_post_parse_initialization (int *argc,
766 gettext_initialization ();
769 signal (SIGPIPE, SIG_IGN);
772 if (g_fatal_warnings)
774 GLogLevelFlags fatal_mask;
776 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
777 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
778 g_log_set_always_fatal (fatal_mask);
781 if (debug_flags & GTK_DEBUG_UPDATES)
782 gdk_window_set_debug_updates (TRUE);
785 /* Translate to default:RTL if you want your widgets
786 * to be RTL, otherwise translate to default:LTR.
787 * Do *not* translate it to "predefinito:LTR", if it
788 * it isn't default:LTR or default:RTL it will not work
790 char *e = _("default:LTR");
791 if (strcmp (e, "default:RTL")==0)
792 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
793 else if (strcmp (e, "default:LTR"))
794 g_warning ("Whoever translated default:LTR did so wrongly.\n");
797 /* do what the call to gtk_type_init() used to do */
800 _gtk_accel_map_init ();
803 /* Set the 'initialized' flag.
805 gtk_initialized = TRUE;
807 /* load gtk modules */
808 if (gtk_modules_string)
810 _gtk_modules_init (argc, argv, gtk_modules_string->str);
811 g_string_free (gtk_modules_string, TRUE);
815 _gtk_modules_init (argc, argv, NULL);
822 gboolean open_default_display;
826 pre_parse_hook (GOptionContext *context,
831 do_pre_parse_initialization (NULL, NULL);
837 post_parse_hook (GOptionContext *context,
842 OptionGroupInfo *info = data;
845 do_post_parse_initialization (NULL, NULL);
847 if (info->open_default_display)
849 if (gdk_display_open_default_libgtk_only () == NULL)
851 const char *display_name = gdk_get_display_arg_name ();
854 G_OPTION_ERROR_FAILED,
855 _("Cannot open display: %s"),
856 display_name ? display_name : "" );
867 * gtk_get_debug_flags:
869 * Returns the GTK+ debug flags setting.
872 gtk_get_debug_flags (void)
878 * gtk_set_debug_flags:
880 * Sets the GTK+ debug flags.
883 gtk_set_debug_flags (guint flags)
889 * gtk_get_option_group:
890 * @open_default_display: whether to open the default display
891 * when parsing the commandline arguments
893 * Returns a #GOptionGroup for the commandline arguments recognized
894 * by GTK+ and GDK. You should add this group to your #GOptionContext
895 * with g_option_context_add_group(), if you are using
896 * g_option_context_parse() to parse your commandline arguments.
898 * Returns: a #GOptionGroup for the commandline arguments recognized
904 gtk_get_option_group (gboolean open_default_display)
907 OptionGroupInfo *info;
909 gettext_initialization ();
911 info = g_new0 (OptionGroupInfo, 1);
912 info->open_default_display = open_default_display;
914 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
915 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
917 gdk_add_option_entries_libgtk_only (group);
918 g_option_group_add_entries (group, gtk_args);
919 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
925 * gtk_init_with_args:
926 * @argc: a pointer to the number of command line arguments.
927 * @argv: a pointer to the array of command line arguments.
928 * @parameter_string: a string which is displayed in
929 * the first line of <option>--help</option> output, after
930 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
931 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
932 * describing the options of your program
933 * @translation_domain: a translation domain to use for translating
934 * the <option>--help</option> output for the options in @entries
935 * and the @parameter_string with gettext(), or %NULL
936 * @error: a return location for errors
938 * This function does the same work as gtk_init_check().
939 * Additionally, it allows you to add your own commandline options,
940 * and it automatically generates nicely formatted
941 * <option>--help</option> output. Note that your program will
942 * be terminated after writing out the help output.
944 * Returns: %TRUE if the GUI has been successfully initialized,
950 gtk_init_with_args (gint *argc,
952 const gchar *parameter_string,
953 const GOptionEntry *entries,
954 const gchar *translation_domain,
957 GOptionContext *context;
958 GOptionGroup *gtk_group;
962 return gdk_display_open_default_libgtk_only () != NULL;
964 gettext_initialization ();
966 if (!check_setugid ())
969 gtk_group = gtk_get_option_group (TRUE);
971 context = g_option_context_new (parameter_string);
972 g_option_context_add_group (context, gtk_group);
973 g_option_context_set_translation_domain (context, translation_domain);
976 g_option_context_add_main_entries (context, entries, translation_domain);
977 retval = g_option_context_parse (context, argc, argv, error);
979 g_option_context_free (context);
987 * @argc: (inout): a pointer to the number of command line arguments.
988 * @argv: (array) (inout): a pointer to the array of command line arguments.
990 * Parses command line arguments, and initializes global
991 * attributes of GTK+, but does not actually open a connection
992 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
994 * Any arguments used by GTK+ or GDK are removed from the array and
995 * @argc and @argv are updated accordingly.
997 * You shouldn't call this function explicitely if you are using
998 * gtk_init(), or gtk_init_check().
1000 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1003 gtk_parse_args (int *argc,
1006 GOptionContext *option_context;
1007 GOptionGroup *gtk_group;
1008 GError *error = NULL;
1010 if (gtk_initialized)
1013 gettext_initialization ();
1015 if (!check_setugid ())
1018 option_context = g_option_context_new (NULL);
1019 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1020 g_option_context_set_help_enabled (option_context, FALSE);
1021 gtk_group = gtk_get_option_group (FALSE);
1022 g_option_context_set_main_group (option_context, gtk_group);
1023 if (!g_option_context_parse (option_context, argc, argv, &error))
1025 g_warning ("%s", error->message);
1026 g_error_free (error);
1029 g_option_context_free (option_context);
1034 #ifdef G_PLATFORM_WIN32
1035 #undef gtk_init_check
1040 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1041 * main() function. Changed if any arguments were handled.
1042 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1043 * Any parameters understood by gtk_init() are stripped before return.
1045 * This function does the same work as gtk_init() with only
1046 * a single change: It does not terminate the program if the GUI can't be
1047 * initialized. Instead it returns %FALSE on failure.
1049 * This way the application can fall back to some other means of communication
1050 * with the user - for example a curses or command line interface.
1052 * Return value: %TRUE if the GUI has been successfully initialized,
1056 gtk_init_check (int *argc,
1059 if (!gtk_parse_args (argc, argv))
1062 return gdk_display_open_default_libgtk_only () != NULL;
1065 #ifdef G_PLATFORM_WIN32
1071 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1072 * main() function. Changed if any arguments were handled.
1073 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1074 * Any parameters understood by gtk_init() are stripped before return.
1076 * Call this function before using any other GTK+ functions in your GUI
1077 * applications. It will initialize everything needed to operate the
1078 * toolkit and parses some standard command line options. @argc and
1079 * @argv are adjusted accordingly so your own code will
1080 * never see those standard arguments.
1082 * Note that there are some alternative ways to initialize GTK+:
1083 * if you are calling gtk_parse_args(), gtk_init_check(),
1084 * gtk_init_with_args() or g_option_context_parse() with
1085 * the option group returned by gtk_get_option_group(), you
1086 * <emphasis>don't</emphasis> have to call gtk_init().
1089 * This function will terminate your program if it was unable to initialize
1090 * the GUI for some reason. If you want your program to fall back to a
1091 * textual interface you want to call gtk_init_check() instead.
1095 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1096 * during initialization, to ignore SIGPIPE signals, since these are
1097 * almost never wanted in graphical applications. If you do need to
1098 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1099 * but notice that other libraries (e.g. libdbus or gvfs) might do
1104 gtk_init (int *argc, char ***argv)
1106 if (!gtk_init_check (argc, argv))
1108 const char *display_name_arg = gdk_get_display_arg_name ();
1109 if (display_name_arg == NULL)
1110 display_name_arg = getenv("DISPLAY");
1111 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1116 #ifdef G_PLATFORM_WIN32
1119 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1121 if (sizeof_GtkWindow != sizeof (GtkWindow))
1122 g_error ("Incompatible build!\n"
1123 "The code using GTK+ thinks GtkWindow is of different\n"
1124 "size than it actually is in this build of GTK+.\n"
1125 "On Windows, this probably means that you have compiled\n"
1126 "your code with gcc without the -mms-bitfields switch,\n"
1127 "or that you are using an unsupported compiler.");
1130 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1131 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1132 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1133 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1134 * -fnative-struct still matters. GtkBox is one such.
1137 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1139 if (sizeof_GtkBox != sizeof (GtkBox))
1140 g_error ("Incompatible build!\n"
1141 "The code using GTK+ thinks GtkBox is of different\n"
1142 "size than it actually is in this build of GTK+.\n"
1143 "On Windows, this probably means that you have compiled\n"
1144 "your code with gcc without the -mms-bitfields switch,\n"
1145 "or that you are using an unsupported compiler.");
1148 /* These two functions might get more checks added later, thus pass
1149 * in the number of extra args.
1152 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1154 check_sizeof_GtkWindow (sizeof_GtkWindow);
1155 if (num_checks >= 2)
1156 check_sizeof_GtkBox (sizeof_GtkBox);
1157 gtk_init (argc, argv);
1161 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1163 check_sizeof_GtkWindow (sizeof_GtkWindow);
1164 if (num_checks >= 2)
1165 check_sizeof_GtkBox (sizeof_GtkBox);
1166 return gtk_init_check (argc, argv);
1174 * Initializes internationalization support for GTK+. gtk_init()
1175 * automatically does this, so there is typically no point
1176 * in calling this function.
1178 * If you are calling this function because you changed the locale
1179 * after GTK+ is was initialized, then calling this function
1180 * may help a bit. (Note, however, that changing the locale
1181 * after GTK+ is initialized may produce inconsistent results and
1182 * is not really supported.)
1184 * In detail - sets the current locale according to the
1185 * program environment. This is the same as calling the C library function
1186 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1187 * locale specific setup of the windowing system used by GDK.
1189 * Returns: a string corresponding to the locale set, typically in the
1190 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1191 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1192 * result of the setlocale(); it is also used on other machines, such as
1193 * Windows, where the C library returns a different result. The string is
1194 * owned by GTK+ and should not be modified or freed.
1197 gtk_set_locale (void)
1199 return gdk_set_locale ();
1203 * _gtk_get_lc_ctype:
1205 * Return the Unix-style locale string for the language currently in
1206 * effect. On Unix systems, this is the return value from
1207 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1208 * affect this through the environment variables LC_ALL, LC_CTYPE or
1209 * LANG (checked in that order). The locale strings typically is in
1210 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1211 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1212 * Swedish as written in Finland or pt_BR for Portuguese as written in
1215 * On Windows, the C library doesn't use any such environment
1216 * variables, and setting them won't affect the behaviour of functions
1217 * like ctime(). The user sets the locale through the Regional Options
1218 * in the Control Panel. The C library (in the setlocale() function)
1219 * does not use country and language codes, but country and language
1220 * names spelled out in English.
1221 * However, this function does check the above environment
1222 * variables, and does return a Unix-style locale string based on
1223 * either said environment variables or the thread's current locale.
1225 * Return value: a dynamically allocated string, free with g_free().
1229 _gtk_get_lc_ctype (void)
1232 /* Somebody might try to set the locale for this process using the
1233 * LANG or LC_ environment variables. The Microsoft C library
1234 * doesn't know anything about them. You set the locale in the
1235 * Control Panel. Setting these env vars won't have any affect on
1236 * locale-dependent C library functions like ctime(). But just for
1237 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1238 * it easier to test GTK and Pango in various default languages, you
1239 * don't have to clickety-click in the Control Panel, you can simply
1240 * start the program with LC_ALL=something on the command line.)
1244 p = getenv ("LC_ALL");
1246 return g_strdup (p);
1248 p = getenv ("LC_CTYPE");
1250 return g_strdup (p);
1252 p = getenv ("LANG");
1254 return g_strdup (p);
1256 return g_win32_getlocale ();
1258 return g_strdup (setlocale (LC_CTYPE, NULL));
1263 * gtk_get_default_language:
1265 * Returns the #PangoLanguage for the default language currently in
1266 * effect. (Note that this can change over the life of an
1267 * application.) The default language is derived from the current
1268 * locale. It determines, for example, whether GTK+ uses the
1269 * right-to-left or left-to-right text direction.
1271 * This function is equivalent to pango_language_get_default(). See
1272 * that function for details.
1274 * Return value: the default language as a #PangoLanguage, must not be
1278 gtk_get_default_language (void)
1280 return pango_language_get_default ();
1289 gtk_main_loop_level++;
1291 loop = g_main_loop_new (NULL, TRUE);
1292 main_loops = g_slist_prepend (main_loops, loop);
1294 if (g_main_loop_is_running (main_loops->data))
1296 GDK_THREADS_LEAVE ();
1297 g_main_loop_run (loop);
1298 GDK_THREADS_ENTER ();
1304 GList *reinvoke_list = NULL;
1305 GtkQuitFunction *quitf;
1307 while (quit_functions)
1309 quitf = quit_functions->data;
1311 tmp_list = quit_functions;
1312 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1313 g_list_free_1 (tmp_list);
1315 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1316 gtk_quit_invoke_function (quitf))
1318 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1322 gtk_quit_destroy (quitf);
1329 work = g_list_last (reinvoke_list);
1331 quit_functions->prev = work;
1332 work->next = quit_functions;
1333 quit_functions = work;
1339 main_loops = g_slist_remove (main_loops, loop);
1341 g_main_loop_unref (loop);
1343 gtk_main_loop_level--;
1345 if (gtk_main_loop_level == 0)
1347 /* Try storing all clipboard data we have */
1348 _gtk_clipboard_store_all ();
1350 /* Synchronize the recent manager singleton */
1351 _gtk_recent_manager_sync ();
1356 gtk_main_level (void)
1358 return gtk_main_loop_level;
1362 gtk_main_quit (void)
1364 g_return_if_fail (main_loops != NULL);
1366 g_main_loop_quit (main_loops->data);
1370 gtk_events_pending (void)
1374 GDK_THREADS_LEAVE ();
1375 result = g_main_context_pending (NULL);
1376 GDK_THREADS_ENTER ();
1382 gtk_main_iteration (void)
1384 GDK_THREADS_LEAVE ();
1385 g_main_context_iteration (NULL, TRUE);
1386 GDK_THREADS_ENTER ();
1389 return !g_main_loop_is_running (main_loops->data);
1395 gtk_main_iteration_do (gboolean blocking)
1397 GDK_THREADS_LEAVE ();
1398 g_main_context_iteration (NULL, blocking);
1399 GDK_THREADS_ENTER ();
1402 return !g_main_loop_is_running (main_loops->data);
1407 /* private libgtk to libgdk interfaces
1409 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1411 GdkWindow **grab_window,
1412 gboolean *owner_events);
1415 rewrite_events_translate (GdkWindow *old_window,
1416 GdkWindow *new_window,
1420 gint old_origin_x, old_origin_y;
1421 gint new_origin_x, new_origin_y;
1423 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1424 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1426 *x += old_origin_x - new_origin_x;
1427 *y += old_origin_y - new_origin_y;
1431 rewrite_event_for_window (GdkEvent *event,
1432 GdkWindow *new_window)
1434 event = gdk_event_copy (event);
1436 switch (event->type)
1439 rewrite_events_translate (event->any.window,
1441 &event->scroll.x, &event->scroll.y);
1443 case GDK_BUTTON_PRESS:
1444 case GDK_2BUTTON_PRESS:
1445 case GDK_3BUTTON_PRESS:
1446 case GDK_BUTTON_RELEASE:
1447 rewrite_events_translate (event->any.window,
1449 &event->button.x, &event->button.y);
1451 case GDK_MOTION_NOTIFY:
1452 rewrite_events_translate (event->any.window,
1454 &event->motion.x, &event->motion.y);
1457 case GDK_KEY_RELEASE:
1458 case GDK_PROXIMITY_IN:
1459 case GDK_PROXIMITY_OUT:
1466 g_object_unref (event->any.window);
1467 event->any.window = g_object_ref (new_window);
1472 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1473 * then what X11 does is deliver the event normally if it was going to this
1474 * client, otherwise, delivers it in terms of the grab window. This function
1475 * rewrites events to the effect that events going to the same window group
1476 * are delivered normally, otherwise, the event is delivered in terms of the
1480 rewrite_event_for_grabs (GdkEvent *event)
1482 GdkWindow *grab_window;
1483 GtkWidget *event_widget, *grab_widget;
1484 gpointer grab_widget_ptr;
1485 gboolean owner_events;
1486 GdkDisplay *display;
1489 switch (event->type)
1492 case GDK_BUTTON_PRESS:
1493 case GDK_2BUTTON_PRESS:
1494 case GDK_3BUTTON_PRESS:
1495 case GDK_BUTTON_RELEASE:
1496 case GDK_MOTION_NOTIFY:
1497 case GDK_PROXIMITY_IN:
1498 case GDK_PROXIMITY_OUT:
1500 case GDK_KEY_RELEASE:
1501 display = gdk_window_get_display (event->any.window);
1502 device = gdk_event_get_device (event);
1504 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1512 event_widget = gtk_get_event_widget (event);
1513 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1514 grab_widget = grab_widget_ptr;
1517 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1518 return rewrite_event_for_window (event, grab_window);
1524 gtk_main_do_event (GdkEvent *event)
1526 GtkWidget *event_widget;
1527 GtkWidget *grab_widget = NULL;
1528 GtkWindowGroup *window_group;
1529 GdkEvent *rewritten_event = NULL;
1533 if (event->type == GDK_SETTING)
1535 _gtk_settings_handle_event (&event->setting);
1539 if (event->type == GDK_OWNER_CHANGE)
1541 _gtk_clipboard_handle_event (&event->owner_change);
1545 /* Find the widget which got the event. We store the widget
1546 * in the user_data field of GdkWindow's.
1547 * Ignore the event if we don't have a widget for it, except
1548 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1549 * Though this happens rarely, bogus events can occour
1550 * for e.g. destroyed GdkWindows.
1552 event_widget = gtk_get_event_widget (event);
1555 /* To handle selection INCR transactions, we select
1556 * PropertyNotify events on the requestor window and create
1557 * a corresponding (fake) GdkWindow so that events get
1558 * here. There won't be a widget though, so we have to handle
1561 if (event->type == GDK_PROPERTY_NOTIFY)
1562 _gtk_selection_incr_event (event->any.window,
1568 /* If pointer or keyboard grabs are in effect, munge the events
1569 * so that each window group looks like a separate app.
1571 rewritten_event = rewrite_event_for_grabs (event);
1572 if (rewritten_event)
1574 event = rewritten_event;
1575 event_widget = gtk_get_event_widget (event);
1578 window_group = gtk_main_get_window_group (event_widget);
1579 device = gdk_event_get_device (event);
1581 /* check whether there is a (device) grab in effect...
1584 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1586 if (!grab_widget && window_group->grabs)
1587 grab_widget = window_group->grabs->data;
1589 /* If the grab widget is an ancestor of the event widget
1590 * then we send the event to the original event widget.
1591 * This is the key to implementing modality.
1594 (gtk_widget_is_sensitive (event_widget) &&
1595 gtk_widget_is_ancestor (event_widget, grab_widget)))
1596 grab_widget = event_widget;
1598 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1600 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1602 if (rewritten_event)
1603 gdk_event_free (rewritten_event);
1608 /* Push the event onto a stack of current events for
1609 * gtk_current_event_get().
1611 current_events = g_list_prepend (current_events, event);
1613 /* Not all events get sent to the grabbing widget.
1614 * The delete, destroy, expose, focus change and resize
1615 * events still get sent to the event widget because
1616 * 1) these events have no meaning for the grabbing widget
1617 * and 2) redirecting these events to the grabbing widget
1618 * could cause the display to be messed up.
1620 * Drag events are also not redirected, since it isn't
1621 * clear what the semantics of that would be.
1623 switch (event->type)
1629 g_object_ref (event_widget);
1630 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1631 !gtk_widget_event (event_widget, event))
1632 gtk_widget_destroy (event_widget);
1633 g_object_unref (event_widget);
1637 /* Unexpected GDK_DESTROY from the outside, ignore for
1638 * child windows, handle like a GDK_DELETE for toplevels
1640 if (!gtk_widget_get_parent (event_widget))
1642 g_object_ref (event_widget);
1643 if (!gtk_widget_event (event_widget, event) &&
1644 gtk_widget_get_realized (event_widget))
1645 gtk_widget_destroy (event_widget);
1646 g_object_unref (event_widget);
1651 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1653 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1654 gtk_widget_send_expose (event_widget, event);
1655 gdk_window_end_paint (event->any.window);
1659 /* The app may paint with a previously allocated cairo_t,
1660 which will draw directly to the window. We can't catch cairo
1661 drap operatoins to automatically flush the window, thus we
1662 need to explicitly flush any outstanding moves or double
1664 gdk_window_flush (event->any.window);
1665 gtk_widget_send_expose (event_widget, event);
1669 case GDK_PROPERTY_NOTIFY:
1671 case GDK_FOCUS_CHANGE:
1675 case GDK_SELECTION_CLEAR:
1676 case GDK_SELECTION_REQUEST:
1677 case GDK_SELECTION_NOTIFY:
1678 case GDK_CLIENT_EVENT:
1679 case GDK_VISIBILITY_NOTIFY:
1680 case GDK_WINDOW_STATE:
1681 case GDK_GRAB_BROKEN:
1683 gtk_widget_event (event_widget, event);
1687 case GDK_BUTTON_PRESS:
1688 case GDK_2BUTTON_PRESS:
1689 case GDK_3BUTTON_PRESS:
1690 gtk_propagate_event (grab_widget, event);
1694 case GDK_KEY_RELEASE:
1697 if (gtk_invoke_key_snoopers (grab_widget, event))
1700 /* Catch alt press to enable auto-mnemonics;
1701 * menus are handled elsewhere
1703 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1704 !GTK_IS_MENU_SHELL (grab_widget))
1706 gboolean auto_mnemonics;
1708 g_object_get (gtk_widget_get_settings (grab_widget),
1709 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1713 gboolean mnemonics_visible;
1716 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1718 window = gtk_widget_get_toplevel (grab_widget);
1720 if (GTK_IS_WINDOW (window))
1721 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1724 /* else fall through */
1725 case GDK_MOTION_NOTIFY:
1726 case GDK_BUTTON_RELEASE:
1727 case GDK_PROXIMITY_IN:
1728 case GDK_PROXIMITY_OUT:
1729 gtk_propagate_event (grab_widget, event);
1732 case GDK_ENTER_NOTIFY:
1733 _gtk_widget_set_device_window (event_widget,
1734 gdk_event_get_device (event),
1736 if (gtk_widget_is_sensitive (grab_widget))
1737 gtk_widget_event (grab_widget, event);
1740 case GDK_LEAVE_NOTIFY:
1741 _gtk_widget_set_device_window (event_widget,
1742 gdk_event_get_device (event),
1744 if (gtk_widget_is_sensitive (grab_widget))
1745 gtk_widget_event (grab_widget, event);
1748 case GDK_DRAG_STATUS:
1749 case GDK_DROP_FINISHED:
1750 _gtk_drag_source_handle_event (event_widget, event);
1752 case GDK_DRAG_ENTER:
1753 case GDK_DRAG_LEAVE:
1754 case GDK_DRAG_MOTION:
1755 case GDK_DROP_START:
1756 _gtk_drag_dest_handle_event (event_widget, event);
1759 g_assert_not_reached ();
1763 if (event->type == GDK_ENTER_NOTIFY
1764 || event->type == GDK_LEAVE_NOTIFY
1765 || event->type == GDK_BUTTON_PRESS
1766 || event->type == GDK_2BUTTON_PRESS
1767 || event->type == GDK_3BUTTON_PRESS
1768 || event->type == GDK_KEY_PRESS
1769 || event->type == GDK_DRAG_ENTER
1770 || event->type == GDK_GRAB_BROKEN
1771 || event->type == GDK_MOTION_NOTIFY
1772 || event->type == GDK_SCROLL)
1774 _gtk_tooltip_handle_event (event);
1777 tmp_list = current_events;
1778 current_events = g_list_remove_link (current_events, tmp_list);
1779 g_list_free_1 (tmp_list);
1781 if (rewritten_event)
1782 gdk_event_free (rewritten_event);
1797 static GtkWindowGroup *
1798 gtk_main_get_window_group (GtkWidget *widget)
1800 GtkWidget *toplevel = NULL;
1803 toplevel = gtk_widget_get_toplevel (widget);
1805 if (GTK_IS_WINDOW (toplevel))
1806 return gtk_window_get_group (GTK_WINDOW (toplevel));
1808 return gtk_window_get_group (NULL);
1813 GtkWidget *old_grab_widget;
1814 GtkWidget *new_grab_widget;
1815 gboolean was_grabbed;
1816 gboolean is_grabbed;
1818 GList *notified_windows;
1823 synth_crossing_for_grab_notify (GtkWidget *from,
1825 GrabNotifyInfo *info,
1827 GdkCrossingMode mode)
1831 GdkDevice *device = devices->data;
1832 GdkWindow *from_window, *to_window;
1834 /* Do not propagate events more than once to
1835 * the same windows if non-multidevice aware.
1841 from_window = _gtk_widget_get_device_window (from, device);
1844 !gdk_window_get_support_multidevice (from_window) &&
1845 g_list_find (info->notified_windows, from_window))
1853 to_window = _gtk_widget_get_device_window (to, device);
1856 !gdk_window_get_support_multidevice (to_window) &&
1857 g_list_find (info->notified_windows, to_window))
1861 if (from_window || to_window)
1863 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1864 (to_window) ? to : NULL,
1868 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1871 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1874 devices = devices->next;
1879 gtk_grab_notify_foreach (GtkWidget *child,
1882 GrabNotifyInfo *info = data;
1883 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1886 was_grabbed = info->was_grabbed;
1887 is_grabbed = info->is_grabbed;
1889 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1890 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1892 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1893 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1895 g_object_ref (child);
1897 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1898 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1901 _gtk_widget_get_device_window (child, info->device))
1903 /* Device specified and is on widget */
1904 devices = g_list_prepend (NULL, info->device);
1907 devices = _gtk_widget_list_devices (child);
1911 _gtk_widget_set_shadowed (child, TRUE);
1912 if (!was_shadowed && devices &&
1913 gtk_widget_is_sensitive (child))
1914 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1916 GDK_CROSSING_GTK_GRAB);
1920 _gtk_widget_set_shadowed (child, FALSE);
1921 if (was_shadowed && devices &&
1922 gtk_widget_is_sensitive (child))
1923 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1925 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1926 GDK_CROSSING_GTK_UNGRAB);
1929 if (was_shadowed != is_shadowed)
1930 _gtk_widget_grab_notify (child, was_shadowed);
1932 g_object_unref (child);
1933 g_list_free (devices);
1935 info->was_grabbed = was_grabbed;
1936 info->is_grabbed = is_grabbed;
1940 gtk_grab_notify (GtkWindowGroup *group,
1942 GtkWidget *old_grab_widget,
1943 GtkWidget *new_grab_widget,
1947 GrabNotifyInfo info = { 0 };
1949 if (old_grab_widget == new_grab_widget)
1952 info.old_grab_widget = old_grab_widget;
1953 info.new_grab_widget = new_grab_widget;
1954 info.from_grab = from_grab;
1955 info.device = device;
1957 g_object_ref (group);
1959 toplevels = gtk_window_list_toplevels ();
1960 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1964 GtkWindow *toplevel = toplevels->data;
1965 toplevels = g_list_delete_link (toplevels, toplevels);
1967 info.was_grabbed = FALSE;
1968 info.is_grabbed = FALSE;
1970 if (group == gtk_window_get_group (toplevel))
1971 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1972 g_object_unref (toplevel);
1975 g_list_free (info.notified_windows);
1976 g_object_unref (group);
1980 gtk_grab_add (GtkWidget *widget)
1982 GtkWindowGroup *group;
1983 GtkWidget *old_grab_widget;
1985 g_return_if_fail (widget != NULL);
1987 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1989 _gtk_widget_set_has_grab (widget, TRUE);
1991 group = gtk_main_get_window_group (widget);
1994 old_grab_widget = (GtkWidget *)group->grabs->data;
1996 old_grab_widget = NULL;
1998 g_object_ref (widget);
1999 group->grabs = g_slist_prepend (group->grabs, widget);
2001 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
2006 * gtk_grab_get_current:
2008 * Queries the current grab of the default window group.
2010 * Return value: (transfer none): The widget which currently
2011 * has the grab or %NULL if no grab is active
2014 gtk_grab_get_current (void)
2016 GtkWindowGroup *group;
2018 group = gtk_main_get_window_group (NULL);
2021 return GTK_WIDGET (group->grabs->data);
2026 gtk_grab_remove (GtkWidget *widget)
2028 GtkWindowGroup *group;
2029 GtkWidget *new_grab_widget;
2031 g_return_if_fail (widget != NULL);
2033 if (gtk_widget_has_grab (widget))
2035 _gtk_widget_set_has_grab (widget, FALSE);
2037 group = gtk_main_get_window_group (widget);
2038 group->grabs = g_slist_remove (group->grabs, widget);
2041 new_grab_widget = (GtkWidget *)group->grabs->data;
2043 new_grab_widget = NULL;
2045 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2047 g_object_unref (widget);
2052 * gtk_device_grab_add:
2053 * @widget: a #GtkWidget
2054 * @device: a #GtkDevice to grab on.
2055 * @block_others: %TRUE to prevent other devices to interact with @widget.
2057 * Adds a GTK+ grab on @device, so all the events on @device and its
2058 * associated pointer or keyboard (if any) are delivered to @widget.
2059 * If the @block_others parameter is %TRUE, any other devices will be
2060 * unable to interact with @widget during the grab.
2065 gtk_device_grab_add (GtkWidget *widget,
2067 gboolean block_others)
2069 GtkWindowGroup *group;
2070 GtkWidget *old_grab_widget;
2072 g_return_if_fail (GTK_IS_WIDGET (widget));
2073 g_return_if_fail (GDK_IS_DEVICE (device));
2075 group = gtk_main_get_window_group (widget);
2076 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2078 if (old_grab_widget != widget)
2079 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2081 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2085 * gtk_device_grab_remove:
2086 * @widget: a #GtkWidget
2087 * @device: a #GdkDevice
2089 * Removes a device grab from the given widget. You have to pair calls
2090 * to gtk_device_grab_add() and gtk_device_grab_remove().
2095 gtk_device_grab_remove (GtkWidget *widget,
2098 GtkWindowGroup *group;
2099 GtkWidget *new_grab_widget;
2101 g_return_if_fail (GTK_IS_WIDGET (widget));
2102 g_return_if_fail (GDK_IS_DEVICE (device));
2104 group = gtk_main_get_window_group (widget);
2105 _gtk_window_group_remove_device_grab (group, widget, device);
2106 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2108 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2112 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2115 GtkKeySnooperData *data;
2116 static guint snooper_id = 1;
2118 g_return_val_if_fail (snooper != NULL, 0);
2120 data = g_new (GtkKeySnooperData, 1);
2121 data->func = snooper;
2122 data->func_data = func_data;
2123 data->id = snooper_id++;
2124 key_snoopers = g_slist_prepend (key_snoopers, data);
2130 gtk_key_snooper_remove (guint snooper_id)
2132 GtkKeySnooperData *data = NULL;
2135 slist = key_snoopers;
2139 if (data->id == snooper_id)
2142 slist = slist->next;
2147 key_snoopers = g_slist_remove (key_snoopers, data);
2153 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2157 gint return_val = FALSE;
2159 slist = key_snoopers;
2160 while (slist && !return_val)
2162 GtkKeySnooperData *data;
2165 slist = slist->next;
2166 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2173 gtk_quit_add_full (guint main_level,
2174 GtkFunction function,
2175 GtkCallbackMarshal marshal,
2177 GDestroyNotify destroy)
2179 static guint quit_id = 1;
2180 GtkQuitFunction *quitf;
2182 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2184 quitf = g_slice_new (GtkQuitFunction);
2186 quitf->id = quit_id++;
2187 quitf->main_level = main_level;
2188 quitf->function = function;
2189 quitf->marshal = marshal;
2191 quitf->destroy = destroy;
2193 quit_functions = g_list_prepend (quit_functions, quitf);
2199 gtk_quit_destroy (GtkQuitFunction *quitf)
2202 quitf->destroy (quitf->data);
2203 g_slice_free (GtkQuitFunction, quitf);
2207 gtk_quit_destructor (GtkWidget **object_p)
2210 gtk_widget_destroy (*object_p);
2217 gtk_quit_add_destroy (guint main_level,
2220 GtkWidget **object_p;
2222 g_return_if_fail (main_level > 0);
2223 g_return_if_fail (GTK_IS_WIDGET (object));
2225 object_p = g_new (GtkWidget*, 1);
2227 g_signal_connect (object,
2229 G_CALLBACK (gtk_widget_destroyed),
2231 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2235 gtk_quit_add (guint main_level,
2236 GtkFunction function,
2239 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2243 gtk_quit_remove (guint id)
2245 GtkQuitFunction *quitf;
2248 tmp_list = quit_functions;
2251 quitf = tmp_list->data;
2253 if (quitf->id == id)
2255 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2256 g_list_free (tmp_list);
2257 gtk_quit_destroy (quitf);
2262 tmp_list = tmp_list->next;
2267 gtk_quit_remove_by_data (gpointer data)
2269 GtkQuitFunction *quitf;
2272 tmp_list = quit_functions;
2275 quitf = tmp_list->data;
2277 if (quitf->data == data)
2279 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2280 g_list_free (tmp_list);
2281 gtk_quit_destroy (quitf);
2286 tmp_list = tmp_list->next;
2291 * gtk_get_current_event:
2293 * Obtains a copy of the event currently being processed by GTK+. For
2294 * example, if you get a "clicked" signal from #GtkButton, the current
2295 * event will be the #GdkEventButton that triggered the "clicked"
2296 * signal. The returned event must be freed with gdk_event_free().
2297 * If there is no current event, the function returns %NULL.
2299 * Return value: a copy of the current event, or %NULL if no current event.
2302 gtk_get_current_event (void)
2305 return gdk_event_copy (current_events->data);
2311 * gtk_get_current_event_time:
2313 * If there is a current event and it has a timestamp, return that
2314 * timestamp, otherwise return %GDK_CURRENT_TIME.
2316 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2319 gtk_get_current_event_time (void)
2322 return gdk_event_get_time (current_events->data);
2324 return GDK_CURRENT_TIME;
2328 * gtk_get_current_event_state:
2329 * @state: a location to store the state of the current event
2331 * If there is a current event and it has a state field, place
2332 * that state field in @state and return %TRUE, otherwise return
2335 * Return value: %TRUE if there was a current event and it had a state field
2338 gtk_get_current_event_state (GdkModifierType *state)
2340 g_return_val_if_fail (state != NULL, FALSE);
2343 return gdk_event_get_state (current_events->data, state);
2352 * gtk_get_current_event_device:
2354 * If there is a current event and it has a device, return that
2355 * device, otherwise return %NULL.
2357 * Returns: (transfer none): a #GdkDevice, or %NULL
2360 gtk_get_current_event_device (void)
2363 return gdk_event_get_device (current_events->data);
2369 * gtk_get_event_widget:
2370 * @event: a #GdkEvent
2372 * If @event is %NULL or the event was not associated with any widget,
2373 * returns %NULL, otherwise returns the widget that received the event
2376 * Return value: (transfer none): the widget that originally
2377 * received @event, or %NULL
2380 gtk_get_event_widget (GdkEvent *event)
2383 gpointer widget_ptr;
2386 if (event && event->any.window &&
2387 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2389 gdk_window_get_user_data (event->any.window, &widget_ptr);
2390 widget = widget_ptr;
2397 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2399 if (!quitf->marshal)
2400 return quitf->function (quitf->data);
2404 gint ret_val = FALSE;
2406 args[0].name = NULL;
2407 args[0].type = G_TYPE_BOOLEAN;
2408 args[0].d.pointer_data = &ret_val;
2409 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2417 * gtk_propagate_event:
2418 * @widget: a #GtkWidget
2421 * Sends an event to a widget, propagating the event to parent widgets
2422 * if the event remains unhandled. Events received by GTK+ from GDK
2423 * normally begin in gtk_main_do_event(). Depending on the type of
2424 * event, existence of modal dialogs, grabs, etc., the event may be
2425 * propagated; if so, this function is used. gtk_propagate_event()
2426 * calls gtk_widget_event() on each widget it decides to send the
2427 * event to. So gtk_widget_event() is the lowest-level function; it
2428 * simply emits the "event" and possibly an event-specific signal on a
2429 * widget. gtk_propagate_event() is a bit higher-level, and
2430 * gtk_main_do_event() is the highest level.
2432 * All that said, you most likely don't want to use any of these
2433 * functions; synthesizing events is rarely needed. Consider asking on
2434 * the mailing list for better ways to achieve your goals. For
2435 * example, use gdk_window_invalidate_rect() or
2436 * gtk_widget_queue_draw() instead of making up expose events.
2440 gtk_propagate_event (GtkWidget *widget,
2445 g_return_if_fail (GTK_IS_WIDGET (widget));
2446 g_return_if_fail (event != NULL);
2448 handled_event = FALSE;
2450 g_object_ref (widget);
2452 if ((event->type == GDK_KEY_PRESS) ||
2453 (event->type == GDK_KEY_RELEASE))
2455 /* Only send key events within Window widgets to the Window
2456 * The Window widget will in turn pass the
2457 * key event on to the currently focused widget
2462 window = gtk_widget_get_toplevel (widget);
2463 if (GTK_IS_WINDOW (window))
2465 /* If there is a grab within the window, give the grab widget
2466 * a first crack at the key event
2468 if (widget != window && gtk_widget_has_grab (widget))
2469 handled_event = gtk_widget_event (widget, event);
2473 window = gtk_widget_get_toplevel (widget);
2474 if (GTK_IS_WINDOW (window))
2476 if (gtk_widget_is_sensitive (window))
2477 gtk_widget_event (window, event);
2481 handled_event = TRUE; /* don't send to widget */
2485 /* Other events get propagated up the widget tree
2486 * so that parents can see the button and motion
2487 * events of the children.
2495 /* Scroll events are special cased here because it
2496 * feels wrong when scrolling a GtkViewport, say,
2497 * to have children of the viewport eat the scroll
2500 if (!gtk_widget_is_sensitive (widget))
2501 handled_event = event->type != GDK_SCROLL;
2503 handled_event = gtk_widget_event (widget, event);
2505 tmp = gtk_widget_get_parent (widget);
2506 g_object_unref (widget);
2510 if (!handled_event && widget)
2511 g_object_ref (widget);
2517 g_object_unref (widget);
2521 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2522 GValue *return_accu,
2523 const GValue *handler_return,
2526 gboolean continue_emission;
2527 gboolean signal_handled;
2529 signal_handled = g_value_get_boolean (handler_return);
2530 g_value_set_boolean (return_accu, signal_handled);
2531 continue_emission = !signal_handled;
2533 return continue_emission;