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 _GtkInitFunction GtkInitFunction;
150 typedef struct _GtkQuitFunction GtkQuitFunction;
151 typedef struct _GtkKeySnooperData GtkKeySnooperData;
153 struct _GtkInitFunction
155 GtkFunction function;
159 struct _GtkQuitFunction
163 GtkCallbackMarshal marshal;
164 GtkFunction function;
166 GDestroyNotify destroy;
169 struct _GtkKeySnooperData
171 GtkKeySnoopFunc func;
176 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
177 static void gtk_quit_destroy (GtkQuitFunction *quitf);
178 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
181 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
183 static guint gtk_main_loop_level = 0;
184 static gint pre_initialized = FALSE;
185 static gint gtk_initialized = FALSE;
186 static GList *current_events = NULL;
188 static GSList *main_loops = NULL; /* stack of currently executing main loops */
190 static GList *init_functions = NULL; /* A list of init functions.
192 static GList *quit_functions = NULL; /* A list of quit functions.
194 static GSList *key_snoopers = NULL;
196 static guint debug_flags = 0; /* Global GTK debug flag */
198 #ifdef G_ENABLE_DEBUG
199 static const GDebugKey gtk_debug_keys[] = {
200 {"misc", GTK_DEBUG_MISC},
201 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
202 {"text", GTK_DEBUG_TEXT},
203 {"tree", GTK_DEBUG_TREE},
204 {"updates", GTK_DEBUG_UPDATES},
205 {"keybindings", GTK_DEBUG_KEYBINDINGS},
206 {"multihead", GTK_DEBUG_MULTIHEAD},
207 {"modules", GTK_DEBUG_MODULES},
208 {"geometry", GTK_DEBUG_GEOMETRY},
209 {"icontheme", GTK_DEBUG_ICONTHEME},
210 {"printing", GTK_DEBUG_PRINTING},
211 {"builder", GTK_DEBUG_BUILDER},
212 {"size-request", GTK_DEBUG_SIZE_REQUEST},
214 #endif /* G_ENABLE_DEBUG */
217 * gtk_get_major_version:
219 * Returns the major version number of the GTK+ library. (e.g. in GTK+ version
222 * This function is in the library, so it represents the GTK+ library
223 * your code is running against. Contrast with the #GTK_MAJOR_VERSION
224 * macro, which represents the major version of the GTK+ headers you
225 * have included when compiling your code.
227 * Returns: the major version number of the GTK+ library.
232 gtk_get_major_version (void)
234 return GTK_MAJOR_VERSION;
238 * gtk_get_minor_version:
240 * Returns the minor version number of the GTK+ library. (e.g. in GTK+ version
243 * This function is in the library, so it represents the GTK+ library
244 * your code is are running against. Contrast with the
245 * #GTK_MINOR_VERSION macro, which represents the minor version of the
246 * GTK+ headers you have included when compiling your code.
248 * Returns: the minor version number of the GTK+ library.
253 gtk_get_minor_version (void)
255 return GTK_MINOR_VERSION;
259 * gtk_get_micro_version:
261 * Returns the micro version number of the GTK+ library. (e.g. in GTK+ version
264 * This function is in the library, so it represents the GTK+ library
265 * your code is are running against. Contrast with the
266 * #GTK_MICRO_VERSION macro, which represents the micro version of the
267 * GTK+ headers you have included when compiling your code.
269 * Returns: the micro version number of the GTK+ library.
274 gtk_get_micro_version (void)
276 return GTK_MICRO_VERSION;
280 * gtk_get_binary_age:
282 * Returns the binary age as passed to
283 * <application>libtool</application> when building the GTK+ library
284 * the process is running against. If
285 * <application>libtool</application> means nothing to you, don't
288 * Returns: the binary age of the GTK+ library.
293 gtk_get_binary_age (void)
295 return GTK_BINARY_AGE;
299 * gtk_get_interface_age:
301 * Returns the interface age as passed to
302 * <application>libtool</application> when building the GTK+ library
303 * the process is running against. If
304 * <application>libtool</application> means nothing to you, don't
307 * Returns: the interface age of the GTK+ library.
312 gtk_get_interface_age (void)
314 return GTK_INTERFACE_AGE;
319 * @required_major: the required major version.
320 * @required_minor: the required minor version.
321 * @required_micro: the required micro version.
323 * Checks that the GTK+ library in use is compatible with the
324 * given version. Generally you would pass in the constants
325 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
326 * as the three arguments to this function; that produces
327 * a check that the library in use is compatible with
328 * the version of GTK+ the application or module was compiled
331 * Compatibility is defined by two things: first the version
332 * of the running library is newer than the version
333 * @required_major.required_minor.@required_micro. Second
334 * the running library must be binary compatible with the
335 * version @required_major.required_minor.@required_micro
336 * (same major version.)
338 * This function is primarily for GTK+ modules; the module
339 * can call this function to check that it wasn't loaded
340 * into an incompatible version of GTK+. However, such a
341 * check isn't completely reliable, since the module may be
342 * linked against an old version of GTK+ and calling the
343 * old version of gtk_check_version(), but still get loaded
344 * into an application using a newer version of GTK+.
346 * Return value: %NULL if the GTK+ library is compatible with the
347 * given version, or a string describing the version mismatch.
348 * The returned string is owned by GTK+ and should not be modified
352 gtk_check_version (guint required_major,
353 guint required_minor,
354 guint required_micro)
356 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
357 gint required_effective_micro = 100 * required_minor + required_micro;
359 if (required_major > GTK_MAJOR_VERSION)
360 return "Gtk+ version too old (major mismatch)";
361 if (required_major < GTK_MAJOR_VERSION)
362 return "Gtk+ version too new (major mismatch)";
363 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
364 return "Gtk+ version too new (micro mismatch)";
365 if (required_effective_micro > gtk_effective_micro)
366 return "Gtk+ version too old (micro mismatch)";
370 /* This checks to see if the process is running suid or sgid
371 * at the current time. If so, we don't allow GTK+ to be initialized.
372 * This is meant to be a mild check - we only error out if we
373 * can prove the programmer is doing something wrong, not if
374 * they could be doing something wrong. For this reason, we
375 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
380 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
382 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
383 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
385 #ifdef HAVE_GETRESUID
386 /* These aren't in the header files, so we prototype them here.
388 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
389 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
391 if (getresuid (&ruid, &euid, &suid) != 0 ||
392 getresgid (&rgid, &egid, &sgid) != 0)
393 #endif /* HAVE_GETRESUID */
395 suid = ruid = getuid ();
396 sgid = rgid = getgid ();
401 if (ruid != euid || ruid != suid ||
402 rgid != egid || rgid != sgid)
404 g_warning ("This process is currently running setuid or setgid.\n"
405 "This is not a supported use of GTK+. You must create a helper\n"
406 "program instead. For further details, see:\n\n"
407 " http://www.gtk.org/setuid.html\n\n"
408 "Refusing to initialize GTK+.");
418 _gtk_get_datadir (void)
420 static char *gtk_datadir = NULL;
421 if (gtk_datadir == NULL)
423 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
424 gtk_datadir = g_build_filename (root, "share", NULL);
432 _gtk_get_sysconfdir (void)
434 static char *gtk_sysconfdir = NULL;
435 if (gtk_sysconfdir == NULL)
437 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
438 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
442 return gtk_sysconfdir;
446 _gtk_get_data_prefix (void)
448 static char *gtk_data_prefix = NULL;
449 if (gtk_data_prefix == NULL)
450 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
452 return gtk_data_prefix;
455 #endif /* G_OS_WIN32 */
457 static gboolean do_setlocale = TRUE;
460 * gtk_disable_setlocale:
462 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
463 * gtk_parse_args() from automatically
464 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
465 * want to use this function if you wanted to set the locale for
466 * your program to something other than the user's locale, or if
467 * you wanted to set different values for different locale categories.
469 * Most programs should not need to call this function.
472 gtk_disable_setlocale (void)
475 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
477 do_setlocale = FALSE;
480 #ifdef G_PLATFORM_WIN32
481 #undef gtk_init_check
484 static GString *gtk_modules_string = NULL;
485 static gboolean g_fatal_warnings = FALSE;
487 #ifdef G_ENABLE_DEBUG
489 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
491 debug_flags |= g_parse_debug_string (value,
493 G_N_ELEMENTS (gtk_debug_keys));
499 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
501 debug_flags &= ~g_parse_debug_string (value,
503 G_N_ELEMENTS (gtk_debug_keys));
507 #endif /* G_ENABLE_DEBUG */
510 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
514 if (gtk_modules_string)
515 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
517 gtk_modules_string = g_string_new (NULL);
519 g_string_append (gtk_modules_string, value);
525 static const GOptionEntry gtk_args[] = {
526 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
527 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
528 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
529 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
530 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
531 #ifdef G_ENABLE_DEBUG
532 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
533 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
534 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
535 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
536 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
537 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
544 static char *iso639_to_check = NULL;
545 static char *iso3166_to_check = NULL;
546 static char *script_to_check = NULL;
547 static gboolean setlocale_called = FALSE;
550 enum_locale_proc (LPTSTR locale)
558 lcid = strtoul (locale, &endptr, 16);
559 if (*endptr == '\0' &&
560 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
561 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
563 if (strcmp (iso639, iso639_to_check) == 0 &&
564 ((iso3166_to_check != NULL &&
565 strcmp (iso3166, iso3166_to_check) == 0) ||
566 (iso3166_to_check == NULL &&
567 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
569 char language[100], country[100];
572 if (script_to_check != NULL)
574 /* If lcid is the "other" script for this language,
575 * return TRUE, i.e. continue looking.
577 if (strcmp (script_to_check, "Latn") == 0)
579 switch (LANGIDFROMLCID (lcid))
581 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
583 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
585 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
587 case MAKELANGID (LANG_SERBIAN, 0x07):
588 /* Serbian in Bosnia and Herzegovina, Cyrillic */
592 else if (strcmp (script_to_check, "Cyrl") == 0)
594 switch (LANGIDFROMLCID (lcid))
596 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
598 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
600 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
602 case MAKELANGID (LANG_SERBIAN, 0x06):
603 /* Serbian in Bosnia and Herzegovina, Latin */
609 SetThreadLocale (lcid);
611 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
612 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
614 strcpy (locale, language);
615 strcat (locale, "_");
616 strcat (locale, country);
618 if (setlocale (LC_ALL, locale) != NULL)
619 setlocale_called = TRUE;
632 setlocale_initialization (void)
634 static gboolean initialized = FALSE;
643 /* If some of the POSIXish environment variables are set, set
644 * the Win32 thread locale correspondingly.
646 char *p = getenv ("LC_ALL");
653 if (strcmp (p, "C") == 0)
654 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
657 /* Check if one of the supported locales match the
658 * environment variable. If so, use that locale.
661 iso3166_to_check = strchr (iso639_to_check, '_');
662 if (iso3166_to_check != NULL)
664 *iso3166_to_check++ = '\0';
666 script_to_check = strchr (iso3166_to_check, '@');
667 if (script_to_check != NULL)
668 *script_to_check++ = '\0';
670 /* Handle special cases. */
672 /* The standard code for Serbia and Montenegro was
673 * "CS", but MSFT uses for some reason "SP". By now
674 * (October 2006), SP has split into two, "RS" and
675 * "ME", but don't bother trying to handle those
676 * yet. Do handle the even older "YU", though.
678 if (strcmp (iso3166_to_check, "CS") == 0 ||
679 strcmp (iso3166_to_check, "YU") == 0)
680 iso3166_to_check = "SP";
684 script_to_check = strchr (iso639_to_check, '@');
685 if (script_to_check != NULL)
686 *script_to_check++ = '\0';
687 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
688 if (strcmp (iso639_to_check, "sr") == 0)
689 iso3166_to_check = "SP";
692 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
696 if (!setlocale_called)
697 setlocale (LC_ALL, "");
699 if (!setlocale (LC_ALL, ""))
700 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
706 check_mixed_deps (void)
711 module = g_module_open (NULL, 0);
713 if (g_module_symbol (module, "gtk_progress_get_type", &func))
715 g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
718 g_module_close (module);
722 do_pre_parse_initialization (int *argc,
725 const gchar *env_string;
730 pre_initialized = TRUE;
734 gdk_pre_parse_libgtk_only ();
735 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
737 #ifdef G_ENABLE_DEBUG
738 env_string = g_getenv ("GTK_DEBUG");
739 if (env_string != NULL)
741 debug_flags = g_parse_debug_string (env_string,
743 G_N_ELEMENTS (gtk_debug_keys));
746 #endif /* G_ENABLE_DEBUG */
748 env_string = g_getenv ("GTK_MODULES");
750 gtk_modules_string = g_string_new (env_string);
754 gettext_initialization (void)
756 setlocale_initialization ();
759 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
760 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
761 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
762 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
763 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
769 do_post_parse_initialization (int *argc,
775 gettext_initialization ();
778 signal (SIGPIPE, SIG_IGN);
781 if (g_fatal_warnings)
783 GLogLevelFlags fatal_mask;
785 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
786 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
787 g_log_set_always_fatal (fatal_mask);
790 if (debug_flags & GTK_DEBUG_UPDATES)
791 gdk_window_set_debug_updates (TRUE);
794 /* Translate to default:RTL if you want your widgets
795 * to be RTL, otherwise translate to default:LTR.
796 * Do *not* translate it to "predefinito:LTR", if it
797 * it isn't default:LTR or default:RTL it will not work
799 char *e = _("default:LTR");
800 if (strcmp (e, "default:RTL")==0)
801 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
802 else if (strcmp (e, "default:LTR"))
803 g_warning ("Whoever translated default:LTR did so wrongly.\n");
806 /* do what the call to gtk_type_init() used to do */
809 _gtk_accel_map_init ();
812 /* Set the 'initialized' flag.
814 gtk_initialized = TRUE;
816 /* load gtk modules */
817 if (gtk_modules_string)
819 _gtk_modules_init (argc, argv, gtk_modules_string->str);
820 g_string_free (gtk_modules_string, TRUE);
824 _gtk_modules_init (argc, argv, NULL);
831 gboolean open_default_display;
835 pre_parse_hook (GOptionContext *context,
840 do_pre_parse_initialization (NULL, NULL);
846 post_parse_hook (GOptionContext *context,
851 OptionGroupInfo *info = data;
854 do_post_parse_initialization (NULL, NULL);
856 if (info->open_default_display)
858 if (gdk_display_open_default_libgtk_only () == NULL)
860 const char *display_name = gdk_get_display_arg_name ();
863 G_OPTION_ERROR_FAILED,
864 _("Cannot open display: %s"),
865 display_name ? display_name : "" );
876 * gtk_get_debug_flags:
878 * Returns the GTK+ debug flags setting.
881 gtk_get_debug_flags (void)
887 * gtk_set_debug_flags:
889 * Sets the GTK+ debug flags.
892 gtk_set_debug_flags (guint flags)
898 * gtk_get_option_group:
899 * @open_default_display: whether to open the default display
900 * when parsing the commandline arguments
902 * Returns a #GOptionGroup for the commandline arguments recognized
903 * by GTK+ and GDK. You should add this group to your #GOptionContext
904 * with g_option_context_add_group(), if you are using
905 * g_option_context_parse() to parse your commandline arguments.
907 * Returns: a #GOptionGroup for the commandline arguments recognized
913 gtk_get_option_group (gboolean open_default_display)
916 OptionGroupInfo *info;
918 gettext_initialization ();
920 info = g_new0 (OptionGroupInfo, 1);
921 info->open_default_display = open_default_display;
923 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
924 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
926 gdk_add_option_entries_libgtk_only (group);
927 g_option_group_add_entries (group, gtk_args);
928 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
934 * gtk_init_with_args:
935 * @argc: a pointer to the number of command line arguments.
936 * @argv: a pointer to the array of command line arguments.
937 * @parameter_string: a string which is displayed in
938 * the first line of <option>--help</option> output, after
939 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
940 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
941 * describing the options of your program
942 * @translation_domain: a translation domain to use for translating
943 * the <option>--help</option> output for the options in @entries
944 * and the @parameter_string with gettext(), or %NULL
945 * @error: a return location for errors
947 * This function does the same work as gtk_init_check().
948 * Additionally, it allows you to add your own commandline options,
949 * and it automatically generates nicely formatted
950 * <option>--help</option> output. Note that your program will
951 * be terminated after writing out the help output.
953 * Returns: %TRUE if the GUI has been successfully initialized,
959 gtk_init_with_args (gint *argc,
961 const gchar *parameter_string,
962 const GOptionEntry *entries,
963 const gchar *translation_domain,
966 GOptionContext *context;
967 GOptionGroup *gtk_group;
971 return gdk_display_open_default_libgtk_only () != NULL;
973 gettext_initialization ();
975 if (!check_setugid ())
978 gtk_group = gtk_get_option_group (TRUE);
980 context = g_option_context_new (parameter_string);
981 g_option_context_add_group (context, gtk_group);
982 g_option_context_set_translation_domain (context, translation_domain);
985 g_option_context_add_main_entries (context, entries, translation_domain);
986 retval = g_option_context_parse (context, argc, argv, error);
988 g_option_context_free (context);
996 * @argc: (inout): a pointer to the number of command line arguments.
997 * @argv: (array) (inout): a pointer to the array of command line arguments.
999 * Parses command line arguments, and initializes global
1000 * attributes of GTK+, but does not actually open a connection
1001 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
1003 * Any arguments used by GTK+ or GDK are removed from the array and
1004 * @argc and @argv are updated accordingly.
1006 * You shouldn't call this function explicitely if you are using
1007 * gtk_init(), or gtk_init_check().
1009 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1012 gtk_parse_args (int *argc,
1015 GOptionContext *option_context;
1016 GOptionGroup *gtk_group;
1017 GError *error = NULL;
1019 if (gtk_initialized)
1022 gettext_initialization ();
1024 if (!check_setugid ())
1027 option_context = g_option_context_new (NULL);
1028 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1029 g_option_context_set_help_enabled (option_context, FALSE);
1030 gtk_group = gtk_get_option_group (FALSE);
1031 g_option_context_set_main_group (option_context, gtk_group);
1032 if (!g_option_context_parse (option_context, argc, argv, &error))
1034 g_warning ("%s", error->message);
1035 g_error_free (error);
1038 g_option_context_free (option_context);
1043 #ifdef G_PLATFORM_WIN32
1044 #undef gtk_init_check
1049 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1050 * main() function. Changed if any arguments were handled.
1051 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1052 * Any parameters understood by gtk_init() are stripped before return.
1054 * This function does the same work as gtk_init() with only
1055 * a single change: It does not terminate the program if the GUI can't be
1056 * initialized. Instead it returns %FALSE on failure.
1058 * This way the application can fall back to some other means of communication
1059 * with the user - for example a curses or command line interface.
1061 * Return value: %TRUE if the GUI has been successfully initialized,
1065 gtk_init_check (int *argc,
1068 if (!gtk_parse_args (argc, argv))
1071 return gdk_display_open_default_libgtk_only () != NULL;
1074 #ifdef G_PLATFORM_WIN32
1080 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1081 * main() function. Changed if any arguments were handled.
1082 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1083 * Any parameters understood by gtk_init() are stripped before return.
1085 * Call this function before using any other GTK+ functions in your GUI
1086 * applications. It will initialize everything needed to operate the
1087 * toolkit and parses some standard command line options. @argc and
1088 * @argv are adjusted accordingly so your own code will
1089 * never see those standard arguments.
1091 * Note that there are some alternative ways to initialize GTK+:
1092 * if you are calling gtk_parse_args(), gtk_init_check(),
1093 * gtk_init_with_args() or g_option_context_parse() with
1094 * the option group returned by gtk_get_option_group(), you
1095 * <emphasis>don't</emphasis> have to call gtk_init().
1098 * This function will terminate your program if it was unable to initialize
1099 * the GUI for some reason. If you want your program to fall back to a
1100 * textual interface you want to call gtk_init_check() instead.
1104 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1105 * during initialization, to ignore SIGPIPE signals, since these are
1106 * almost never wanted in graphical applications. If you do need to
1107 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1108 * but notice that other libraries (e.g. libdbus or gvfs) might do
1113 gtk_init (int *argc, char ***argv)
1115 if (!gtk_init_check (argc, argv))
1117 const char *display_name_arg = gdk_get_display_arg_name ();
1118 if (display_name_arg == NULL)
1119 display_name_arg = getenv("DISPLAY");
1120 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1125 #ifdef G_PLATFORM_WIN32
1128 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1130 if (sizeof_GtkWindow != sizeof (GtkWindow))
1131 g_error ("Incompatible build!\n"
1132 "The code using GTK+ thinks GtkWindow is of different\n"
1133 "size than it actually is in this build of GTK+.\n"
1134 "On Windows, this probably means that you have compiled\n"
1135 "your code with gcc without the -mms-bitfields switch,\n"
1136 "or that you are using an unsupported compiler.");
1139 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1140 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1141 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1142 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1143 * -fnative-struct still matters. GtkBox is one such.
1146 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1148 if (sizeof_GtkBox != sizeof (GtkBox))
1149 g_error ("Incompatible build!\n"
1150 "The code using GTK+ thinks GtkBox is of different\n"
1151 "size than it actually is in this build of GTK+.\n"
1152 "On Windows, this probably means that you have compiled\n"
1153 "your code with gcc without the -mms-bitfields switch,\n"
1154 "or that you are using an unsupported compiler.");
1157 /* These two functions might get more checks added later, thus pass
1158 * in the number of extra args.
1161 gtk_init_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 gtk_init (argc, argv);
1170 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1172 check_sizeof_GtkWindow (sizeof_GtkWindow);
1173 if (num_checks >= 2)
1174 check_sizeof_GtkBox (sizeof_GtkBox);
1175 return gtk_init_check (argc, argv);
1183 * Initializes internationalization support for GTK+. gtk_init()
1184 * automatically does this, so there is typically no point
1185 * in calling this function.
1187 * If you are calling this function because you changed the locale
1188 * after GTK+ is was initialized, then calling this function
1189 * may help a bit. (Note, however, that changing the locale
1190 * after GTK+ is initialized may produce inconsistent results and
1191 * is not really supported.)
1193 * In detail - sets the current locale according to the
1194 * program environment. This is the same as calling the C library function
1195 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1196 * locale specific setup of the windowing system used by GDK.
1198 * Returns: a string corresponding to the locale set, typically in the
1199 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1200 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1201 * result of the setlocale(); it is also used on other machines, such as
1202 * Windows, where the C library returns a different result. The string is
1203 * owned by GTK+ and should not be modified or freed.
1206 gtk_set_locale (void)
1208 return gdk_set_locale ();
1212 * _gtk_get_lc_ctype:
1214 * Return the Unix-style locale string for the language currently in
1215 * effect. On Unix systems, this is the return value from
1216 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1217 * affect this through the environment variables LC_ALL, LC_CTYPE or
1218 * LANG (checked in that order). The locale strings typically is in
1219 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1220 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1221 * Swedish as written in Finland or pt_BR for Portuguese as written in
1224 * On Windows, the C library doesn't use any such environment
1225 * variables, and setting them won't affect the behaviour of functions
1226 * like ctime(). The user sets the locale through the Regional Options
1227 * in the Control Panel. The C library (in the setlocale() function)
1228 * does not use country and language codes, but country and language
1229 * names spelled out in English.
1230 * However, this function does check the above environment
1231 * variables, and does return a Unix-style locale string based on
1232 * either said environment variables or the thread's current locale.
1234 * Return value: a dynamically allocated string, free with g_free().
1238 _gtk_get_lc_ctype (void)
1241 /* Somebody might try to set the locale for this process using the
1242 * LANG or LC_ environment variables. The Microsoft C library
1243 * doesn't know anything about them. You set the locale in the
1244 * Control Panel. Setting these env vars won't have any affect on
1245 * locale-dependent C library functions like ctime(). But just for
1246 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1247 * it easier to test GTK and Pango in various default languages, you
1248 * don't have to clickety-click in the Control Panel, you can simply
1249 * start the program with LC_ALL=something on the command line.)
1253 p = getenv ("LC_ALL");
1255 return g_strdup (p);
1257 p = getenv ("LC_CTYPE");
1259 return g_strdup (p);
1261 p = getenv ("LANG");
1263 return g_strdup (p);
1265 return g_win32_getlocale ();
1267 return g_strdup (setlocale (LC_CTYPE, NULL));
1272 * gtk_get_default_language:
1274 * Returns the #PangoLanguage for the default language currently in
1275 * effect. (Note that this can change over the life of an
1276 * application.) The default language is derived from the current
1277 * locale. It determines, for example, whether GTK+ uses the
1278 * right-to-left or left-to-right text direction.
1280 * This function is equivalent to pango_language_get_default(). See
1281 * that function for details.
1283 * Return value: the default language as a #PangoLanguage, must not be
1287 gtk_get_default_language (void)
1289 return pango_language_get_default ();
1297 GtkInitFunction *init;
1300 gtk_main_loop_level++;
1302 loop = g_main_loop_new (NULL, TRUE);
1303 main_loops = g_slist_prepend (main_loops, loop);
1305 tmp_list = functions = init_functions;
1306 init_functions = NULL;
1310 init = tmp_list->data;
1311 tmp_list = tmp_list->next;
1313 (* init->function) (init->data);
1316 g_list_free (functions);
1318 if (g_main_loop_is_running (main_loops->data))
1320 GDK_THREADS_LEAVE ();
1321 g_main_loop_run (loop);
1322 GDK_THREADS_ENTER ();
1328 GList *reinvoke_list = NULL;
1329 GtkQuitFunction *quitf;
1331 while (quit_functions)
1333 quitf = quit_functions->data;
1335 tmp_list = quit_functions;
1336 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1337 g_list_free_1 (tmp_list);
1339 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1340 gtk_quit_invoke_function (quitf))
1342 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1346 gtk_quit_destroy (quitf);
1353 work = g_list_last (reinvoke_list);
1355 quit_functions->prev = work;
1356 work->next = quit_functions;
1357 quit_functions = work;
1363 main_loops = g_slist_remove (main_loops, loop);
1365 g_main_loop_unref (loop);
1367 gtk_main_loop_level--;
1369 if (gtk_main_loop_level == 0)
1371 /* Try storing all clipboard data we have */
1372 _gtk_clipboard_store_all ();
1374 /* Synchronize the recent manager singleton */
1375 _gtk_recent_manager_sync ();
1380 gtk_main_level (void)
1382 return gtk_main_loop_level;
1386 gtk_main_quit (void)
1388 g_return_if_fail (main_loops != NULL);
1390 g_main_loop_quit (main_loops->data);
1394 gtk_events_pending (void)
1398 GDK_THREADS_LEAVE ();
1399 result = g_main_context_pending (NULL);
1400 GDK_THREADS_ENTER ();
1406 gtk_main_iteration (void)
1408 GDK_THREADS_LEAVE ();
1409 g_main_context_iteration (NULL, TRUE);
1410 GDK_THREADS_ENTER ();
1413 return !g_main_loop_is_running (main_loops->data);
1419 gtk_main_iteration_do (gboolean blocking)
1421 GDK_THREADS_LEAVE ();
1422 g_main_context_iteration (NULL, blocking);
1423 GDK_THREADS_ENTER ();
1426 return !g_main_loop_is_running (main_loops->data);
1431 /* private libgtk to libgdk interfaces
1433 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1435 GdkWindow **grab_window,
1436 gboolean *owner_events);
1439 rewrite_events_translate (GdkWindow *old_window,
1440 GdkWindow *new_window,
1444 gint old_origin_x, old_origin_y;
1445 gint new_origin_x, new_origin_y;
1447 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1448 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1450 *x += old_origin_x - new_origin_x;
1451 *y += old_origin_y - new_origin_y;
1455 rewrite_event_for_window (GdkEvent *event,
1456 GdkWindow *new_window)
1458 event = gdk_event_copy (event);
1460 switch (event->type)
1463 rewrite_events_translate (event->any.window,
1465 &event->scroll.x, &event->scroll.y);
1467 case GDK_BUTTON_PRESS:
1468 case GDK_2BUTTON_PRESS:
1469 case GDK_3BUTTON_PRESS:
1470 case GDK_BUTTON_RELEASE:
1471 rewrite_events_translate (event->any.window,
1473 &event->button.x, &event->button.y);
1475 case GDK_MOTION_NOTIFY:
1476 rewrite_events_translate (event->any.window,
1478 &event->motion.x, &event->motion.y);
1481 case GDK_KEY_RELEASE:
1482 case GDK_PROXIMITY_IN:
1483 case GDK_PROXIMITY_OUT:
1490 g_object_unref (event->any.window);
1491 event->any.window = g_object_ref (new_window);
1496 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1497 * then what X11 does is deliver the event normally if it was going to this
1498 * client, otherwise, delivers it in terms of the grab window. This function
1499 * rewrites events to the effect that events going to the same window group
1500 * are delivered normally, otherwise, the event is delivered in terms of the
1504 rewrite_event_for_grabs (GdkEvent *event)
1506 GdkWindow *grab_window;
1507 GtkWidget *event_widget, *grab_widget;
1508 gpointer grab_widget_ptr;
1509 gboolean owner_events;
1510 GdkDisplay *display;
1513 switch (event->type)
1516 case GDK_BUTTON_PRESS:
1517 case GDK_2BUTTON_PRESS:
1518 case GDK_3BUTTON_PRESS:
1519 case GDK_BUTTON_RELEASE:
1520 case GDK_MOTION_NOTIFY:
1521 case GDK_PROXIMITY_IN:
1522 case GDK_PROXIMITY_OUT:
1524 case GDK_KEY_RELEASE:
1525 display = gdk_window_get_display (event->any.window);
1526 device = gdk_event_get_device (event);
1528 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1536 event_widget = gtk_get_event_widget (event);
1537 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1538 grab_widget = grab_widget_ptr;
1541 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1542 return rewrite_event_for_window (event, grab_window);
1548 gtk_main_do_event (GdkEvent *event)
1550 GtkWidget *event_widget;
1551 GtkWidget *grab_widget = NULL;
1552 GtkWindowGroup *window_group;
1553 GdkEvent *rewritten_event = NULL;
1557 if (event->type == GDK_SETTING)
1559 _gtk_settings_handle_event (&event->setting);
1563 if (event->type == GDK_OWNER_CHANGE)
1565 _gtk_clipboard_handle_event (&event->owner_change);
1569 /* Find the widget which got the event. We store the widget
1570 * in the user_data field of GdkWindow's.
1571 * Ignore the event if we don't have a widget for it, except
1572 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1573 * Though this happens rarely, bogus events can occour
1574 * for e.g. destroyed GdkWindows.
1576 event_widget = gtk_get_event_widget (event);
1579 /* To handle selection INCR transactions, we select
1580 * PropertyNotify events on the requestor window and create
1581 * a corresponding (fake) GdkWindow so that events get
1582 * here. There won't be a widget though, so we have to handle
1585 if (event->type == GDK_PROPERTY_NOTIFY)
1586 _gtk_selection_incr_event (event->any.window,
1592 /* If pointer or keyboard grabs are in effect, munge the events
1593 * so that each window group looks like a separate app.
1595 rewritten_event = rewrite_event_for_grabs (event);
1596 if (rewritten_event)
1598 event = rewritten_event;
1599 event_widget = gtk_get_event_widget (event);
1602 window_group = gtk_main_get_window_group (event_widget);
1603 device = gdk_event_get_device (event);
1605 /* check whether there is a (device) grab in effect...
1608 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1610 if (!grab_widget && window_group->grabs)
1611 grab_widget = window_group->grabs->data;
1613 /* If the grab widget is an ancestor of the event widget
1614 * then we send the event to the original event widget.
1615 * This is the key to implementing modality.
1618 (gtk_widget_is_sensitive (event_widget) &&
1619 gtk_widget_is_ancestor (event_widget, grab_widget)))
1620 grab_widget = event_widget;
1622 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1624 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1626 if (rewritten_event)
1627 gdk_event_free (rewritten_event);
1632 /* Push the event onto a stack of current events for
1633 * gtk_current_event_get().
1635 current_events = g_list_prepend (current_events, event);
1637 /* Not all events get sent to the grabbing widget.
1638 * The delete, destroy, expose, focus change and resize
1639 * events still get sent to the event widget because
1640 * 1) these events have no meaning for the grabbing widget
1641 * and 2) redirecting these events to the grabbing widget
1642 * could cause the display to be messed up.
1644 * Drag events are also not redirected, since it isn't
1645 * clear what the semantics of that would be.
1647 switch (event->type)
1653 g_object_ref (event_widget);
1654 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1655 !gtk_widget_event (event_widget, event))
1656 gtk_widget_destroy (event_widget);
1657 g_object_unref (event_widget);
1661 /* Unexpected GDK_DESTROY from the outside, ignore for
1662 * child windows, handle like a GDK_DELETE for toplevels
1664 if (!gtk_widget_get_parent (event_widget))
1666 g_object_ref (event_widget);
1667 if (!gtk_widget_event (event_widget, event) &&
1668 gtk_widget_get_realized (event_widget))
1669 gtk_widget_destroy (event_widget);
1670 g_object_unref (event_widget);
1675 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1677 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1678 gtk_widget_send_expose (event_widget, event);
1679 gdk_window_end_paint (event->any.window);
1683 /* The app may paint with a previously allocated cairo_t,
1684 which will draw directly to the window. We can't catch cairo
1685 drap operatoins to automatically flush the window, thus we
1686 need to explicitly flush any outstanding moves or double
1688 gdk_window_flush (event->any.window);
1689 gtk_widget_send_expose (event_widget, event);
1693 case GDK_PROPERTY_NOTIFY:
1695 case GDK_FOCUS_CHANGE:
1699 case GDK_SELECTION_CLEAR:
1700 case GDK_SELECTION_REQUEST:
1701 case GDK_SELECTION_NOTIFY:
1702 case GDK_CLIENT_EVENT:
1703 case GDK_VISIBILITY_NOTIFY:
1704 case GDK_WINDOW_STATE:
1705 case GDK_GRAB_BROKEN:
1707 gtk_widget_event (event_widget, event);
1711 case GDK_BUTTON_PRESS:
1712 case GDK_2BUTTON_PRESS:
1713 case GDK_3BUTTON_PRESS:
1714 gtk_propagate_event (grab_widget, event);
1718 case GDK_KEY_RELEASE:
1721 if (gtk_invoke_key_snoopers (grab_widget, event))
1724 /* Catch alt press to enable auto-mnemonics;
1725 * menus are handled elsewhere
1727 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1728 !GTK_IS_MENU_SHELL (grab_widget))
1730 gboolean auto_mnemonics;
1732 g_object_get (gtk_widget_get_settings (grab_widget),
1733 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1737 gboolean mnemonics_visible;
1740 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1742 window = gtk_widget_get_toplevel (grab_widget);
1744 if (GTK_IS_WINDOW (window))
1745 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1748 /* else fall through */
1749 case GDK_MOTION_NOTIFY:
1750 case GDK_BUTTON_RELEASE:
1751 case GDK_PROXIMITY_IN:
1752 case GDK_PROXIMITY_OUT:
1753 gtk_propagate_event (grab_widget, event);
1756 case GDK_ENTER_NOTIFY:
1757 _gtk_widget_set_device_window (event_widget,
1758 gdk_event_get_device (event),
1760 if (gtk_widget_is_sensitive (grab_widget))
1761 gtk_widget_event (grab_widget, event);
1764 case GDK_LEAVE_NOTIFY:
1765 _gtk_widget_set_device_window (event_widget,
1766 gdk_event_get_device (event),
1768 if (gtk_widget_is_sensitive (grab_widget))
1769 gtk_widget_event (grab_widget, event);
1772 case GDK_DRAG_STATUS:
1773 case GDK_DROP_FINISHED:
1774 _gtk_drag_source_handle_event (event_widget, event);
1776 case GDK_DRAG_ENTER:
1777 case GDK_DRAG_LEAVE:
1778 case GDK_DRAG_MOTION:
1779 case GDK_DROP_START:
1780 _gtk_drag_dest_handle_event (event_widget, event);
1783 g_assert_not_reached ();
1787 if (event->type == GDK_ENTER_NOTIFY
1788 || event->type == GDK_LEAVE_NOTIFY
1789 || event->type == GDK_BUTTON_PRESS
1790 || event->type == GDK_2BUTTON_PRESS
1791 || event->type == GDK_3BUTTON_PRESS
1792 || event->type == GDK_KEY_PRESS
1793 || event->type == GDK_DRAG_ENTER
1794 || event->type == GDK_GRAB_BROKEN
1795 || event->type == GDK_MOTION_NOTIFY
1796 || event->type == GDK_SCROLL)
1798 _gtk_tooltip_handle_event (event);
1801 tmp_list = current_events;
1802 current_events = g_list_remove_link (current_events, tmp_list);
1803 g_list_free_1 (tmp_list);
1805 if (rewritten_event)
1806 gdk_event_free (rewritten_event);
1821 static GtkWindowGroup *
1822 gtk_main_get_window_group (GtkWidget *widget)
1824 GtkWidget *toplevel = NULL;
1827 toplevel = gtk_widget_get_toplevel (widget);
1829 if (GTK_IS_WINDOW (toplevel))
1830 return gtk_window_get_group (GTK_WINDOW (toplevel));
1832 return gtk_window_get_group (NULL);
1837 GtkWidget *old_grab_widget;
1838 GtkWidget *new_grab_widget;
1839 gboolean was_grabbed;
1840 gboolean is_grabbed;
1842 GList *notified_windows;
1847 synth_crossing_for_grab_notify (GtkWidget *from,
1849 GrabNotifyInfo *info,
1851 GdkCrossingMode mode)
1855 GdkDevice *device = devices->data;
1856 GdkWindow *from_window, *to_window;
1858 /* Do not propagate events more than once to
1859 * the same windows if non-multidevice aware.
1865 from_window = _gtk_widget_get_device_window (from, device);
1868 !gdk_window_get_support_multidevice (from_window) &&
1869 g_list_find (info->notified_windows, from_window))
1877 to_window = _gtk_widget_get_device_window (to, device);
1880 !gdk_window_get_support_multidevice (to_window) &&
1881 g_list_find (info->notified_windows, to_window))
1885 if (from_window || to_window)
1887 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1888 (to_window) ? to : NULL,
1892 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1895 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1898 devices = devices->next;
1903 gtk_grab_notify_foreach (GtkWidget *child,
1906 GrabNotifyInfo *info = data;
1907 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1910 was_grabbed = info->was_grabbed;
1911 is_grabbed = info->is_grabbed;
1913 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1914 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1916 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1917 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1919 g_object_ref (child);
1921 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1922 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1925 _gtk_widget_get_device_window (child, info->device))
1927 /* Device specified and is on widget */
1928 devices = g_list_prepend (NULL, info->device);
1931 devices = _gtk_widget_list_devices (child);
1935 _gtk_widget_set_shadowed (child, TRUE);
1936 if (!was_shadowed && devices &&
1937 gtk_widget_is_sensitive (child))
1938 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1940 GDK_CROSSING_GTK_GRAB);
1944 _gtk_widget_set_shadowed (child, FALSE);
1945 if (was_shadowed && devices &&
1946 gtk_widget_is_sensitive (child))
1947 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1949 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1950 GDK_CROSSING_GTK_UNGRAB);
1953 if (was_shadowed != is_shadowed)
1954 _gtk_widget_grab_notify (child, was_shadowed);
1956 g_object_unref (child);
1957 g_list_free (devices);
1959 info->was_grabbed = was_grabbed;
1960 info->is_grabbed = is_grabbed;
1964 gtk_grab_notify (GtkWindowGroup *group,
1966 GtkWidget *old_grab_widget,
1967 GtkWidget *new_grab_widget,
1971 GrabNotifyInfo info = { 0 };
1973 if (old_grab_widget == new_grab_widget)
1976 info.old_grab_widget = old_grab_widget;
1977 info.new_grab_widget = new_grab_widget;
1978 info.from_grab = from_grab;
1979 info.device = device;
1981 g_object_ref (group);
1983 toplevels = gtk_window_list_toplevels ();
1984 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1988 GtkWindow *toplevel = toplevels->data;
1989 toplevels = g_list_delete_link (toplevels, toplevels);
1991 info.was_grabbed = FALSE;
1992 info.is_grabbed = FALSE;
1994 if (group == gtk_window_get_group (toplevel))
1995 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1996 g_object_unref (toplevel);
1999 g_list_free (info.notified_windows);
2000 g_object_unref (group);
2004 gtk_grab_add (GtkWidget *widget)
2006 GtkWindowGroup *group;
2007 GtkWidget *old_grab_widget;
2009 g_return_if_fail (widget != NULL);
2011 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
2013 _gtk_widget_set_has_grab (widget, TRUE);
2015 group = gtk_main_get_window_group (widget);
2018 old_grab_widget = (GtkWidget *)group->grabs->data;
2020 old_grab_widget = NULL;
2022 g_object_ref (widget);
2023 group->grabs = g_slist_prepend (group->grabs, widget);
2025 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
2030 * gtk_grab_get_current:
2032 * Queries the current grab of the default window group.
2034 * Return value: (transfer none): The widget which currently
2035 * has the grab or %NULL if no grab is active
2038 gtk_grab_get_current (void)
2040 GtkWindowGroup *group;
2042 group = gtk_main_get_window_group (NULL);
2045 return GTK_WIDGET (group->grabs->data);
2050 gtk_grab_remove (GtkWidget *widget)
2052 GtkWindowGroup *group;
2053 GtkWidget *new_grab_widget;
2055 g_return_if_fail (widget != NULL);
2057 if (gtk_widget_has_grab (widget))
2059 _gtk_widget_set_has_grab (widget, FALSE);
2061 group = gtk_main_get_window_group (widget);
2062 group->grabs = g_slist_remove (group->grabs, widget);
2065 new_grab_widget = (GtkWidget *)group->grabs->data;
2067 new_grab_widget = NULL;
2069 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2071 g_object_unref (widget);
2076 * gtk_device_grab_add:
2077 * @widget: a #GtkWidget
2078 * @device: a #GtkDevice to grab on.
2079 * @block_others: %TRUE to prevent other devices to interact with @widget.
2081 * Adds a GTK+ grab on @device, so all the events on @device and its
2082 * associated pointer or keyboard (if any) are delivered to @widget.
2083 * If the @block_others parameter is %TRUE, any other devices will be
2084 * unable to interact with @widget during the grab.
2089 gtk_device_grab_add (GtkWidget *widget,
2091 gboolean block_others)
2093 GtkWindowGroup *group;
2094 GtkWidget *old_grab_widget;
2096 g_return_if_fail (GTK_IS_WIDGET (widget));
2097 g_return_if_fail (GDK_IS_DEVICE (device));
2099 group = gtk_main_get_window_group (widget);
2100 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2102 if (old_grab_widget != widget)
2103 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2105 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2109 * gtk_device_grab_remove:
2110 * @widget: a #GtkWidget
2111 * @device: a #GdkDevice
2113 * Removes a device grab from the given widget. You have to pair calls
2114 * to gtk_device_grab_add() and gtk_device_grab_remove().
2119 gtk_device_grab_remove (GtkWidget *widget,
2122 GtkWindowGroup *group;
2123 GtkWidget *new_grab_widget;
2125 g_return_if_fail (GTK_IS_WIDGET (widget));
2126 g_return_if_fail (GDK_IS_DEVICE (device));
2128 group = gtk_main_get_window_group (widget);
2129 _gtk_window_group_remove_device_grab (group, widget, device);
2130 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2132 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2136 gtk_init_add (GtkFunction function,
2139 GtkInitFunction *init;
2141 init = g_new (GtkInitFunction, 1);
2142 init->function = function;
2145 init_functions = g_list_prepend (init_functions, init);
2149 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2152 GtkKeySnooperData *data;
2153 static guint snooper_id = 1;
2155 g_return_val_if_fail (snooper != NULL, 0);
2157 data = g_new (GtkKeySnooperData, 1);
2158 data->func = snooper;
2159 data->func_data = func_data;
2160 data->id = snooper_id++;
2161 key_snoopers = g_slist_prepend (key_snoopers, data);
2167 gtk_key_snooper_remove (guint snooper_id)
2169 GtkKeySnooperData *data = NULL;
2172 slist = key_snoopers;
2176 if (data->id == snooper_id)
2179 slist = slist->next;
2184 key_snoopers = g_slist_remove (key_snoopers, data);
2190 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2194 gint return_val = FALSE;
2196 slist = key_snoopers;
2197 while (slist && !return_val)
2199 GtkKeySnooperData *data;
2202 slist = slist->next;
2203 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2210 gtk_quit_add_full (guint main_level,
2211 GtkFunction function,
2212 GtkCallbackMarshal marshal,
2214 GDestroyNotify destroy)
2216 static guint quit_id = 1;
2217 GtkQuitFunction *quitf;
2219 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2221 quitf = g_slice_new (GtkQuitFunction);
2223 quitf->id = quit_id++;
2224 quitf->main_level = main_level;
2225 quitf->function = function;
2226 quitf->marshal = marshal;
2228 quitf->destroy = destroy;
2230 quit_functions = g_list_prepend (quit_functions, quitf);
2236 gtk_quit_destroy (GtkQuitFunction *quitf)
2239 quitf->destroy (quitf->data);
2240 g_slice_free (GtkQuitFunction, quitf);
2244 gtk_quit_destructor (GtkWidget **object_p)
2247 gtk_widget_destroy (*object_p);
2254 gtk_quit_add_destroy (guint main_level,
2257 GtkWidget **object_p;
2259 g_return_if_fail (main_level > 0);
2260 g_return_if_fail (GTK_IS_WIDGET (object));
2262 object_p = g_new (GtkWidget*, 1);
2264 g_signal_connect (object,
2266 G_CALLBACK (gtk_widget_destroyed),
2268 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2272 gtk_quit_add (guint main_level,
2273 GtkFunction function,
2276 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2280 gtk_quit_remove (guint id)
2282 GtkQuitFunction *quitf;
2285 tmp_list = quit_functions;
2288 quitf = tmp_list->data;
2290 if (quitf->id == id)
2292 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2293 g_list_free (tmp_list);
2294 gtk_quit_destroy (quitf);
2299 tmp_list = tmp_list->next;
2304 gtk_quit_remove_by_data (gpointer data)
2306 GtkQuitFunction *quitf;
2309 tmp_list = quit_functions;
2312 quitf = tmp_list->data;
2314 if (quitf->data == data)
2316 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2317 g_list_free (tmp_list);
2318 gtk_quit_destroy (quitf);
2323 tmp_list = tmp_list->next;
2328 * gtk_get_current_event:
2330 * Obtains a copy of the event currently being processed by GTK+. For
2331 * example, if you get a "clicked" signal from #GtkButton, the current
2332 * event will be the #GdkEventButton that triggered the "clicked"
2333 * signal. The returned event must be freed with gdk_event_free().
2334 * If there is no current event, the function returns %NULL.
2336 * Return value: a copy of the current event, or %NULL if no current event.
2339 gtk_get_current_event (void)
2342 return gdk_event_copy (current_events->data);
2348 * gtk_get_current_event_time:
2350 * If there is a current event and it has a timestamp, return that
2351 * timestamp, otherwise return %GDK_CURRENT_TIME.
2353 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2356 gtk_get_current_event_time (void)
2359 return gdk_event_get_time (current_events->data);
2361 return GDK_CURRENT_TIME;
2365 * gtk_get_current_event_state:
2366 * @state: a location to store the state of the current event
2368 * If there is a current event and it has a state field, place
2369 * that state field in @state and return %TRUE, otherwise return
2372 * Return value: %TRUE if there was a current event and it had a state field
2375 gtk_get_current_event_state (GdkModifierType *state)
2377 g_return_val_if_fail (state != NULL, FALSE);
2380 return gdk_event_get_state (current_events->data, state);
2389 * gtk_get_current_event_device:
2391 * If there is a current event and it has a device, return that
2392 * device, otherwise return %NULL.
2394 * Returns: (transfer none): a #GdkDevice, or %NULL
2397 gtk_get_current_event_device (void)
2400 return gdk_event_get_device (current_events->data);
2406 * gtk_get_event_widget:
2407 * @event: a #GdkEvent
2409 * If @event is %NULL or the event was not associated with any widget,
2410 * returns %NULL, otherwise returns the widget that received the event
2413 * Return value: (transfer none): the widget that originally
2414 * received @event, or %NULL
2417 gtk_get_event_widget (GdkEvent *event)
2420 gpointer widget_ptr;
2423 if (event && event->any.window &&
2424 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2426 gdk_window_get_user_data (event->any.window, &widget_ptr);
2427 widget = widget_ptr;
2434 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2436 if (!quitf->marshal)
2437 return quitf->function (quitf->data);
2441 gint ret_val = FALSE;
2443 args[0].name = NULL;
2444 args[0].type = G_TYPE_BOOLEAN;
2445 args[0].d.pointer_data = &ret_val;
2446 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2454 * gtk_propagate_event:
2455 * @widget: a #GtkWidget
2458 * Sends an event to a widget, propagating the event to parent widgets
2459 * if the event remains unhandled. Events received by GTK+ from GDK
2460 * normally begin in gtk_main_do_event(). Depending on the type of
2461 * event, existence of modal dialogs, grabs, etc., the event may be
2462 * propagated; if so, this function is used. gtk_propagate_event()
2463 * calls gtk_widget_event() on each widget it decides to send the
2464 * event to. So gtk_widget_event() is the lowest-level function; it
2465 * simply emits the "event" and possibly an event-specific signal on a
2466 * widget. gtk_propagate_event() is a bit higher-level, and
2467 * gtk_main_do_event() is the highest level.
2469 * All that said, you most likely don't want to use any of these
2470 * functions; synthesizing events is rarely needed. Consider asking on
2471 * the mailing list for better ways to achieve your goals. For
2472 * example, use gdk_window_invalidate_rect() or
2473 * gtk_widget_queue_draw() instead of making up expose events.
2477 gtk_propagate_event (GtkWidget *widget,
2482 g_return_if_fail (GTK_IS_WIDGET (widget));
2483 g_return_if_fail (event != NULL);
2485 handled_event = FALSE;
2487 g_object_ref (widget);
2489 if ((event->type == GDK_KEY_PRESS) ||
2490 (event->type == GDK_KEY_RELEASE))
2492 /* Only send key events within Window widgets to the Window
2493 * The Window widget will in turn pass the
2494 * key event on to the currently focused widget
2499 window = gtk_widget_get_toplevel (widget);
2500 if (GTK_IS_WINDOW (window))
2502 /* If there is a grab within the window, give the grab widget
2503 * a first crack at the key event
2505 if (widget != window && gtk_widget_has_grab (widget))
2506 handled_event = gtk_widget_event (widget, event);
2510 window = gtk_widget_get_toplevel (widget);
2511 if (GTK_IS_WINDOW (window))
2513 if (gtk_widget_is_sensitive (window))
2514 gtk_widget_event (window, event);
2518 handled_event = TRUE; /* don't send to widget */
2522 /* Other events get propagated up the widget tree
2523 * so that parents can see the button and motion
2524 * events of the children.
2532 /* Scroll events are special cased here because it
2533 * feels wrong when scrolling a GtkViewport, say,
2534 * to have children of the viewport eat the scroll
2537 if (!gtk_widget_is_sensitive (widget))
2538 handled_event = event->type != GDK_SCROLL;
2540 handled_event = gtk_widget_event (widget, event);
2542 tmp = gtk_widget_get_parent (widget);
2543 g_object_unref (widget);
2547 if (!handled_event && widget)
2548 g_object_ref (widget);
2554 g_object_unref (widget);
2558 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2559 GValue *return_accu,
2560 const GValue *handler_return,
2563 gboolean continue_emission;
2564 gboolean signal_handled;
2566 signal_handled = g_value_get_boolean (handler_return);
2567 g_value_set_boolean (return_accu, signal_handled);
2568 continue_emission = !signal_handled;
2570 return continue_emission;