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"
67 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
71 static HMODULE gtk_dll;
74 DllMain (HINSTANCE hinstDLL,
80 case DLL_PROCESS_ATTACH:
81 gtk_dll = (HMODULE) hinstDLL;
88 /* These here before inclusion of gtkprivate.h so that the original
89 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
93 _gtk_get_libdir (void)
95 static char *gtk_libdir = NULL;
96 if (gtk_libdir == NULL)
98 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
99 gchar *slash = strrchr (root, '\\');
100 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
101 gtk_libdir = GTK_LIBDIR;
103 gtk_libdir = g_build_filename (root, "lib", NULL);
111 _gtk_get_localedir (void)
113 static char *gtk_localedir = NULL;
114 if (gtk_localedir == NULL)
119 /* GTK_LOCALEDIR ends in either /lib/locale or
120 * /share/locale. Scan for that slash.
122 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
128 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
129 temp = g_build_filename (root, p, NULL);
132 /* gtk_localedir is passed to bindtextdomain() which isn't
135 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
138 return gtk_localedir;
143 #include "gtkprivate.h"
145 /* Private type definitions
147 typedef struct _GtkInitFunction GtkInitFunction;
148 typedef struct _GtkQuitFunction GtkQuitFunction;
149 typedef struct _GtkClosure GtkClosure;
150 typedef struct _GtkKeySnooperData GtkKeySnooperData;
152 struct _GtkInitFunction
154 GtkFunction function;
158 struct _GtkQuitFunction
162 GtkCallbackMarshal marshal;
163 GtkFunction function;
165 GDestroyNotify destroy;
170 GtkCallbackMarshal marshal;
172 GDestroyNotify destroy;
175 struct _GtkKeySnooperData
177 GtkKeySnoopFunc func;
182 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
183 static void gtk_quit_destroy (GtkQuitFunction *quitf);
184 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
187 static void gtk_destroy_closure (gpointer data);
188 static gboolean gtk_invoke_idle_timeout (gpointer data);
189 static void gtk_invoke_input (gpointer data,
191 GdkInputCondition condition);
194 static void gtk_error (gchar *str);
195 static void gtk_warning (gchar *str);
196 static void gtk_message (gchar *str);
197 static void gtk_print (gchar *str);
200 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
202 const guint gtk_major_version = GTK_MAJOR_VERSION;
203 const guint gtk_minor_version = GTK_MINOR_VERSION;
204 const guint gtk_micro_version = GTK_MICRO_VERSION;
205 const guint gtk_binary_age = GTK_BINARY_AGE;
206 const guint gtk_interface_age = GTK_INTERFACE_AGE;
208 static guint gtk_main_loop_level = 0;
209 static gint pre_initialized = FALSE;
210 static gint gtk_initialized = FALSE;
211 static GList *current_events = NULL;
213 static GSList *main_loops = NULL; /* stack of currently executing main loops */
215 static GList *init_functions = NULL; /* A list of init functions.
217 static GList *quit_functions = NULL; /* A list of quit functions.
219 static GSList *key_snoopers = NULL;
221 guint gtk_debug_flags = 0; /* Global GTK debug flag */
223 #ifdef G_ENABLE_DEBUG
224 static const GDebugKey gtk_debug_keys[] = {
225 {"misc", GTK_DEBUG_MISC},
226 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
227 {"text", GTK_DEBUG_TEXT},
228 {"tree", GTK_DEBUG_TREE},
229 {"updates", GTK_DEBUG_UPDATES},
230 {"keybindings", GTK_DEBUG_KEYBINDINGS},
231 {"multihead", GTK_DEBUG_MULTIHEAD},
232 {"modules", GTK_DEBUG_MODULES},
233 {"geometry", GTK_DEBUG_GEOMETRY},
234 {"icontheme", GTK_DEBUG_ICONTHEME},
235 {"printing", GTK_DEBUG_PRINTING},
236 {"builder", GTK_DEBUG_BUILDER}
238 #endif /* G_ENABLE_DEBUG */
242 * @required_major: the required major version.
243 * @required_minor: the required minor version.
244 * @required_micro: the required micro version.
246 * Checks that the GTK+ library in use is compatible with the
247 * given version. Generally you would pass in the constants
248 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
249 * as the three arguments to this function; that produces
250 * a check that the library in use is compatible with
251 * the version of GTK+ the application or module was compiled
254 * Compatibility is defined by two things: first the version
255 * of the running library is newer than the version
256 * @required_major.required_minor.@required_micro. Second
257 * the running library must be binary compatible with the
258 * version @required_major.required_minor.@required_micro
259 * (same major version.)
261 * This function is primarily for GTK+ modules; the module
262 * can call this function to check that it wasn't loaded
263 * into an incompatible version of GTK+. However, such a
264 * a check isn't completely reliable, since the module may be
265 * linked against an old version of GTK+ and calling the
266 * old version of gtk_check_version(), but still get loaded
267 * into an application using a newer version of GTK+.
269 * Return value: %NULL if the GTK+ library is compatible with the
270 * given version, or a string describing the version mismatch.
271 * The returned string is owned by GTK+ and should not be modified
275 gtk_check_version (guint required_major,
276 guint required_minor,
277 guint required_micro)
279 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
280 gint required_effective_micro = 100 * required_minor + required_micro;
282 if (required_major > GTK_MAJOR_VERSION)
283 return "Gtk+ version too old (major mismatch)";
284 if (required_major < GTK_MAJOR_VERSION)
285 return "Gtk+ version too new (major mismatch)";
286 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
287 return "Gtk+ version too new (micro mismatch)";
288 if (required_effective_micro > gtk_effective_micro)
289 return "Gtk+ version too old (micro mismatch)";
293 /* This checks to see if the process is running suid or sgid
294 * at the current time. If so, we don't allow GTK+ to be initialized.
295 * This is meant to be a mild check - we only error out if we
296 * can prove the programmer is doing something wrong, not if
297 * they could be doing something wrong. For this reason, we
298 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
303 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
305 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
306 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
308 #ifdef HAVE_GETRESUID
309 /* These aren't in the header files, so we prototype them here.
311 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
312 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
314 if (getresuid (&ruid, &euid, &suid) != 0 ||
315 getresgid (&rgid, &egid, &sgid) != 0)
316 #endif /* HAVE_GETRESUID */
318 suid = ruid = getuid ();
319 sgid = rgid = getgid ();
324 if (ruid != euid || ruid != suid ||
325 rgid != egid || rgid != sgid)
327 g_warning ("This process is currently running setuid or setgid.\n"
328 "This is not a supported use of GTK+. You must create a helper\n"
329 "program instead. For further details, see:\n\n"
330 " http://www.gtk.org/setuid.html\n\n"
331 "Refusing to initialize GTK+.");
341 _gtk_get_datadir (void)
343 static char *gtk_datadir = NULL;
344 if (gtk_datadir == NULL)
346 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
347 gtk_datadir = g_build_filename (root, "share", NULL);
355 _gtk_get_sysconfdir (void)
357 static char *gtk_sysconfdir = NULL;
358 if (gtk_sysconfdir == NULL)
360 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
361 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
365 return gtk_sysconfdir;
369 _gtk_get_data_prefix (void)
371 static char *gtk_data_prefix = NULL;
372 if (gtk_data_prefix == NULL)
373 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
375 return gtk_data_prefix;
378 #endif /* G_OS_WIN32 */
380 static gboolean do_setlocale = TRUE;
383 * gtk_disable_setlocale:
385 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
386 * gtk_parse_args() from automatically
387 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
388 * want to use this function if you wanted to set the locale for
389 * your program to something other than the user's locale, or if
390 * you wanted to set different values for different locale categories.
392 * Most programs should not need to call this function.
395 gtk_disable_setlocale (void)
398 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
400 do_setlocale = FALSE;
403 #ifdef G_PLATFORM_WIN32
404 #undef gtk_init_check
407 static GString *gtk_modules_string = NULL;
408 static gboolean g_fatal_warnings = FALSE;
410 #ifdef G_ENABLE_DEBUG
412 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
414 gtk_debug_flags |= g_parse_debug_string (value,
416 G_N_ELEMENTS (gtk_debug_keys));
422 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
424 gtk_debug_flags &= ~g_parse_debug_string (value,
426 G_N_ELEMENTS (gtk_debug_keys));
430 #endif /* G_ENABLE_DEBUG */
433 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
437 if (gtk_modules_string)
438 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
440 gtk_modules_string = g_string_new (NULL);
442 g_string_append (gtk_modules_string, value);
448 static const GOptionEntry gtk_args[] = {
449 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
450 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
451 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
452 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
453 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
454 #ifdef G_ENABLE_DEBUG
455 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
456 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
457 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
458 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
459 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
460 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
467 static char *iso639_to_check = NULL;
468 static char *iso3166_to_check = NULL;
469 static char *script_to_check = NULL;
470 static gboolean setlocale_called = FALSE;
473 enum_locale_proc (LPTSTR locale)
481 lcid = strtoul (locale, &endptr, 16);
482 if (*endptr == '\0' &&
483 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
484 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
486 if (strcmp (iso639, iso639_to_check) == 0 &&
487 ((iso3166_to_check != NULL &&
488 strcmp (iso3166, iso3166_to_check) == 0) ||
489 (iso3166_to_check == NULL &&
490 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
492 char language[100], country[100];
495 if (script_to_check != NULL)
497 /* If lcid is the "other" script for this language,
498 * return TRUE, i.e. continue looking.
500 if (strcmp (script_to_check, "Latn") == 0)
502 switch (LANGIDFROMLCID (lcid))
504 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
506 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
508 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
510 case MAKELANGID (LANG_SERBIAN, 0x07):
511 /* Serbian in Bosnia and Herzegovina, Cyrillic */
515 else if (strcmp (script_to_check, "Cyrl") == 0)
517 switch (LANGIDFROMLCID (lcid))
519 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
521 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
523 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
525 case MAKELANGID (LANG_SERBIAN, 0x06):
526 /* Serbian in Bosnia and Herzegovina, Latin */
532 SetThreadLocale (lcid);
534 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
535 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
537 strcpy (locale, language);
538 strcat (locale, "_");
539 strcat (locale, country);
541 if (setlocale (LC_ALL, locale) != NULL)
542 setlocale_called = TRUE;
555 setlocale_initialization (void)
557 static gboolean initialized = FALSE;
566 /* If some of the POSIXish environment variables are set, set
567 * the Win32 thread locale correspondingly.
569 char *p = getenv ("LC_ALL");
576 if (strcmp (p, "C") == 0)
577 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
580 /* Check if one of the supported locales match the
581 * environment variable. If so, use that locale.
584 iso3166_to_check = strchr (iso639_to_check, '_');
585 if (iso3166_to_check != NULL)
587 *iso3166_to_check++ = '\0';
589 script_to_check = strchr (iso3166_to_check, '@');
590 if (script_to_check != NULL)
591 *script_to_check++ = '\0';
593 /* Handle special cases. */
595 /* The standard code for Serbia and Montenegro was
596 * "CS", but MSFT uses for some reason "SP". By now
597 * (October 2006), SP has split into two, "RS" and
598 * "ME", but don't bother trying to handle those
599 * yet. Do handle the even older "YU", though.
601 if (strcmp (iso3166_to_check, "CS") == 0 ||
602 strcmp (iso3166_to_check, "YU") == 0)
603 iso3166_to_check = "SP";
607 script_to_check = strchr (iso639_to_check, '@');
608 if (script_to_check != NULL)
609 *script_to_check++ = '\0';
610 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
611 if (strcmp (iso639_to_check, "sr") == 0)
612 iso3166_to_check = "SP";
615 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
619 if (!setlocale_called)
620 setlocale (LC_ALL, "");
622 if (!setlocale (LC_ALL, ""))
623 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
629 do_pre_parse_initialization (int *argc,
632 const gchar *env_string;
635 g_set_error_handler (gtk_error);
636 g_set_warning_handler (gtk_warning);
637 g_set_message_handler (gtk_message);
638 g_set_print_handler (gtk_print);
644 pre_initialized = TRUE;
646 gdk_pre_parse_libgtk_only ();
647 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
649 #ifdef G_ENABLE_DEBUG
650 env_string = g_getenv ("GTK_DEBUG");
651 if (env_string != NULL)
653 gtk_debug_flags = g_parse_debug_string (env_string,
655 G_N_ELEMENTS (gtk_debug_keys));
658 #endif /* G_ENABLE_DEBUG */
660 env_string = g_getenv ("GTK_MODULES");
662 gtk_modules_string = g_string_new (env_string);
666 gettext_initialization (void)
668 setlocale_initialization ();
671 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
672 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
673 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
674 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
675 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
681 do_post_parse_initialization (int *argc,
687 gettext_initialization ();
690 signal (SIGPIPE, SIG_IGN);
693 if (g_fatal_warnings)
695 GLogLevelFlags fatal_mask;
697 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
698 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
699 g_log_set_always_fatal (fatal_mask);
702 if (gtk_debug_flags & GTK_DEBUG_UPDATES)
703 gdk_window_set_debug_updates (TRUE);
706 /* Translate to default:RTL if you want your widgets
707 * to be RTL, otherwise translate to default:LTR.
708 * Do *not* translate it to "predefinito:LTR", if it
709 * it isn't default:LTR or default:RTL it will not work
711 char *e = _("default:LTR");
712 if (strcmp (e, "default:RTL")==0)
713 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
714 else if (strcmp (e, "default:LTR"))
715 g_warning ("Whoever translated default:LTR did so wrongly.\n");
718 /* do what the call to gtk_type_init() used to do */
720 gtk_object_get_type ();
722 _gtk_accel_map_init ();
725 /* Set the 'initialized' flag.
727 gtk_initialized = TRUE;
729 /* load gtk modules */
730 if (gtk_modules_string)
732 _gtk_modules_init (argc, argv, gtk_modules_string->str);
733 g_string_free (gtk_modules_string, TRUE);
737 _gtk_modules_init (argc, argv, NULL);
744 gboolean open_default_display;
748 pre_parse_hook (GOptionContext *context,
753 do_pre_parse_initialization (NULL, NULL);
759 post_parse_hook (GOptionContext *context,
764 OptionGroupInfo *info = data;
767 do_post_parse_initialization (NULL, NULL);
769 if (info->open_default_display)
771 if (gdk_display_open_default_libgtk_only () == NULL)
773 const char *display_name = gdk_get_display_arg_name ();
776 G_OPTION_ERROR_FAILED,
777 _("Cannot open display: %s"),
778 display_name ? display_name : "" );
789 * gtk_get_option_group:
790 * @open_default_display: whether to open the default display
791 * when parsing the commandline arguments
793 * Returns a #GOptionGroup for the commandline arguments recognized
794 * by GTK+ and GDK. You should add this group to your #GOptionContext
795 * with g_option_context_add_group(), if you are using
796 * g_option_context_parse() to parse your commandline arguments.
798 * Returns: a #GOptionGroup for the commandline arguments recognized
804 gtk_get_option_group (gboolean open_default_display)
807 OptionGroupInfo *info;
809 gettext_initialization ();
811 info = g_new0 (OptionGroupInfo, 1);
812 info->open_default_display = open_default_display;
814 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
815 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
817 gdk_add_option_entries_libgtk_only (group);
818 g_option_group_add_entries (group, gtk_args);
819 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
825 * gtk_init_with_args:
826 * @argc: a pointer to the number of command line arguments.
827 * @argv: a pointer to the array of command line arguments.
828 * @parameter_string: a string which is displayed in
829 * the first line of <option>--help</option> output, after
830 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
831 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
832 * describing the options of your program
833 * @translation_domain: a translation domain to use for translating
834 * the <option>--help</option> output for the options in @entries
835 * with gettext(), or %NULL
836 * @error: a return location for errors
838 * This function does the same work as gtk_init_check().
839 * Additionally, it allows you to add your own commandline options,
840 * and it automatically generates nicely formatted
841 * <option>--help</option> output. Note that your program will
842 * be terminated after writing out the help output.
844 * Returns: %TRUE if the GUI has been successfully initialized,
850 gtk_init_with_args (int *argc,
852 char *parameter_string,
853 GOptionEntry *entries,
854 char *translation_domain,
857 GOptionContext *context;
858 GOptionGroup *gtk_group;
862 return gdk_display_open_default_libgtk_only () != NULL;
864 gettext_initialization ();
866 if (!check_setugid ())
869 gtk_group = gtk_get_option_group (TRUE);
871 context = g_option_context_new (parameter_string);
872 g_option_context_add_group (context, gtk_group);
875 g_option_context_add_main_entries (context, entries, translation_domain);
876 retval = g_option_context_parse (context, argc, argv, error);
878 g_option_context_free (context);
886 * @argc: a pointer to the number of command line arguments.
887 * @argv: a pointer to the array of command line arguments.
889 * Parses command line arguments, and initializes global
890 * attributes of GTK+, but does not actually open a connection
891 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
893 * Any arguments used by GTK+ or GDK are removed from the array and
894 * @argc and @argv are updated accordingly.
896 * You shouldn't call this function explicitely if you are using
897 * gtk_init(), or gtk_init_check().
899 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
902 gtk_parse_args (int *argc,
905 GOptionContext *option_context;
906 GOptionGroup *gtk_group;
907 GError *error = NULL;
912 gettext_initialization ();
914 if (!check_setugid ())
917 option_context = g_option_context_new (NULL);
918 g_option_context_set_ignore_unknown_options (option_context, TRUE);
919 g_option_context_set_help_enabled (option_context, FALSE);
920 gtk_group = gtk_get_option_group (FALSE);
921 g_option_context_set_main_group (option_context, gtk_group);
922 if (!g_option_context_parse (option_context, argc, argv, &error))
924 g_warning ("%s", error->message);
925 g_error_free (error);
928 g_option_context_free (option_context);
933 #ifdef G_PLATFORM_WIN32
934 #undef gtk_init_check
939 * @argc: Address of the <parameter>argc</parameter> parameter of your
940 * main() function. Changed if any arguments were handled.
941 * @argv: Address of the <parameter>argv</parameter> parameter of main().
942 * Any parameters understood by gtk_init() are stripped before return.
944 * This function does the same work as gtk_init() with only
945 * a single change: It does not terminate the program if the GUI can't be
946 * initialized. Instead it returns %FALSE on failure.
948 * This way the application can fall back to some other means of communication
949 * with the user - for example a curses or command line interface.
951 * Return value: %TRUE if the GUI has been successfully initialized,
955 gtk_init_check (int *argc,
958 if (!gtk_parse_args (argc, argv))
961 return gdk_display_open_default_libgtk_only () != NULL;
964 #ifdef G_PLATFORM_WIN32
970 * @argc: Address of the <parameter>argc</parameter> parameter of your
971 * main() function. Changed if any arguments were handled.
972 * @argv: Address of the <parameter>argv</parameter> parameter of main().
973 * Any parameters understood by gtk_init() are stripped before return.
975 * Call this function before using any other GTK+ functions in your GUI
976 * applications. It will initialize everything needed to operate the
977 * toolkit and parses some standard command line options. @argc and
978 * @argv are adjusted accordingly so your own code will
979 * never see those standard arguments.
981 * Note that there are some alternative ways to initialize GTK+:
982 * if you are calling gtk_parse_args(), gtk_init_check(),
983 * gtk_init_with_args() or g_option_context_parse() with
984 * the option group returned by gtk_get_option_group(), you
985 * <emphasis>don't</emphasis> have to call gtk_init().
988 * This function will terminate your program if it was unable to initialize
989 * the GUI for some reason. If you want your program to fall back to a
990 * textual interface you want to call gtk_init_check() instead.
994 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
995 * during initialization, to ignore SIGPIPE signals, since these are
996 * almost never wanted in graphical applications. If you do need to
997 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
998 * but notice that other libraries (e.g. libdbus or gvfs) might do
1003 gtk_init (int *argc, char ***argv)
1005 if (!gtk_init_check (argc, argv))
1007 const char *display_name_arg = gdk_get_display_arg_name ();
1008 if (display_name_arg == NULL)
1009 display_name_arg = getenv("DISPLAY");
1010 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1015 #ifdef G_PLATFORM_WIN32
1018 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1020 if (sizeof_GtkWindow != sizeof (GtkWindow))
1021 g_error ("Incompatible build!\n"
1022 "The code using GTK+ thinks GtkWindow is of different\n"
1023 "size than it actually is in this build of GTK+.\n"
1024 "On Windows, this probably means that you have compiled\n"
1025 "your code with gcc without the -mms-bitfields switch,\n"
1026 "or that you are using an unsupported compiler.");
1029 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1030 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1031 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1032 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1033 * -fnative-struct still matters. GtkBox is one such.
1036 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1038 if (sizeof_GtkBox != sizeof (GtkBox))
1039 g_error ("Incompatible build!\n"
1040 "The code using GTK+ thinks GtkBox is of different\n"
1041 "size than it actually is in this build of GTK+.\n"
1042 "On Windows, this probably means that you have compiled\n"
1043 "your code with gcc without the -mms-bitfields switch,\n"
1044 "or that you are using an unsupported compiler.");
1047 /* These two functions might get more checks added later, thus pass
1048 * in the number of extra args.
1051 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1053 check_sizeof_GtkWindow (sizeof_GtkWindow);
1054 if (num_checks >= 2)
1055 check_sizeof_GtkBox (sizeof_GtkBox);
1056 gtk_init (argc, argv);
1060 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1062 check_sizeof_GtkWindow (sizeof_GtkWindow);
1063 if (num_checks >= 2)
1064 check_sizeof_GtkBox (sizeof_GtkBox);
1065 return gtk_init_check (argc, argv);
1071 gtk_exit (gint errorcode)
1080 * Initializes internationalization support for GTK+. gtk_init()
1081 * automatically does this, so there is typically no point
1082 * in calling this function.
1084 * If you are calling this function because you changed the locale
1085 * after GTK+ is was initialized, then calling this function
1086 * may help a bit. (Note, however, that changing the locale
1087 * after GTK+ is initialized may produce inconsistent results and
1088 * is not really supported.)
1090 * In detail - sets the current locale according to the
1091 * program environment. This is the same as calling the C library function
1092 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1093 * locale specific setup of the windowing system used by GDK.
1095 * Returns: a string corresponding to the locale set, typically in the
1096 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1097 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1098 * result of the setlocale(); it is also used on other machines, such as
1099 * Windows, where the C library returns a different result. The string is
1100 * owned by GTK+ and should not be modified or freed.
1103 gtk_set_locale (void)
1105 return gdk_set_locale ();
1109 * _gtk_get_lc_ctype:
1111 * Return the Unix-style locale string for the language currently in
1112 * effect. On Unix systems, this is the return value from
1113 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1114 * affect this through the environment variables LC_ALL, LC_CTYPE or
1115 * LANG (checked in that order). The locale strings typically is in
1116 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1117 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1118 * Swedish as written in Finland or pt_BR for Portuguese as written in
1121 * On Windows, the C library doesn't use any such environment
1122 * variables, and setting them won't affect the behaviour of functions
1123 * like ctime(). The user sets the locale through the Regional Options
1124 * in the Control Panel. The C library (in the setlocale() function)
1125 * does not use country and language codes, but country and language
1126 * names spelled out in English.
1127 * However, this function does check the above environment
1128 * variables, and does return a Unix-style locale string based on
1129 * either said environment variables or the thread's current locale.
1131 * Return value: a dynamically allocated string, free with g_free().
1135 _gtk_get_lc_ctype (void)
1138 /* Somebody might try to set the locale for this process using the
1139 * LANG or LC_ environment variables. The Microsoft C library
1140 * doesn't know anything about them. You set the locale in the
1141 * Control Panel. Setting these env vars won't have any affect on
1142 * locale-dependent C library functions like ctime(). But just for
1143 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1144 * it easier to test GTK and Pango in various default languages, you
1145 * don't have to clickety-click in the Control Panel, you can simply
1146 * start the program with LC_ALL=something on the command line.)
1150 p = getenv ("LC_ALL");
1152 return g_strdup (p);
1154 p = getenv ("LC_CTYPE");
1156 return g_strdup (p);
1158 p = getenv ("LANG");
1160 return g_strdup (p);
1162 return g_win32_getlocale ();
1164 return g_strdup (setlocale (LC_CTYPE, NULL));
1169 * gtk_get_default_language:
1171 * Returns the #PangoLanguage for the default language currently in
1172 * effect. (Note that this can change over the life of an
1173 * application.) The default language is derived from the current
1174 * locale. It determines, for example, whether GTK+ uses the
1175 * right-to-left or left-to-right text direction.
1177 * This function is equivalent to pango_language_get_default(). See
1178 * that function for details.
1180 * Return value: the default language as a #PangoLanguage, must not be
1184 gtk_get_default_language (void)
1186 return pango_language_get_default ();
1194 GtkInitFunction *init;
1197 gtk_main_loop_level++;
1199 loop = g_main_loop_new (NULL, TRUE);
1200 main_loops = g_slist_prepend (main_loops, loop);
1202 tmp_list = functions = init_functions;
1203 init_functions = NULL;
1207 init = tmp_list->data;
1208 tmp_list = tmp_list->next;
1210 (* init->function) (init->data);
1213 g_list_free (functions);
1215 if (g_main_loop_is_running (main_loops->data))
1217 GDK_THREADS_LEAVE ();
1218 g_main_loop_run (loop);
1219 GDK_THREADS_ENTER ();
1225 GList *reinvoke_list = NULL;
1226 GtkQuitFunction *quitf;
1228 while (quit_functions)
1230 quitf = quit_functions->data;
1232 tmp_list = quit_functions;
1233 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1234 g_list_free_1 (tmp_list);
1236 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1237 gtk_quit_invoke_function (quitf))
1239 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1243 gtk_quit_destroy (quitf);
1250 work = g_list_last (reinvoke_list);
1252 quit_functions->prev = work;
1253 work->next = quit_functions;
1254 quit_functions = work;
1260 main_loops = g_slist_remove (main_loops, loop);
1262 g_main_loop_unref (loop);
1264 gtk_main_loop_level--;
1266 if (gtk_main_loop_level == 0)
1268 /* Try storing all clipboard data we have */
1269 _gtk_clipboard_store_all ();
1271 /* Synchronize the recent manager singleton */
1272 _gtk_recent_manager_sync ();
1277 gtk_main_level (void)
1279 return gtk_main_loop_level;
1283 gtk_main_quit (void)
1285 g_return_if_fail (main_loops != NULL);
1287 g_main_loop_quit (main_loops->data);
1291 gtk_events_pending (void)
1295 GDK_THREADS_LEAVE ();
1296 result = g_main_context_pending (NULL);
1297 GDK_THREADS_ENTER ();
1303 gtk_main_iteration (void)
1305 GDK_THREADS_LEAVE ();
1306 g_main_context_iteration (NULL, TRUE);
1307 GDK_THREADS_ENTER ();
1310 return !g_main_loop_is_running (main_loops->data);
1316 gtk_main_iteration_do (gboolean blocking)
1318 GDK_THREADS_LEAVE ();
1319 g_main_context_iteration (NULL, blocking);
1320 GDK_THREADS_ENTER ();
1323 return !g_main_loop_is_running (main_loops->data);
1328 /* private libgtk to libgdk interfaces
1330 gboolean gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
1331 GdkWindow **grab_window,
1332 gboolean *owner_events);
1333 gboolean gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1334 GdkWindow **grab_window,
1335 gboolean *owner_events);
1338 rewrite_events_translate (GdkWindow *old_window,
1339 GdkWindow *new_window,
1343 gint old_origin_x, old_origin_y;
1344 gint new_origin_x, new_origin_y;
1346 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1347 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1349 *x += old_origin_x - new_origin_x;
1350 *y += old_origin_y - new_origin_y;
1354 rewrite_event_for_window (GdkEvent *event,
1355 GdkWindow *new_window)
1357 event = gdk_event_copy (event);
1359 switch (event->type)
1362 rewrite_events_translate (event->any.window,
1364 &event->scroll.x, &event->scroll.y);
1366 case GDK_BUTTON_PRESS:
1367 case GDK_2BUTTON_PRESS:
1368 case GDK_3BUTTON_PRESS:
1369 case GDK_BUTTON_RELEASE:
1370 rewrite_events_translate (event->any.window,
1372 &event->button.x, &event->button.y);
1374 case GDK_MOTION_NOTIFY:
1375 rewrite_events_translate (event->any.window,
1377 &event->motion.x, &event->motion.y);
1380 case GDK_KEY_RELEASE:
1381 case GDK_PROXIMITY_IN:
1382 case GDK_PROXIMITY_OUT:
1389 g_object_unref (event->any.window);
1390 event->any.window = g_object_ref (new_window);
1395 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1396 * then what X11 does is deliver the event normally if it was going to this
1397 * client, otherwise, delivers it in terms of the grab window. This function
1398 * rewrites events to the effect that events going to the same window group
1399 * are delivered normally, otherwise, the event is delivered in terms of the
1403 rewrite_event_for_grabs (GdkEvent *event)
1405 GdkWindow *grab_window;
1406 GtkWidget *event_widget, *grab_widget;
1407 gpointer grab_widget_ptr;
1408 gboolean owner_events;
1409 GdkDisplay *display;
1411 switch (event->type)
1414 case GDK_BUTTON_PRESS:
1415 case GDK_2BUTTON_PRESS:
1416 case GDK_3BUTTON_PRESS:
1417 case GDK_BUTTON_RELEASE:
1418 case GDK_MOTION_NOTIFY:
1419 case GDK_PROXIMITY_IN:
1420 case GDK_PROXIMITY_OUT:
1421 display = gdk_drawable_get_display (event->proximity.window);
1422 if (!gdk_pointer_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1428 case GDK_KEY_RELEASE:
1429 display = gdk_drawable_get_display (event->key.window);
1430 if (!gdk_keyboard_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1439 event_widget = gtk_get_event_widget (event);
1440 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1441 grab_widget = grab_widget_ptr;
1444 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1445 return rewrite_event_for_window (event, grab_window);
1451 gtk_main_do_event (GdkEvent *event)
1453 GtkWidget *event_widget;
1454 GtkWidget *grab_widget;
1455 GtkWindowGroup *window_group;
1456 GdkEvent *rewritten_event = NULL;
1459 if (event->type == GDK_SETTING)
1461 _gtk_settings_handle_event (&event->setting);
1465 if (event->type == GDK_OWNER_CHANGE)
1467 _gtk_clipboard_handle_event (&event->owner_change);
1471 /* Find the widget which got the event. We store the widget
1472 * in the user_data field of GdkWindow's.
1473 * Ignore the event if we don't have a widget for it, except
1474 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1475 * Though this happens rarely, bogus events can occour
1476 * for e.g. destroyed GdkWindows.
1478 event_widget = gtk_get_event_widget (event);
1481 /* To handle selection INCR transactions, we select
1482 * PropertyNotify events on the requestor window and create
1483 * a corresponding (fake) GdkWindow so that events get
1484 * here. There won't be a widget though, so we have to handle
1487 if (event->type == GDK_PROPERTY_NOTIFY)
1488 _gtk_selection_incr_event (event->any.window,
1494 /* If pointer or keyboard grabs are in effect, munge the events
1495 * so that each window group looks like a separate app.
1497 rewritten_event = rewrite_event_for_grabs (event);
1498 if (rewritten_event)
1500 event = rewritten_event;
1501 event_widget = gtk_get_event_widget (event);
1504 window_group = gtk_main_get_window_group (event_widget);
1506 /* Push the event onto a stack of current events for
1507 * gtk_current_event_get().
1509 current_events = g_list_prepend (current_events, event);
1511 /* If there is a grab in effect...
1513 if (window_group->grabs)
1515 grab_widget = window_group->grabs->data;
1517 /* If the grab widget is an ancestor of the event widget
1518 * then we send the event to the original event widget.
1519 * This is the key to implementing modality.
1521 if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
1522 gtk_widget_is_ancestor (event_widget, grab_widget))
1523 grab_widget = event_widget;
1527 grab_widget = event_widget;
1530 /* Not all events get sent to the grabbing widget.
1531 * The delete, destroy, expose, focus change and resize
1532 * events still get sent to the event widget because
1533 * 1) these events have no meaning for the grabbing widget
1534 * and 2) redirecting these events to the grabbing widget
1535 * could cause the display to be messed up.
1537 * Drag events are also not redirected, since it isn't
1538 * clear what the semantics of that would be.
1540 switch (event->type)
1546 g_object_ref (event_widget);
1547 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1548 !gtk_widget_event (event_widget, event))
1549 gtk_widget_destroy (event_widget);
1550 g_object_unref (event_widget);
1554 /* Unexpected GDK_DESTROY from the outside, ignore for
1555 * child windows, handle like a GDK_DELETE for toplevels
1557 if (!event_widget->parent)
1559 g_object_ref (event_widget);
1560 if (!gtk_widget_event (event_widget, event) &&
1561 GTK_WIDGET_REALIZED (event_widget))
1562 gtk_widget_destroy (event_widget);
1563 g_object_unref (event_widget);
1568 if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
1570 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1571 gtk_widget_send_expose (event_widget, event);
1572 gdk_window_end_paint (event->any.window);
1576 /* The app may paint with a previously allocated cairo_t,
1577 which will draw directly to the window. We can't catch cairo
1578 drap operatoins to automatically flush the window, thus we
1579 need to explicitly flush any outstanding moves or double
1581 gdk_window_flush (event->any.window);
1582 gtk_widget_send_expose (event_widget, event);
1586 case GDK_PROPERTY_NOTIFY:
1588 case GDK_FOCUS_CHANGE:
1592 case GDK_SELECTION_CLEAR:
1593 case GDK_SELECTION_REQUEST:
1594 case GDK_SELECTION_NOTIFY:
1595 case GDK_CLIENT_EVENT:
1596 case GDK_VISIBILITY_NOTIFY:
1597 case GDK_WINDOW_STATE:
1598 case GDK_GRAB_BROKEN:
1600 gtk_widget_event (event_widget, event);
1604 case GDK_BUTTON_PRESS:
1605 case GDK_2BUTTON_PRESS:
1606 case GDK_3BUTTON_PRESS:
1607 gtk_propagate_event (grab_widget, event);
1611 case GDK_KEY_RELEASE:
1614 if (gtk_invoke_key_snoopers (grab_widget, event))
1617 /* else fall through */
1618 case GDK_MOTION_NOTIFY:
1619 case GDK_BUTTON_RELEASE:
1620 case GDK_PROXIMITY_IN:
1621 case GDK_PROXIMITY_OUT:
1622 gtk_propagate_event (grab_widget, event);
1625 case GDK_ENTER_NOTIFY:
1626 GTK_PRIVATE_SET_FLAG (event_widget, GTK_HAS_POINTER);
1627 _gtk_widget_set_pointer_window (event_widget, event->any.window);
1628 if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1629 gtk_widget_event (grab_widget, event);
1632 case GDK_LEAVE_NOTIFY:
1633 GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_HAS_POINTER);
1634 if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1635 gtk_widget_event (grab_widget, event);
1638 case GDK_DRAG_STATUS:
1639 case GDK_DROP_FINISHED:
1640 _gtk_drag_source_handle_event (event_widget, event);
1642 case GDK_DRAG_ENTER:
1643 case GDK_DRAG_LEAVE:
1644 case GDK_DRAG_MOTION:
1645 case GDK_DROP_START:
1646 _gtk_drag_dest_handle_event (event_widget, event);
1649 g_assert_not_reached ();
1653 if (event->type == GDK_ENTER_NOTIFY
1654 || event->type == GDK_LEAVE_NOTIFY
1655 || event->type == GDK_BUTTON_PRESS
1656 || event->type == GDK_2BUTTON_PRESS
1657 || event->type == GDK_3BUTTON_PRESS
1658 || event->type == GDK_KEY_PRESS
1659 || event->type == GDK_DRAG_ENTER
1660 || event->type == GDK_GRAB_BROKEN
1661 || event->type == GDK_MOTION_NOTIFY
1662 || event->type == GDK_SCROLL)
1664 _gtk_tooltip_handle_event (event);
1667 tmp_list = current_events;
1668 current_events = g_list_remove_link (current_events, tmp_list);
1669 g_list_free_1 (tmp_list);
1671 if (rewritten_event)
1672 gdk_event_free (rewritten_event);
1687 static GtkWindowGroup *
1688 gtk_main_get_window_group (GtkWidget *widget)
1690 GtkWidget *toplevel = NULL;
1693 toplevel = gtk_widget_get_toplevel (widget);
1695 if (GTK_IS_WINDOW (toplevel))
1696 return gtk_window_get_group (GTK_WINDOW (toplevel));
1698 return gtk_window_get_group (NULL);
1703 GtkWidget *old_grab_widget;
1704 GtkWidget *new_grab_widget;
1705 gboolean was_grabbed;
1706 gboolean is_grabbed;
1711 gtk_grab_notify_foreach (GtkWidget *child,
1715 GrabNotifyInfo *info = data;
1717 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1719 was_grabbed = info->was_grabbed;
1720 is_grabbed = info->is_grabbed;
1722 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1723 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1725 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1726 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1728 g_object_ref (child);
1730 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1731 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1735 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1736 if (!was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1737 && GTK_WIDGET_IS_SENSITIVE (child))
1738 _gtk_widget_synthesize_crossing (child, info->new_grab_widget,
1739 GDK_CROSSING_GTK_GRAB);
1743 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1744 if (was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1745 && GTK_WIDGET_IS_SENSITIVE (child))
1746 _gtk_widget_synthesize_crossing (info->old_grab_widget, child,
1747 info->from_grab ? GDK_CROSSING_GTK_GRAB
1748 : GDK_CROSSING_GTK_UNGRAB);
1751 if (was_shadowed != is_shadowed)
1752 _gtk_widget_grab_notify (child, was_shadowed);
1754 g_object_unref (child);
1756 info->was_grabbed = was_grabbed;
1757 info->is_grabbed = is_grabbed;
1761 gtk_grab_notify (GtkWindowGroup *group,
1762 GtkWidget *old_grab_widget,
1763 GtkWidget *new_grab_widget,
1767 GrabNotifyInfo info;
1769 if (old_grab_widget == new_grab_widget)
1772 info.old_grab_widget = old_grab_widget;
1773 info.new_grab_widget = new_grab_widget;
1774 info.from_grab = from_grab;
1776 g_object_ref (group);
1778 toplevels = gtk_window_list_toplevels ();
1779 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1783 GtkWindow *toplevel = toplevels->data;
1784 toplevels = g_list_delete_link (toplevels, toplevels);
1786 info.was_grabbed = FALSE;
1787 info.is_grabbed = FALSE;
1789 if (group == gtk_window_get_group (toplevel))
1790 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1791 g_object_unref (toplevel);
1794 g_object_unref (group);
1798 gtk_grab_add (GtkWidget *widget)
1800 GtkWindowGroup *group;
1801 GtkWidget *old_grab_widget;
1803 g_return_if_fail (widget != NULL);
1805 if (!GTK_WIDGET_HAS_GRAB (widget) && GTK_WIDGET_IS_SENSITIVE (widget))
1807 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
1809 group = gtk_main_get_window_group (widget);
1812 old_grab_widget = (GtkWidget *)group->grabs->data;
1814 old_grab_widget = NULL;
1816 g_object_ref (widget);
1817 group->grabs = g_slist_prepend (group->grabs, widget);
1819 gtk_grab_notify (group, old_grab_widget, widget, TRUE);
1824 gtk_grab_get_current (void)
1826 GtkWindowGroup *group;
1828 group = gtk_main_get_window_group (NULL);
1831 return GTK_WIDGET (group->grabs->data);
1836 gtk_grab_remove (GtkWidget *widget)
1838 GtkWindowGroup *group;
1839 GtkWidget *new_grab_widget;
1841 g_return_if_fail (widget != NULL);
1843 if (GTK_WIDGET_HAS_GRAB (widget))
1845 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
1847 group = gtk_main_get_window_group (widget);
1848 group->grabs = g_slist_remove (group->grabs, widget);
1851 new_grab_widget = (GtkWidget *)group->grabs->data;
1853 new_grab_widget = NULL;
1855 gtk_grab_notify (group, widget, new_grab_widget, FALSE);
1857 g_object_unref (widget);
1862 gtk_init_add (GtkFunction function,
1865 GtkInitFunction *init;
1867 init = g_new (GtkInitFunction, 1);
1868 init->function = function;
1871 init_functions = g_list_prepend (init_functions, init);
1875 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
1878 GtkKeySnooperData *data;
1879 static guint snooper_id = 1;
1881 g_return_val_if_fail (snooper != NULL, 0);
1883 data = g_new (GtkKeySnooperData, 1);
1884 data->func = snooper;
1885 data->func_data = func_data;
1886 data->id = snooper_id++;
1887 key_snoopers = g_slist_prepend (key_snoopers, data);
1893 gtk_key_snooper_remove (guint snooper_id)
1895 GtkKeySnooperData *data = NULL;
1898 slist = key_snoopers;
1902 if (data->id == snooper_id)
1905 slist = slist->next;
1910 key_snoopers = g_slist_remove (key_snoopers, data);
1916 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
1920 gint return_val = FALSE;
1922 slist = key_snoopers;
1923 while (slist && !return_val)
1925 GtkKeySnooperData *data;
1928 slist = slist->next;
1929 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
1936 gtk_quit_add_full (guint main_level,
1937 GtkFunction function,
1938 GtkCallbackMarshal marshal,
1940 GDestroyNotify destroy)
1942 static guint quit_id = 1;
1943 GtkQuitFunction *quitf;
1945 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
1947 quitf = g_slice_new (GtkQuitFunction);
1949 quitf->id = quit_id++;
1950 quitf->main_level = main_level;
1951 quitf->function = function;
1952 quitf->marshal = marshal;
1954 quitf->destroy = destroy;
1956 quit_functions = g_list_prepend (quit_functions, quitf);
1962 gtk_quit_destroy (GtkQuitFunction *quitf)
1965 quitf->destroy (quitf->data);
1966 g_slice_free (GtkQuitFunction, quitf);
1970 gtk_quit_destructor (GtkObject **object_p)
1973 gtk_object_destroy (*object_p);
1980 gtk_quit_add_destroy (guint main_level,
1983 GtkObject **object_p;
1985 g_return_if_fail (main_level > 0);
1986 g_return_if_fail (GTK_IS_OBJECT (object));
1988 object_p = g_new (GtkObject*, 1);
1990 g_signal_connect (object,
1992 G_CALLBACK (gtk_widget_destroyed),
1994 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
1998 gtk_quit_add (guint main_level,
1999 GtkFunction function,
2002 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2006 gtk_quit_remove (guint id)
2008 GtkQuitFunction *quitf;
2011 tmp_list = quit_functions;
2014 quitf = tmp_list->data;
2016 if (quitf->id == id)
2018 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2019 g_list_free (tmp_list);
2020 gtk_quit_destroy (quitf);
2025 tmp_list = tmp_list->next;
2030 gtk_quit_remove_by_data (gpointer data)
2032 GtkQuitFunction *quitf;
2035 tmp_list = quit_functions;
2038 quitf = tmp_list->data;
2040 if (quitf->data == data)
2042 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2043 g_list_free (tmp_list);
2044 gtk_quit_destroy (quitf);
2049 tmp_list = tmp_list->next;
2054 gtk_timeout_add_full (guint32 interval,
2055 GtkFunction function,
2056 GtkCallbackMarshal marshal,
2058 GDestroyNotify destroy)
2062 GtkClosure *closure;
2064 closure = g_new (GtkClosure, 1);
2065 closure->marshal = marshal;
2066 closure->data = data;
2067 closure->destroy = destroy;
2069 return g_timeout_add_full (0, interval,
2070 gtk_invoke_idle_timeout,
2072 gtk_destroy_closure);
2075 return g_timeout_add_full (0, interval, function, data, destroy);
2079 gtk_timeout_add (guint32 interval,
2080 GtkFunction function,
2083 return g_timeout_add_full (0, interval, function, data, NULL);
2087 gtk_timeout_remove (guint tag)
2089 g_source_remove (tag);
2093 gtk_idle_add_full (gint priority,
2094 GtkFunction function,
2095 GtkCallbackMarshal marshal,
2097 GDestroyNotify destroy)
2101 GtkClosure *closure;
2103 closure = g_new (GtkClosure, 1);
2104 closure->marshal = marshal;
2105 closure->data = data;
2106 closure->destroy = destroy;
2108 return g_idle_add_full (priority,
2109 gtk_invoke_idle_timeout,
2111 gtk_destroy_closure);
2114 return g_idle_add_full (priority, function, data, destroy);
2118 gtk_idle_add (GtkFunction function,
2121 return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
2125 gtk_idle_add_priority (gint priority,
2126 GtkFunction function,
2129 return g_idle_add_full (priority, function, data, NULL);
2133 gtk_idle_remove (guint tag)
2135 g_source_remove (tag);
2139 gtk_idle_remove_by_data (gpointer data)
2141 if (!g_idle_remove_by_data (data))
2142 g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
2146 gtk_input_add_full (gint source,
2147 GdkInputCondition condition,
2148 GdkInputFunction function,
2149 GtkCallbackMarshal marshal,
2151 GDestroyNotify destroy)
2155 GtkClosure *closure;
2157 closure = g_new (GtkClosure, 1);
2158 closure->marshal = marshal;
2159 closure->data = data;
2160 closure->destroy = destroy;
2162 return gdk_input_add_full (source,
2164 (GdkInputFunction) gtk_invoke_input,
2166 (GDestroyNotify) gtk_destroy_closure);
2169 return gdk_input_add_full (source, condition, function, data, destroy);
2173 gtk_input_remove (guint tag)
2175 g_source_remove (tag);
2179 gtk_destroy_closure (gpointer data)
2181 GtkClosure *closure = data;
2183 if (closure->destroy)
2184 (closure->destroy) (closure->data);
2189 gtk_invoke_idle_timeout (gpointer data)
2191 GtkClosure *closure = data;
2194 gint ret_val = FALSE;
2195 args[0].name = NULL;
2196 args[0].type = G_TYPE_BOOLEAN;
2197 args[0].d.pointer_data = &ret_val;
2198 closure->marshal (NULL, closure->data, 0, args);
2203 gtk_invoke_input (gpointer data,
2205 GdkInputCondition condition)
2207 GtkClosure *closure = data;
2210 args[0].type = G_TYPE_INT;
2211 args[0].name = NULL;
2212 GTK_VALUE_INT (args[0]) = source;
2213 args[1].type = GDK_TYPE_INPUT_CONDITION;
2214 args[1].name = NULL;
2215 GTK_VALUE_FLAGS (args[1]) = condition;
2216 args[2].type = G_TYPE_NONE;
2217 args[2].name = NULL;
2219 closure->marshal (NULL, closure->data, 2, args);
2223 * gtk_get_current_event:
2225 * Obtains a copy of the event currently being processed by GTK+. For
2226 * example, if you get a "clicked" signal from #GtkButton, the current
2227 * event will be the #GdkEventButton that triggered the "clicked"
2228 * signal. The returned event must be freed with gdk_event_free().
2229 * If there is no current event, the function returns %NULL.
2231 * Return value: a copy of the current event, or %NULL if no current event.
2234 gtk_get_current_event (void)
2237 return gdk_event_copy (current_events->data);
2243 * gtk_get_current_event_time:
2245 * If there is a current event and it has a timestamp, return that
2246 * timestamp, otherwise return %GDK_CURRENT_TIME.
2248 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2251 gtk_get_current_event_time (void)
2254 return gdk_event_get_time (current_events->data);
2256 return GDK_CURRENT_TIME;
2260 * gtk_get_current_event_state:
2261 * @state: a location to store the state of the current event
2263 * If there is a current event and it has a state field, place
2264 * that state field in @state and return %TRUE, otherwise return
2267 * Return value: %TRUE if there was a current event and it had a state field
2270 gtk_get_current_event_state (GdkModifierType *state)
2272 g_return_val_if_fail (state != NULL, FALSE);
2275 return gdk_event_get_state (current_events->data, state);
2284 * gtk_get_event_widget:
2285 * @event: a #GdkEvent
2287 * If @event is %NULL or the event was not associated with any widget,
2288 * returns %NULL, otherwise returns the widget that received the event
2291 * Return value: the widget that originally received @event, or %NULL
2294 gtk_get_event_widget (GdkEvent *event)
2297 gpointer widget_ptr;
2300 if (event && event->any.window &&
2301 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2303 gdk_window_get_user_data (event->any.window, &widget_ptr);
2304 widget = widget_ptr;
2311 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2313 if (!quitf->marshal)
2314 return quitf->function (quitf->data);
2318 gint ret_val = FALSE;
2320 args[0].name = NULL;
2321 args[0].type = G_TYPE_BOOLEAN;
2322 args[0].d.pointer_data = &ret_val;
2323 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2331 * gtk_propagate_event:
2332 * @widget: a #GtkWidget
2335 * Sends an event to a widget, propagating the event to parent widgets
2336 * if the event remains unhandled. Events received by GTK+ from GDK
2337 * normally begin in gtk_main_do_event(). Depending on the type of
2338 * event, existence of modal dialogs, grabs, etc., the event may be
2339 * propagated; if so, this function is used. gtk_propagate_event()
2340 * calls gtk_widget_event() on each widget it decides to send the
2341 * event to. So gtk_widget_event() is the lowest-level function; it
2342 * simply emits the "event" and possibly an event-specific signal on a
2343 * widget. gtk_propagate_event() is a bit higher-level, and
2344 * gtk_main_do_event() is the highest level.
2346 * All that said, you most likely don't want to use any of these
2347 * functions; synthesizing events is rarely needed. Consider asking on
2348 * the mailing list for better ways to achieve your goals. For
2349 * example, use gdk_window_invalidate_rect() or
2350 * gtk_widget_queue_draw() instead of making up expose events.
2354 gtk_propagate_event (GtkWidget *widget,
2359 g_return_if_fail (GTK_IS_WIDGET (widget));
2360 g_return_if_fail (event != NULL);
2362 handled_event = FALSE;
2364 g_object_ref (widget);
2366 if ((event->type == GDK_KEY_PRESS) ||
2367 (event->type == GDK_KEY_RELEASE))
2369 /* Only send key events within Window widgets to the Window
2370 * The Window widget will in turn pass the
2371 * key event on to the currently focused widget
2376 window = gtk_widget_get_toplevel (widget);
2377 if (GTK_IS_WINDOW (window))
2379 /* If there is a grab within the window, give the grab widget
2380 * a first crack at the key event
2382 if (widget != window && GTK_WIDGET_HAS_GRAB (widget))
2383 handled_event = gtk_widget_event (widget, event);
2387 window = gtk_widget_get_toplevel (widget);
2388 if (GTK_IS_WINDOW (window))
2390 if (GTK_WIDGET_IS_SENSITIVE (window))
2391 gtk_widget_event (window, event);
2395 handled_event = TRUE; /* don't send to widget */
2399 /* Other events get propagated up the widget tree
2400 * so that parents can see the button and motion
2401 * events of the children.
2409 /* Scroll events are special cased here because it
2410 * feels wrong when scrolling a GtkViewport, say,
2411 * to have children of the viewport eat the scroll
2414 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2415 handled_event = event->type != GDK_SCROLL;
2417 handled_event = gtk_widget_event (widget, event);
2419 tmp = widget->parent;
2420 g_object_unref (widget);
2424 if (!handled_event && widget)
2425 g_object_ref (widget);
2431 g_object_unref (widget);
2436 gtk_error (gchar *str)
2442 gtk_warning (gchar *str)
2448 gtk_message (gchar *str)
2454 gtk_print (gchar *str)
2456 static GtkWidget *window = NULL;
2457 static GtkWidget *text;
2458 static int level = 0;
2462 GtkWidget *hscrollbar;
2463 GtkWidget *vscrollbar;
2464 GtkWidget *separator;
2469 fputs (str, stdout);
2476 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2478 gtk_signal_connect (GTK_OBJECT (window), "destroy",
2479 G_CALLBACK (gtk_widget_destroyed),
2482 gtk_window_set_title (GTK_WINDOW (window), "Messages");
2484 box1 = gtk_vbox_new (FALSE, 0);
2485 gtk_container_add (GTK_CONTAINER (window), box1);
2486 gtk_widget_show (box1);
2489 box2 = gtk_vbox_new (FALSE, 10);
2490 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2491 gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2492 gtk_widget_show (box2);
2495 table = gtk_table_new (2, 2, FALSE);
2496 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2497 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2498 gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2499 gtk_widget_show (table);
2501 text = gtk_text_new (NULL, NULL);
2502 gtk_text_set_editable (GTK_TEXT (text), FALSE);
2503 gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2504 gtk_widget_show (text);
2505 gtk_widget_realize (text);
2507 hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2508 gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2509 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2510 gtk_widget_show (hscrollbar);
2512 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2513 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2514 GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2515 gtk_widget_show (vscrollbar);
2517 separator = gtk_hseparator_new ();
2518 gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2519 gtk_widget_show (separator);
2522 box2 = gtk_vbox_new (FALSE, 10);
2523 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2524 gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2525 gtk_widget_show (box2);
2528 button = gtk_button_new_with_label ("close");
2529 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2530 G_CALLBACK (gtk_widget_hide),
2531 GTK_OBJECT (window));
2532 gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2533 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2534 gtk_widget_grab_default (button);
2535 gtk_widget_show (button);
2539 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2542 if (!GTK_WIDGET_VISIBLE (window))
2543 gtk_widget_show (window);
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;
2563 #define __GTK_MAIN_C__
2564 #include "gtkaliasdef.c"