1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdkconfig.h"
40 #include <sys/types.h> /* For uid_t, gid_t */
50 #include "gtkaccelmap.h"
52 #include "gtkclipboard.h"
54 #include "gtkversion.h"
56 #include "gtkmodules.h"
58 #include "gtkrecentmanager.h"
59 #include "gtkselection.h"
60 #include "gtksettings.h"
61 #include "gtkwidget.h"
62 #include "gtkwindow.h"
63 #include "gtktooltip.h"
66 #include "gdk/gdkkeysyms.h"
68 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
72 static HMODULE gtk_dll;
75 DllMain (HINSTANCE hinstDLL,
81 case DLL_PROCESS_ATTACH:
82 gtk_dll = (HMODULE) hinstDLL;
89 /* These here before inclusion of gtkprivate.h so that the original
90 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
94 _gtk_get_libdir (void)
96 static char *gtk_libdir = NULL;
97 if (gtk_libdir == NULL)
99 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
100 gchar *slash = strrchr (root, '\\');
101 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
102 gtk_libdir = GTK_LIBDIR;
104 gtk_libdir = g_build_filename (root, "lib", NULL);
112 _gtk_get_localedir (void)
114 static char *gtk_localedir = NULL;
115 if (gtk_localedir == NULL)
120 /* GTK_LOCALEDIR ends in either /lib/locale or
121 * /share/locale. Scan for that slash.
123 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
129 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
130 temp = g_build_filename (root, p, NULL);
133 /* gtk_localedir is passed to bindtextdomain() which isn't
136 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
139 return gtk_localedir;
144 #include "gtkprivate.h"
146 /* Private type definitions
148 typedef struct _GtkInitFunction GtkInitFunction;
149 typedef struct _GtkQuitFunction GtkQuitFunction;
150 typedef struct _GtkKeySnooperData GtkKeySnooperData;
152 struct _GtkInitFunction
154 GtkFunction function;
158 struct _GtkQuitFunction
162 GtkCallbackMarshal marshal;
163 GtkFunction function;
165 GDestroyNotify destroy;
168 struct _GtkKeySnooperData
170 GtkKeySnoopFunc func;
175 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
176 static void gtk_quit_destroy (GtkQuitFunction *quitf);
177 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
180 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
182 static guint gtk_main_loop_level = 0;
183 static gint pre_initialized = FALSE;
184 static gint gtk_initialized = FALSE;
185 static GList *current_events = NULL;
187 static GSList *main_loops = NULL; /* stack of currently executing main loops */
189 static GList *init_functions = NULL; /* A list of init functions.
191 static GList *quit_functions = NULL; /* A list of quit functions.
193 static GSList *key_snoopers = NULL;
195 static guint debug_flags = 0; /* Global GTK debug flag */
197 #ifdef G_ENABLE_DEBUG
198 static const GDebugKey gtk_debug_keys[] = {
199 {"misc", GTK_DEBUG_MISC},
200 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
201 {"text", GTK_DEBUG_TEXT},
202 {"tree", GTK_DEBUG_TREE},
203 {"updates", GTK_DEBUG_UPDATES},
204 {"keybindings", GTK_DEBUG_KEYBINDINGS},
205 {"multihead", GTK_DEBUG_MULTIHEAD},
206 {"modules", GTK_DEBUG_MODULES},
207 {"geometry", GTK_DEBUG_GEOMETRY},
208 {"icontheme", GTK_DEBUG_ICONTHEME},
209 {"printing", GTK_DEBUG_PRINTING},
210 {"builder", GTK_DEBUG_BUILDER},
211 {"size-request", GTK_DEBUG_SIZE_REQUEST},
213 #endif /* G_ENABLE_DEBUG */
216 * gtk_get_major_version:
218 * Returns the major version number of the GTK+ library. (e.g. in GTK+ version
221 * This function is in the library, so it represents the GTK+ library
222 * your code is running against. Contrast with the #GTK_MAJOR_VERSION
223 * macro, which represents the major version of the GTK+ headers you
224 * have included when compiling your code.
226 * Returns: the major version number of the GTK+ library.
231 gtk_get_major_version (void)
233 return GTK_MAJOR_VERSION;
237 * gtk_get_minor_version:
239 * Returns the minor version number of the GTK+ library. (e.g. in GTK+ version
242 * This function is in the library, so it represents the GTK+ library
243 * your code is are running against. Contrast with the
244 * #GTK_MINOR_VERSION macro, which represents the minor version of the
245 * GTK+ headers you have included when compiling your code.
247 * Returns: the minor version number of the GTK+ library.
252 gtk_get_minor_version (void)
254 return GTK_MINOR_VERSION;
258 * gtk_get_micro_version:
260 * Returns the micro version number of the GTK+ library. (e.g. in GTK+ version
263 * This function is in the library, so it represents the GTK+ library
264 * your code is are running against. Contrast with the
265 * #GTK_MICRO_VERSION macro, which represents the micro version of the
266 * GTK+ headers you have included when compiling your code.
268 * Returns: the micro version number of the GTK+ library.
273 gtk_get_micro_version (void)
275 return GTK_MICRO_VERSION;
279 * gtk_get_binary_age:
281 * Returns the binary age as passed to
282 * <application>libtool</application> when building the GTK+ library
283 * the process is running against. If
284 * <application>libtool</application> means nothing to you, don't
287 * Returns: the binary age of the GTK+ library.
292 gtk_get_binary_age (void)
294 return GTK_BINARY_AGE;
298 * gtk_get_interface_age:
300 * Returns the interface age as passed to
301 * <application>libtool</application> when building the GTK+ library
302 * the process is running against. If
303 * <application>libtool</application> means nothing to you, don't
306 * Returns: the interface age of the GTK+ library.
311 gtk_get_interface_age (void)
313 return GTK_INTERFACE_AGE;
318 * @required_major: the required major version.
319 * @required_minor: the required minor version.
320 * @required_micro: the required micro version.
322 * Checks that the GTK+ library in use is compatible with the
323 * given version. Generally you would pass in the constants
324 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
325 * as the three arguments to this function; that produces
326 * a check that the library in use is compatible with
327 * the version of GTK+ the application or module was compiled
330 * Compatibility is defined by two things: first the version
331 * of the running library is newer than the version
332 * @required_major.required_minor.@required_micro. Second
333 * the running library must be binary compatible with the
334 * version @required_major.required_minor.@required_micro
335 * (same major version.)
337 * This function is primarily for GTK+ modules; the module
338 * can call this function to check that it wasn't loaded
339 * into an incompatible version of GTK+. However, such a
340 * check isn't completely reliable, since the module may be
341 * linked against an old version of GTK+ and calling the
342 * old version of gtk_check_version(), but still get loaded
343 * into an application using a newer version of GTK+.
345 * Return value: %NULL if the GTK+ library is compatible with the
346 * given version, or a string describing the version mismatch.
347 * The returned string is owned by GTK+ and should not be modified
351 gtk_check_version (guint required_major,
352 guint required_minor,
353 guint required_micro)
355 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
356 gint required_effective_micro = 100 * required_minor + required_micro;
358 if (required_major > GTK_MAJOR_VERSION)
359 return "Gtk+ version too old (major mismatch)";
360 if (required_major < GTK_MAJOR_VERSION)
361 return "Gtk+ version too new (major mismatch)";
362 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
363 return "Gtk+ version too new (micro mismatch)";
364 if (required_effective_micro > gtk_effective_micro)
365 return "Gtk+ version too old (micro mismatch)";
369 /* This checks to see if the process is running suid or sgid
370 * at the current time. If so, we don't allow GTK+ to be initialized.
371 * This is meant to be a mild check - we only error out if we
372 * can prove the programmer is doing something wrong, not if
373 * they could be doing something wrong. For this reason, we
374 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
379 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
381 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
382 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
384 #ifdef HAVE_GETRESUID
385 /* These aren't in the header files, so we prototype them here.
387 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
388 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
390 if (getresuid (&ruid, &euid, &suid) != 0 ||
391 getresgid (&rgid, &egid, &sgid) != 0)
392 #endif /* HAVE_GETRESUID */
394 suid = ruid = getuid ();
395 sgid = rgid = getgid ();
400 if (ruid != euid || ruid != suid ||
401 rgid != egid || rgid != sgid)
403 g_warning ("This process is currently running setuid or setgid.\n"
404 "This is not a supported use of GTK+. You must create a helper\n"
405 "program instead. For further details, see:\n\n"
406 " http://www.gtk.org/setuid.html\n\n"
407 "Refusing to initialize GTK+.");
417 _gtk_get_datadir (void)
419 static char *gtk_datadir = NULL;
420 if (gtk_datadir == NULL)
422 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
423 gtk_datadir = g_build_filename (root, "share", NULL);
431 _gtk_get_sysconfdir (void)
433 static char *gtk_sysconfdir = NULL;
434 if (gtk_sysconfdir == NULL)
436 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
437 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
441 return gtk_sysconfdir;
445 _gtk_get_data_prefix (void)
447 static char *gtk_data_prefix = NULL;
448 if (gtk_data_prefix == NULL)
449 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
451 return gtk_data_prefix;
454 #endif /* G_OS_WIN32 */
456 static gboolean do_setlocale = TRUE;
459 * gtk_disable_setlocale:
461 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
462 * gtk_parse_args() from automatically
463 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
464 * want to use this function if you wanted to set the locale for
465 * your program to something other than the user's locale, or if
466 * you wanted to set different values for different locale categories.
468 * Most programs should not need to call this function.
471 gtk_disable_setlocale (void)
474 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
476 do_setlocale = FALSE;
479 #ifdef G_PLATFORM_WIN32
480 #undef gtk_init_check
483 static GString *gtk_modules_string = NULL;
484 static gboolean g_fatal_warnings = FALSE;
486 #ifdef G_ENABLE_DEBUG
488 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
490 debug_flags |= g_parse_debug_string (value,
492 G_N_ELEMENTS (gtk_debug_keys));
498 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
500 debug_flags &= ~g_parse_debug_string (value,
502 G_N_ELEMENTS (gtk_debug_keys));
506 #endif /* G_ENABLE_DEBUG */
509 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
513 if (gtk_modules_string)
514 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
516 gtk_modules_string = g_string_new (NULL);
518 g_string_append (gtk_modules_string, value);
524 static const GOptionEntry gtk_args[] = {
525 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
526 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
527 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
528 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
529 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
530 #ifdef G_ENABLE_DEBUG
531 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
532 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
533 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
534 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
535 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
536 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
543 static char *iso639_to_check = NULL;
544 static char *iso3166_to_check = NULL;
545 static char *script_to_check = NULL;
546 static gboolean setlocale_called = FALSE;
549 enum_locale_proc (LPTSTR locale)
557 lcid = strtoul (locale, &endptr, 16);
558 if (*endptr == '\0' &&
559 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
560 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
562 if (strcmp (iso639, iso639_to_check) == 0 &&
563 ((iso3166_to_check != NULL &&
564 strcmp (iso3166, iso3166_to_check) == 0) ||
565 (iso3166_to_check == NULL &&
566 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
568 char language[100], country[100];
571 if (script_to_check != NULL)
573 /* If lcid is the "other" script for this language,
574 * return TRUE, i.e. continue looking.
576 if (strcmp (script_to_check, "Latn") == 0)
578 switch (LANGIDFROMLCID (lcid))
580 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
582 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
584 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
586 case MAKELANGID (LANG_SERBIAN, 0x07):
587 /* Serbian in Bosnia and Herzegovina, Cyrillic */
591 else if (strcmp (script_to_check, "Cyrl") == 0)
593 switch (LANGIDFROMLCID (lcid))
595 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
597 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
599 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
601 case MAKELANGID (LANG_SERBIAN, 0x06):
602 /* Serbian in Bosnia and Herzegovina, Latin */
608 SetThreadLocale (lcid);
610 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
611 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
613 strcpy (locale, language);
614 strcat (locale, "_");
615 strcat (locale, country);
617 if (setlocale (LC_ALL, locale) != NULL)
618 setlocale_called = TRUE;
631 setlocale_initialization (void)
633 static gboolean initialized = FALSE;
642 /* If some of the POSIXish environment variables are set, set
643 * the Win32 thread locale correspondingly.
645 char *p = getenv ("LC_ALL");
652 if (strcmp (p, "C") == 0)
653 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
656 /* Check if one of the supported locales match the
657 * environment variable. If so, use that locale.
660 iso3166_to_check = strchr (iso639_to_check, '_');
661 if (iso3166_to_check != NULL)
663 *iso3166_to_check++ = '\0';
665 script_to_check = strchr (iso3166_to_check, '@');
666 if (script_to_check != NULL)
667 *script_to_check++ = '\0';
669 /* Handle special cases. */
671 /* The standard code for Serbia and Montenegro was
672 * "CS", but MSFT uses for some reason "SP". By now
673 * (October 2006), SP has split into two, "RS" and
674 * "ME", but don't bother trying to handle those
675 * yet. Do handle the even older "YU", though.
677 if (strcmp (iso3166_to_check, "CS") == 0 ||
678 strcmp (iso3166_to_check, "YU") == 0)
679 iso3166_to_check = "SP";
683 script_to_check = strchr (iso639_to_check, '@');
684 if (script_to_check != NULL)
685 *script_to_check++ = '\0';
686 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
687 if (strcmp (iso639_to_check, "sr") == 0)
688 iso3166_to_check = "SP";
691 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
695 if (!setlocale_called)
696 setlocale (LC_ALL, "");
698 if (!setlocale (LC_ALL, ""))
699 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
705 check_mixed_deps (void)
710 module = g_module_open (NULL, 0);
712 if (g_module_symbol (module, "gtk_progress_get_type", &func))
714 g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
717 g_module_close (module);
721 do_pre_parse_initialization (int *argc,
724 const gchar *env_string;
729 pre_initialized = TRUE;
733 gdk_pre_parse_libgtk_only ();
734 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
736 #ifdef G_ENABLE_DEBUG
737 env_string = g_getenv ("GTK_DEBUG");
738 if (env_string != NULL)
740 debug_flags = g_parse_debug_string (env_string,
742 G_N_ELEMENTS (gtk_debug_keys));
745 #endif /* G_ENABLE_DEBUG */
747 env_string = g_getenv ("GTK_MODULES");
749 gtk_modules_string = g_string_new (env_string);
753 gettext_initialization (void)
755 setlocale_initialization ();
758 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
759 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
760 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
761 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
762 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
768 do_post_parse_initialization (int *argc,
774 gettext_initialization ();
777 signal (SIGPIPE, SIG_IGN);
780 if (g_fatal_warnings)
782 GLogLevelFlags fatal_mask;
784 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
785 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
786 g_log_set_always_fatal (fatal_mask);
789 if (debug_flags & GTK_DEBUG_UPDATES)
790 gdk_window_set_debug_updates (TRUE);
793 /* Translate to default:RTL if you want your widgets
794 * to be RTL, otherwise translate to default:LTR.
795 * Do *not* translate it to "predefinito:LTR", if it
796 * it isn't default:LTR or default:RTL it will not work
798 char *e = _("default:LTR");
799 if (strcmp (e, "default:RTL")==0)
800 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
801 else if (strcmp (e, "default:LTR"))
802 g_warning ("Whoever translated default:LTR did so wrongly.\n");
805 /* do what the call to gtk_type_init() used to do */
808 _gtk_accel_map_init ();
811 /* Set the 'initialized' flag.
813 gtk_initialized = TRUE;
815 /* load gtk modules */
816 if (gtk_modules_string)
818 _gtk_modules_init (argc, argv, gtk_modules_string->str);
819 g_string_free (gtk_modules_string, TRUE);
823 _gtk_modules_init (argc, argv, NULL);
830 gboolean open_default_display;
834 pre_parse_hook (GOptionContext *context,
839 do_pre_parse_initialization (NULL, NULL);
845 post_parse_hook (GOptionContext *context,
850 OptionGroupInfo *info = data;
853 do_post_parse_initialization (NULL, NULL);
855 if (info->open_default_display)
857 if (gdk_display_open_default_libgtk_only () == NULL)
859 const char *display_name = gdk_get_display_arg_name ();
862 G_OPTION_ERROR_FAILED,
863 _("Cannot open display: %s"),
864 display_name ? display_name : "" );
875 * gtk_get_debug_flags:
877 * Returns the GTK+ debug flags setting.
880 gtk_get_debug_flags (void)
886 * gtk_set_debug_flags:
888 * Sets the GTK+ debug flags.
891 gtk_set_debug_flags (guint flags)
897 * gtk_get_option_group:
898 * @open_default_display: whether to open the default display
899 * when parsing the commandline arguments
901 * Returns a #GOptionGroup for the commandline arguments recognized
902 * by GTK+ and GDK. You should add this group to your #GOptionContext
903 * with g_option_context_add_group(), if you are using
904 * g_option_context_parse() to parse your commandline arguments.
906 * Returns: a #GOptionGroup for the commandline arguments recognized
912 gtk_get_option_group (gboolean open_default_display)
915 OptionGroupInfo *info;
917 gettext_initialization ();
919 info = g_new0 (OptionGroupInfo, 1);
920 info->open_default_display = open_default_display;
922 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
923 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
925 gdk_add_option_entries_libgtk_only (group);
926 g_option_group_add_entries (group, gtk_args);
927 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
933 * gtk_init_with_args:
934 * @argc: a pointer to the number of command line arguments.
935 * @argv: a pointer to the array of command line arguments.
936 * @parameter_string: a string which is displayed in
937 * the first line of <option>--help</option> output, after
938 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
939 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
940 * describing the options of your program
941 * @translation_domain: a translation domain to use for translating
942 * the <option>--help</option> output for the options in @entries
943 * and the @parameter_string with gettext(), or %NULL
944 * @error: a return location for errors
946 * This function does the same work as gtk_init_check().
947 * Additionally, it allows you to add your own commandline options,
948 * and it automatically generates nicely formatted
949 * <option>--help</option> output. Note that your program will
950 * be terminated after writing out the help output.
952 * Returns: %TRUE if the GUI has been successfully initialized,
958 gtk_init_with_args (gint *argc,
960 const gchar *parameter_string,
961 const GOptionEntry *entries,
962 const gchar *translation_domain,
965 GOptionContext *context;
966 GOptionGroup *gtk_group;
970 return gdk_display_open_default_libgtk_only () != NULL;
972 gettext_initialization ();
974 if (!check_setugid ())
977 gtk_group = gtk_get_option_group (TRUE);
979 context = g_option_context_new (parameter_string);
980 g_option_context_add_group (context, gtk_group);
981 g_option_context_set_translation_domain (context, translation_domain);
984 g_option_context_add_main_entries (context, entries, translation_domain);
985 retval = g_option_context_parse (context, argc, argv, error);
987 g_option_context_free (context);
995 * @argc: (inout): a pointer to the number of command line arguments.
996 * @argv: (array) (inout): a pointer to the array of command line arguments.
998 * Parses command line arguments, and initializes global
999 * attributes of GTK+, but does not actually open a connection
1000 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
1002 * Any arguments used by GTK+ or GDK are removed from the array and
1003 * @argc and @argv are updated accordingly.
1005 * You shouldn't call this function explicitely if you are using
1006 * gtk_init(), or gtk_init_check().
1008 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1011 gtk_parse_args (int *argc,
1014 GOptionContext *option_context;
1015 GOptionGroup *gtk_group;
1016 GError *error = NULL;
1018 if (gtk_initialized)
1021 gettext_initialization ();
1023 if (!check_setugid ())
1026 option_context = g_option_context_new (NULL);
1027 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1028 g_option_context_set_help_enabled (option_context, FALSE);
1029 gtk_group = gtk_get_option_group (FALSE);
1030 g_option_context_set_main_group (option_context, gtk_group);
1031 if (!g_option_context_parse (option_context, argc, argv, &error))
1033 g_warning ("%s", error->message);
1034 g_error_free (error);
1037 g_option_context_free (option_context);
1042 #ifdef G_PLATFORM_WIN32
1043 #undef gtk_init_check
1048 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1049 * main() function. Changed if any arguments were handled.
1050 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1051 * Any parameters understood by gtk_init() are stripped before return.
1053 * This function does the same work as gtk_init() with only
1054 * a single change: It does not terminate the program if the GUI can't be
1055 * initialized. Instead it returns %FALSE on failure.
1057 * This way the application can fall back to some other means of communication
1058 * with the user - for example a curses or command line interface.
1060 * Return value: %TRUE if the GUI has been successfully initialized,
1064 gtk_init_check (int *argc,
1067 if (!gtk_parse_args (argc, argv))
1070 return gdk_display_open_default_libgtk_only () != NULL;
1073 #ifdef G_PLATFORM_WIN32
1079 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1080 * main() function. Changed if any arguments were handled.
1081 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1082 * Any parameters understood by gtk_init() are stripped before return.
1084 * Call this function before using any other GTK+ functions in your GUI
1085 * applications. It will initialize everything needed to operate the
1086 * toolkit and parses some standard command line options. @argc and
1087 * @argv are adjusted accordingly so your own code will
1088 * never see those standard arguments.
1090 * Note that there are some alternative ways to initialize GTK+:
1091 * if you are calling gtk_parse_args(), gtk_init_check(),
1092 * gtk_init_with_args() or g_option_context_parse() with
1093 * the option group returned by gtk_get_option_group(), you
1094 * <emphasis>don't</emphasis> have to call gtk_init().
1097 * This function will terminate your program if it was unable to initialize
1098 * the GUI for some reason. If you want your program to fall back to a
1099 * textual interface you want to call gtk_init_check() instead.
1103 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1104 * during initialization, to ignore SIGPIPE signals, since these are
1105 * almost never wanted in graphical applications. If you do need to
1106 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1107 * but notice that other libraries (e.g. libdbus or gvfs) might do
1112 gtk_init (int *argc, char ***argv)
1114 if (!gtk_init_check (argc, argv))
1116 const char *display_name_arg = gdk_get_display_arg_name ();
1117 if (display_name_arg == NULL)
1118 display_name_arg = getenv("DISPLAY");
1119 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1124 #ifdef G_PLATFORM_WIN32
1127 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1129 if (sizeof_GtkWindow != sizeof (GtkWindow))
1130 g_error ("Incompatible build!\n"
1131 "The code using GTK+ thinks GtkWindow is of different\n"
1132 "size than it actually is in this build of GTK+.\n"
1133 "On Windows, this probably means that you have compiled\n"
1134 "your code with gcc without the -mms-bitfields switch,\n"
1135 "or that you are using an unsupported compiler.");
1138 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1139 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1140 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1141 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1142 * -fnative-struct still matters. GtkBox is one such.
1145 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1147 if (sizeof_GtkBox != sizeof (GtkBox))
1148 g_error ("Incompatible build!\n"
1149 "The code using GTK+ thinks GtkBox is of different\n"
1150 "size than it actually is in this build of GTK+.\n"
1151 "On Windows, this probably means that you have compiled\n"
1152 "your code with gcc without the -mms-bitfields switch,\n"
1153 "or that you are using an unsupported compiler.");
1156 /* These two functions might get more checks added later, thus pass
1157 * in the number of extra args.
1160 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1162 check_sizeof_GtkWindow (sizeof_GtkWindow);
1163 if (num_checks >= 2)
1164 check_sizeof_GtkBox (sizeof_GtkBox);
1165 gtk_init (argc, argv);
1169 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1171 check_sizeof_GtkWindow (sizeof_GtkWindow);
1172 if (num_checks >= 2)
1173 check_sizeof_GtkBox (sizeof_GtkBox);
1174 return gtk_init_check (argc, argv);
1182 * Initializes internationalization support for GTK+. gtk_init()
1183 * automatically does this, so there is typically no point
1184 * in calling this function.
1186 * If you are calling this function because you changed the locale
1187 * after GTK+ is was initialized, then calling this function
1188 * may help a bit. (Note, however, that changing the locale
1189 * after GTK+ is initialized may produce inconsistent results and
1190 * is not really supported.)
1192 * In detail - sets the current locale according to the
1193 * program environment. This is the same as calling the C library function
1194 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1195 * locale specific setup of the windowing system used by GDK.
1197 * Returns: a string corresponding to the locale set, typically in the
1198 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1199 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1200 * result of the setlocale(); it is also used on other machines, such as
1201 * Windows, where the C library returns a different result. The string is
1202 * owned by GTK+ and should not be modified or freed.
1205 gtk_set_locale (void)
1207 return gdk_set_locale ();
1211 * _gtk_get_lc_ctype:
1213 * Return the Unix-style locale string for the language currently in
1214 * effect. On Unix systems, this is the return value from
1215 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1216 * affect this through the environment variables LC_ALL, LC_CTYPE or
1217 * LANG (checked in that order). The locale strings typically is in
1218 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1219 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1220 * Swedish as written in Finland or pt_BR for Portuguese as written in
1223 * On Windows, the C library doesn't use any such environment
1224 * variables, and setting them won't affect the behaviour of functions
1225 * like ctime(). The user sets the locale through the Regional Options
1226 * in the Control Panel. The C library (in the setlocale() function)
1227 * does not use country and language codes, but country and language
1228 * names spelled out in English.
1229 * However, this function does check the above environment
1230 * variables, and does return a Unix-style locale string based on
1231 * either said environment variables or the thread's current locale.
1233 * Return value: a dynamically allocated string, free with g_free().
1237 _gtk_get_lc_ctype (void)
1240 /* Somebody might try to set the locale for this process using the
1241 * LANG or LC_ environment variables. The Microsoft C library
1242 * doesn't know anything about them. You set the locale in the
1243 * Control Panel. Setting these env vars won't have any affect on
1244 * locale-dependent C library functions like ctime(). But just for
1245 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1246 * it easier to test GTK and Pango in various default languages, you
1247 * don't have to clickety-click in the Control Panel, you can simply
1248 * start the program with LC_ALL=something on the command line.)
1252 p = getenv ("LC_ALL");
1254 return g_strdup (p);
1256 p = getenv ("LC_CTYPE");
1258 return g_strdup (p);
1260 p = getenv ("LANG");
1262 return g_strdup (p);
1264 return g_win32_getlocale ();
1266 return g_strdup (setlocale (LC_CTYPE, NULL));
1271 * gtk_get_default_language:
1273 * Returns the #PangoLanguage for the default language currently in
1274 * effect. (Note that this can change over the life of an
1275 * application.) The default language is derived from the current
1276 * locale. It determines, for example, whether GTK+ uses the
1277 * right-to-left or left-to-right text direction.
1279 * This function is equivalent to pango_language_get_default(). See
1280 * that function for details.
1282 * Return value: the default language as a #PangoLanguage, must not be
1286 gtk_get_default_language (void)
1288 return pango_language_get_default ();
1296 GtkInitFunction *init;
1299 gtk_main_loop_level++;
1301 loop = g_main_loop_new (NULL, TRUE);
1302 main_loops = g_slist_prepend (main_loops, loop);
1304 tmp_list = functions = init_functions;
1305 init_functions = NULL;
1309 init = tmp_list->data;
1310 tmp_list = tmp_list->next;
1312 (* init->function) (init->data);
1315 g_list_free (functions);
1317 if (g_main_loop_is_running (main_loops->data))
1319 GDK_THREADS_LEAVE ();
1320 g_main_loop_run (loop);
1321 GDK_THREADS_ENTER ();
1327 GList *reinvoke_list = NULL;
1328 GtkQuitFunction *quitf;
1330 while (quit_functions)
1332 quitf = quit_functions->data;
1334 tmp_list = quit_functions;
1335 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1336 g_list_free_1 (tmp_list);
1338 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1339 gtk_quit_invoke_function (quitf))
1341 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1345 gtk_quit_destroy (quitf);
1352 work = g_list_last (reinvoke_list);
1354 quit_functions->prev = work;
1355 work->next = quit_functions;
1356 quit_functions = work;
1362 main_loops = g_slist_remove (main_loops, loop);
1364 g_main_loop_unref (loop);
1366 gtk_main_loop_level--;
1368 if (gtk_main_loop_level == 0)
1370 /* Try storing all clipboard data we have */
1371 _gtk_clipboard_store_all ();
1373 /* Synchronize the recent manager singleton */
1374 _gtk_recent_manager_sync ();
1379 gtk_main_level (void)
1381 return gtk_main_loop_level;
1385 gtk_main_quit (void)
1387 g_return_if_fail (main_loops != NULL);
1389 g_main_loop_quit (main_loops->data);
1393 gtk_events_pending (void)
1397 GDK_THREADS_LEAVE ();
1398 result = g_main_context_pending (NULL);
1399 GDK_THREADS_ENTER ();
1405 gtk_main_iteration (void)
1407 GDK_THREADS_LEAVE ();
1408 g_main_context_iteration (NULL, TRUE);
1409 GDK_THREADS_ENTER ();
1412 return !g_main_loop_is_running (main_loops->data);
1418 gtk_main_iteration_do (gboolean blocking)
1420 GDK_THREADS_LEAVE ();
1421 g_main_context_iteration (NULL, blocking);
1422 GDK_THREADS_ENTER ();
1425 return !g_main_loop_is_running (main_loops->data);
1430 /* private libgtk to libgdk interfaces
1432 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1434 GdkWindow **grab_window,
1435 gboolean *owner_events);
1438 rewrite_events_translate (GdkWindow *old_window,
1439 GdkWindow *new_window,
1443 gint old_origin_x, old_origin_y;
1444 gint new_origin_x, new_origin_y;
1446 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1447 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1449 *x += old_origin_x - new_origin_x;
1450 *y += old_origin_y - new_origin_y;
1454 rewrite_event_for_window (GdkEvent *event,
1455 GdkWindow *new_window)
1457 event = gdk_event_copy (event);
1459 switch (event->type)
1462 rewrite_events_translate (event->any.window,
1464 &event->scroll.x, &event->scroll.y);
1466 case GDK_BUTTON_PRESS:
1467 case GDK_2BUTTON_PRESS:
1468 case GDK_3BUTTON_PRESS:
1469 case GDK_BUTTON_RELEASE:
1470 rewrite_events_translate (event->any.window,
1472 &event->button.x, &event->button.y);
1474 case GDK_MOTION_NOTIFY:
1475 rewrite_events_translate (event->any.window,
1477 &event->motion.x, &event->motion.y);
1480 case GDK_KEY_RELEASE:
1481 case GDK_PROXIMITY_IN:
1482 case GDK_PROXIMITY_OUT:
1489 g_object_unref (event->any.window);
1490 event->any.window = g_object_ref (new_window);
1495 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1496 * then what X11 does is deliver the event normally if it was going to this
1497 * client, otherwise, delivers it in terms of the grab window. This function
1498 * rewrites events to the effect that events going to the same window group
1499 * are delivered normally, otherwise, the event is delivered in terms of the
1503 rewrite_event_for_grabs (GdkEvent *event)
1505 GdkWindow *grab_window;
1506 GtkWidget *event_widget, *grab_widget;
1507 gpointer grab_widget_ptr;
1508 gboolean owner_events;
1509 GdkDisplay *display;
1512 switch (event->type)
1515 case GDK_BUTTON_PRESS:
1516 case GDK_2BUTTON_PRESS:
1517 case GDK_3BUTTON_PRESS:
1518 case GDK_BUTTON_RELEASE:
1519 case GDK_MOTION_NOTIFY:
1520 case GDK_PROXIMITY_IN:
1521 case GDK_PROXIMITY_OUT:
1523 case GDK_KEY_RELEASE:
1524 display = gdk_drawable_get_display (event->any.window);
1525 device = gdk_event_get_device (event);
1527 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1535 event_widget = gtk_get_event_widget (event);
1536 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1537 grab_widget = grab_widget_ptr;
1540 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1541 return rewrite_event_for_window (event, grab_window);
1547 gtk_main_do_event (GdkEvent *event)
1549 GtkWidget *event_widget;
1550 GtkWidget *grab_widget = NULL;
1551 GtkWindowGroup *window_group;
1552 GdkEvent *rewritten_event = NULL;
1556 if (event->type == GDK_SETTING)
1558 _gtk_settings_handle_event (&event->setting);
1562 if (event->type == GDK_OWNER_CHANGE)
1564 _gtk_clipboard_handle_event (&event->owner_change);
1568 /* Find the widget which got the event. We store the widget
1569 * in the user_data field of GdkWindow's.
1570 * Ignore the event if we don't have a widget for it, except
1571 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1572 * Though this happens rarely, bogus events can occour
1573 * for e.g. destroyed GdkWindows.
1575 event_widget = gtk_get_event_widget (event);
1578 /* To handle selection INCR transactions, we select
1579 * PropertyNotify events on the requestor window and create
1580 * a corresponding (fake) GdkWindow so that events get
1581 * here. There won't be a widget though, so we have to handle
1584 if (event->type == GDK_PROPERTY_NOTIFY)
1585 _gtk_selection_incr_event (event->any.window,
1591 /* If pointer or keyboard grabs are in effect, munge the events
1592 * so that each window group looks like a separate app.
1594 rewritten_event = rewrite_event_for_grabs (event);
1595 if (rewritten_event)
1597 event = rewritten_event;
1598 event_widget = gtk_get_event_widget (event);
1601 window_group = gtk_main_get_window_group (event_widget);
1602 device = gdk_event_get_device (event);
1604 /* check whether there is a (device) grab in effect...
1607 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1609 if (!grab_widget && window_group->grabs)
1610 grab_widget = window_group->grabs->data;
1612 /* If the grab widget is an ancestor of the event widget
1613 * then we send the event to the original event widget.
1614 * This is the key to implementing modality.
1617 (gtk_widget_is_sensitive (event_widget) &&
1618 gtk_widget_is_ancestor (event_widget, grab_widget)))
1619 grab_widget = event_widget;
1621 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1623 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1625 if (rewritten_event)
1626 gdk_event_free (rewritten_event);
1631 /* Push the event onto a stack of current events for
1632 * gtk_current_event_get().
1634 current_events = g_list_prepend (current_events, event);
1636 /* Not all events get sent to the grabbing widget.
1637 * The delete, destroy, expose, focus change and resize
1638 * events still get sent to the event widget because
1639 * 1) these events have no meaning for the grabbing widget
1640 * and 2) redirecting these events to the grabbing widget
1641 * could cause the display to be messed up.
1643 * Drag events are also not redirected, since it isn't
1644 * clear what the semantics of that would be.
1646 switch (event->type)
1652 g_object_ref (event_widget);
1653 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1654 !gtk_widget_event (event_widget, event))
1655 gtk_widget_destroy (event_widget);
1656 g_object_unref (event_widget);
1660 /* Unexpected GDK_DESTROY from the outside, ignore for
1661 * child windows, handle like a GDK_DELETE for toplevels
1663 if (!gtk_widget_get_parent (event_widget))
1665 g_object_ref (event_widget);
1666 if (!gtk_widget_event (event_widget, event) &&
1667 gtk_widget_get_realized (event_widget))
1668 gtk_widget_destroy (event_widget);
1669 g_object_unref (event_widget);
1674 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1676 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1677 gtk_widget_send_expose (event_widget, event);
1678 gdk_window_end_paint (event->any.window);
1682 /* The app may paint with a previously allocated cairo_t,
1683 which will draw directly to the window. We can't catch cairo
1684 drap operatoins to automatically flush the window, thus we
1685 need to explicitly flush any outstanding moves or double
1687 gdk_window_flush (event->any.window);
1688 gtk_widget_send_expose (event_widget, event);
1692 case GDK_PROPERTY_NOTIFY:
1694 case GDK_FOCUS_CHANGE:
1698 case GDK_SELECTION_CLEAR:
1699 case GDK_SELECTION_REQUEST:
1700 case GDK_SELECTION_NOTIFY:
1701 case GDK_CLIENT_EVENT:
1702 case GDK_VISIBILITY_NOTIFY:
1703 case GDK_WINDOW_STATE:
1704 case GDK_GRAB_BROKEN:
1706 gtk_widget_event (event_widget, event);
1710 case GDK_BUTTON_PRESS:
1711 case GDK_2BUTTON_PRESS:
1712 case GDK_3BUTTON_PRESS:
1713 gtk_propagate_event (grab_widget, event);
1717 case GDK_KEY_RELEASE:
1720 if (gtk_invoke_key_snoopers (grab_widget, event))
1723 /* Catch alt press to enable auto-mnemonics;
1724 * menus are handled elsewhere
1726 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1727 !GTK_IS_MENU_SHELL (grab_widget))
1729 gboolean auto_mnemonics;
1731 g_object_get (gtk_widget_get_settings (grab_widget),
1732 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1736 gboolean mnemonics_visible;
1739 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1741 window = gtk_widget_get_toplevel (grab_widget);
1743 if (GTK_IS_WINDOW (window))
1744 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1747 /* else fall through */
1748 case GDK_MOTION_NOTIFY:
1749 case GDK_BUTTON_RELEASE:
1750 case GDK_PROXIMITY_IN:
1751 case GDK_PROXIMITY_OUT:
1752 gtk_propagate_event (grab_widget, event);
1755 case GDK_ENTER_NOTIFY:
1756 _gtk_widget_set_device_window (event_widget,
1757 gdk_event_get_device (event),
1759 if (gtk_widget_is_sensitive (grab_widget))
1760 gtk_widget_event (grab_widget, event);
1763 case GDK_LEAVE_NOTIFY:
1764 _gtk_widget_set_device_window (event_widget,
1765 gdk_event_get_device (event),
1767 if (gtk_widget_is_sensitive (grab_widget))
1768 gtk_widget_event (grab_widget, event);
1771 case GDK_DRAG_STATUS:
1772 case GDK_DROP_FINISHED:
1773 _gtk_drag_source_handle_event (event_widget, event);
1775 case GDK_DRAG_ENTER:
1776 case GDK_DRAG_LEAVE:
1777 case GDK_DRAG_MOTION:
1778 case GDK_DROP_START:
1779 _gtk_drag_dest_handle_event (event_widget, event);
1782 g_assert_not_reached ();
1786 if (event->type == GDK_ENTER_NOTIFY
1787 || event->type == GDK_LEAVE_NOTIFY
1788 || event->type == GDK_BUTTON_PRESS
1789 || event->type == GDK_2BUTTON_PRESS
1790 || event->type == GDK_3BUTTON_PRESS
1791 || event->type == GDK_KEY_PRESS
1792 || event->type == GDK_DRAG_ENTER
1793 || event->type == GDK_GRAB_BROKEN
1794 || event->type == GDK_MOTION_NOTIFY
1795 || event->type == GDK_SCROLL)
1797 _gtk_tooltip_handle_event (event);
1800 tmp_list = current_events;
1801 current_events = g_list_remove_link (current_events, tmp_list);
1802 g_list_free_1 (tmp_list);
1804 if (rewritten_event)
1805 gdk_event_free (rewritten_event);
1820 static GtkWindowGroup *
1821 gtk_main_get_window_group (GtkWidget *widget)
1823 GtkWidget *toplevel = NULL;
1826 toplevel = gtk_widget_get_toplevel (widget);
1828 if (GTK_IS_WINDOW (toplevel))
1829 return gtk_window_get_group (GTK_WINDOW (toplevel));
1831 return gtk_window_get_group (NULL);
1836 GtkWidget *old_grab_widget;
1837 GtkWidget *new_grab_widget;
1838 gboolean was_grabbed;
1839 gboolean is_grabbed;
1841 GList *notified_windows;
1846 synth_crossing_for_grab_notify (GtkWidget *from,
1848 GrabNotifyInfo *info,
1850 GdkCrossingMode mode)
1854 GdkDevice *device = devices->data;
1855 GdkWindow *from_window, *to_window;
1857 /* Do not propagate events more than once to
1858 * the same windows if non-multidevice aware.
1864 from_window = _gtk_widget_get_device_window (from, device);
1867 !gdk_window_get_support_multidevice (from_window) &&
1868 g_list_find (info->notified_windows, from_window))
1876 to_window = _gtk_widget_get_device_window (to, device);
1879 !gdk_window_get_support_multidevice (to_window) &&
1880 g_list_find (info->notified_windows, to_window))
1884 if (from_window || to_window)
1886 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1887 (to_window) ? to : NULL,
1891 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1894 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1897 devices = devices->next;
1902 gtk_grab_notify_foreach (GtkWidget *child,
1905 GrabNotifyInfo *info = data;
1906 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1909 was_grabbed = info->was_grabbed;
1910 is_grabbed = info->is_grabbed;
1912 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1913 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1915 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1916 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1918 g_object_ref (child);
1920 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1921 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1924 _gtk_widget_get_device_window (child, info->device))
1926 /* Device specified and is on widget */
1927 devices = g_list_prepend (NULL, info->device);
1930 devices = _gtk_widget_list_devices (child);
1934 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1935 if (!was_shadowed && devices &&
1936 gtk_widget_is_sensitive (child))
1937 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1939 GDK_CROSSING_GTK_GRAB);
1943 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1944 if (was_shadowed && devices &&
1945 gtk_widget_is_sensitive (child))
1946 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1948 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1949 GDK_CROSSING_GTK_UNGRAB);
1952 if (was_shadowed != is_shadowed)
1953 _gtk_widget_grab_notify (child, was_shadowed);
1955 g_object_unref (child);
1956 g_list_free (devices);
1958 info->was_grabbed = was_grabbed;
1959 info->is_grabbed = is_grabbed;
1963 gtk_grab_notify (GtkWindowGroup *group,
1965 GtkWidget *old_grab_widget,
1966 GtkWidget *new_grab_widget,
1970 GrabNotifyInfo info = { 0 };
1972 if (old_grab_widget == new_grab_widget)
1975 info.old_grab_widget = old_grab_widget;
1976 info.new_grab_widget = new_grab_widget;
1977 info.from_grab = from_grab;
1978 info.device = device;
1980 g_object_ref (group);
1982 toplevels = gtk_window_list_toplevels ();
1983 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1987 GtkWindow *toplevel = toplevels->data;
1988 toplevels = g_list_delete_link (toplevels, toplevels);
1990 info.was_grabbed = FALSE;
1991 info.is_grabbed = FALSE;
1993 if (group == gtk_window_get_group (toplevel))
1994 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1995 g_object_unref (toplevel);
1998 g_list_free (info.notified_windows);
1999 g_object_unref (group);
2003 gtk_grab_add (GtkWidget *widget)
2005 GtkWindowGroup *group;
2006 GtkWidget *old_grab_widget;
2008 g_return_if_fail (widget != NULL);
2010 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
2012 _gtk_widget_set_has_grab (widget, TRUE);
2014 group = gtk_main_get_window_group (widget);
2017 old_grab_widget = (GtkWidget *)group->grabs->data;
2019 old_grab_widget = NULL;
2021 g_object_ref (widget);
2022 group->grabs = g_slist_prepend (group->grabs, widget);
2024 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
2029 gtk_grab_get_current (void)
2031 GtkWindowGroup *group;
2033 group = gtk_main_get_window_group (NULL);
2036 return GTK_WIDGET (group->grabs->data);
2041 gtk_grab_remove (GtkWidget *widget)
2043 GtkWindowGroup *group;
2044 GtkWidget *new_grab_widget;
2046 g_return_if_fail (widget != NULL);
2048 if (gtk_widget_has_grab (widget))
2050 _gtk_widget_set_has_grab (widget, FALSE);
2052 group = gtk_main_get_window_group (widget);
2053 group->grabs = g_slist_remove (group->grabs, widget);
2056 new_grab_widget = (GtkWidget *)group->grabs->data;
2058 new_grab_widget = NULL;
2060 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2062 g_object_unref (widget);
2067 * gtk_device_grab_add:
2068 * @widget: a #GtkWidget
2069 * @device: a #GtkDevice to grab on.
2070 * @block_others: %TRUE to prevent other devices to interact with @widget.
2072 * Adds a GTK+ grab on @device, so all the events on @device and its
2073 * associated pointer or keyboard (if any) are delivered to @widget.
2074 * If the @block_others parameter is %TRUE, any other devices will be
2075 * unable to interact with @widget during the grab.
2080 gtk_device_grab_add (GtkWidget *widget,
2082 gboolean block_others)
2084 GtkWindowGroup *group;
2085 GtkWidget *old_grab_widget;
2087 g_return_if_fail (GTK_IS_WIDGET (widget));
2088 g_return_if_fail (GDK_IS_DEVICE (device));
2090 group = gtk_main_get_window_group (widget);
2091 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2093 if (old_grab_widget != widget)
2094 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2096 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2100 * gtk_device_grab_remove:
2101 * @widget: a #GtkWidget
2102 * @device: a #GdkDevice
2104 * Removes a device grab from the given widget. You have to pair calls
2105 * to gtk_device_grab_add() and gtk_device_grab_remove().
2110 gtk_device_grab_remove (GtkWidget *widget,
2113 GtkWindowGroup *group;
2114 GtkWidget *new_grab_widget;
2116 g_return_if_fail (GTK_IS_WIDGET (widget));
2117 g_return_if_fail (GDK_IS_DEVICE (device));
2119 group = gtk_main_get_window_group (widget);
2120 _gtk_window_group_remove_device_grab (group, widget, device);
2121 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2123 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2127 gtk_init_add (GtkFunction function,
2130 GtkInitFunction *init;
2132 init = g_new (GtkInitFunction, 1);
2133 init->function = function;
2136 init_functions = g_list_prepend (init_functions, init);
2140 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2143 GtkKeySnooperData *data;
2144 static guint snooper_id = 1;
2146 g_return_val_if_fail (snooper != NULL, 0);
2148 data = g_new (GtkKeySnooperData, 1);
2149 data->func = snooper;
2150 data->func_data = func_data;
2151 data->id = snooper_id++;
2152 key_snoopers = g_slist_prepend (key_snoopers, data);
2158 gtk_key_snooper_remove (guint snooper_id)
2160 GtkKeySnooperData *data = NULL;
2163 slist = key_snoopers;
2167 if (data->id == snooper_id)
2170 slist = slist->next;
2175 key_snoopers = g_slist_remove (key_snoopers, data);
2181 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2185 gint return_val = FALSE;
2187 slist = key_snoopers;
2188 while (slist && !return_val)
2190 GtkKeySnooperData *data;
2193 slist = slist->next;
2194 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2201 gtk_quit_add_full (guint main_level,
2202 GtkFunction function,
2203 GtkCallbackMarshal marshal,
2205 GDestroyNotify destroy)
2207 static guint quit_id = 1;
2208 GtkQuitFunction *quitf;
2210 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2212 quitf = g_slice_new (GtkQuitFunction);
2214 quitf->id = quit_id++;
2215 quitf->main_level = main_level;
2216 quitf->function = function;
2217 quitf->marshal = marshal;
2219 quitf->destroy = destroy;
2221 quit_functions = g_list_prepend (quit_functions, quitf);
2227 gtk_quit_destroy (GtkQuitFunction *quitf)
2230 quitf->destroy (quitf->data);
2231 g_slice_free (GtkQuitFunction, quitf);
2235 gtk_quit_destructor (GtkObject **object_p)
2238 gtk_object_destroy (*object_p);
2245 gtk_quit_add_destroy (guint main_level,
2248 GtkObject **object_p;
2250 g_return_if_fail (main_level > 0);
2251 g_return_if_fail (GTK_IS_OBJECT (object));
2253 object_p = g_new (GtkObject*, 1);
2255 g_signal_connect (object,
2257 G_CALLBACK (gtk_widget_destroyed),
2259 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2263 gtk_quit_add (guint main_level,
2264 GtkFunction function,
2267 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2271 gtk_quit_remove (guint id)
2273 GtkQuitFunction *quitf;
2276 tmp_list = quit_functions;
2279 quitf = tmp_list->data;
2281 if (quitf->id == id)
2283 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2284 g_list_free (tmp_list);
2285 gtk_quit_destroy (quitf);
2290 tmp_list = tmp_list->next;
2295 gtk_quit_remove_by_data (gpointer data)
2297 GtkQuitFunction *quitf;
2300 tmp_list = quit_functions;
2303 quitf = tmp_list->data;
2305 if (quitf->data == data)
2307 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2308 g_list_free (tmp_list);
2309 gtk_quit_destroy (quitf);
2314 tmp_list = tmp_list->next;
2319 * gtk_get_current_event:
2321 * Obtains a copy of the event currently being processed by GTK+. For
2322 * example, if you get a "clicked" signal from #GtkButton, the current
2323 * event will be the #GdkEventButton that triggered the "clicked"
2324 * signal. The returned event must be freed with gdk_event_free().
2325 * If there is no current event, the function returns %NULL.
2327 * Return value: a copy of the current event, or %NULL if no current event.
2330 gtk_get_current_event (void)
2333 return gdk_event_copy (current_events->data);
2339 * gtk_get_current_event_time:
2341 * If there is a current event and it has a timestamp, return that
2342 * timestamp, otherwise return %GDK_CURRENT_TIME.
2344 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2347 gtk_get_current_event_time (void)
2350 return gdk_event_get_time (current_events->data);
2352 return GDK_CURRENT_TIME;
2356 * gtk_get_current_event_state:
2357 * @state: a location to store the state of the current event
2359 * If there is a current event and it has a state field, place
2360 * that state field in @state and return %TRUE, otherwise return
2363 * Return value: %TRUE if there was a current event and it had a state field
2366 gtk_get_current_event_state (GdkModifierType *state)
2368 g_return_val_if_fail (state != NULL, FALSE);
2371 return gdk_event_get_state (current_events->data, state);
2380 * gtk_get_current_event_device:
2382 * If there is a current event and it has a device, return that
2383 * device, otherwise return %NULL.
2385 * Returns: a #GdkDevice, or %NULL
2388 gtk_get_current_event_device (void)
2391 return gdk_event_get_device (current_events->data);
2397 * gtk_get_event_widget:
2398 * @event: a #GdkEvent
2400 * If @event is %NULL or the event was not associated with any widget,
2401 * returns %NULL, otherwise returns the widget that received the event
2404 * Return value: the widget that originally received @event, or %NULL
2407 gtk_get_event_widget (GdkEvent *event)
2410 gpointer widget_ptr;
2413 if (event && event->any.window &&
2414 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2416 gdk_window_get_user_data (event->any.window, &widget_ptr);
2417 widget = widget_ptr;
2424 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2426 if (!quitf->marshal)
2427 return quitf->function (quitf->data);
2431 gint ret_val = FALSE;
2433 args[0].name = NULL;
2434 args[0].type = G_TYPE_BOOLEAN;
2435 args[0].d.pointer_data = &ret_val;
2436 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2444 * gtk_propagate_event:
2445 * @widget: a #GtkWidget
2448 * Sends an event to a widget, propagating the event to parent widgets
2449 * if the event remains unhandled. Events received by GTK+ from GDK
2450 * normally begin in gtk_main_do_event(). Depending on the type of
2451 * event, existence of modal dialogs, grabs, etc., the event may be
2452 * propagated; if so, this function is used. gtk_propagate_event()
2453 * calls gtk_widget_event() on each widget it decides to send the
2454 * event to. So gtk_widget_event() is the lowest-level function; it
2455 * simply emits the "event" and possibly an event-specific signal on a
2456 * widget. gtk_propagate_event() is a bit higher-level, and
2457 * gtk_main_do_event() is the highest level.
2459 * All that said, you most likely don't want to use any of these
2460 * functions; synthesizing events is rarely needed. Consider asking on
2461 * the mailing list for better ways to achieve your goals. For
2462 * example, use gdk_window_invalidate_rect() or
2463 * gtk_widget_queue_draw() instead of making up expose events.
2467 gtk_propagate_event (GtkWidget *widget,
2472 g_return_if_fail (GTK_IS_WIDGET (widget));
2473 g_return_if_fail (event != NULL);
2475 handled_event = FALSE;
2477 g_object_ref (widget);
2479 if ((event->type == GDK_KEY_PRESS) ||
2480 (event->type == GDK_KEY_RELEASE))
2482 /* Only send key events within Window widgets to the Window
2483 * The Window widget will in turn pass the
2484 * key event on to the currently focused widget
2489 window = gtk_widget_get_toplevel (widget);
2490 if (GTK_IS_WINDOW (window))
2492 /* If there is a grab within the window, give the grab widget
2493 * a first crack at the key event
2495 if (widget != window && gtk_widget_has_grab (widget))
2496 handled_event = gtk_widget_event (widget, event);
2500 window = gtk_widget_get_toplevel (widget);
2501 if (GTK_IS_WINDOW (window))
2503 if (gtk_widget_is_sensitive (window))
2504 gtk_widget_event (window, event);
2508 handled_event = TRUE; /* don't send to widget */
2512 /* Other events get propagated up the widget tree
2513 * so that parents can see the button and motion
2514 * events of the children.
2522 /* Scroll events are special cased here because it
2523 * feels wrong when scrolling a GtkViewport, say,
2524 * to have children of the viewport eat the scroll
2527 if (!gtk_widget_is_sensitive (widget))
2528 handled_event = event->type != GDK_SCROLL;
2530 handled_event = gtk_widget_event (widget, event);
2532 tmp = gtk_widget_get_parent (widget);
2533 g_object_unref (widget);
2537 if (!handled_event && widget)
2538 g_object_ref (widget);
2544 g_object_unref (widget);
2548 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2549 GValue *return_accu,
2550 const GValue *handler_return,
2553 gboolean continue_emission;
2554 gboolean signal_handled;
2556 signal_handled = g_value_get_boolean (handler_return);
2557 g_value_set_boolean (return_accu, signal_handled);
2558 continue_emission = !signal_handled;
2560 return continue_emission;