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 */
721 _gtk_accel_map_init ();
724 /* Set the 'initialized' flag.
726 gtk_initialized = TRUE;
728 /* load gtk modules */
729 if (gtk_modules_string)
731 _gtk_modules_init (argc, argv, gtk_modules_string->str);
732 g_string_free (gtk_modules_string, TRUE);
736 _gtk_modules_init (argc, argv, NULL);
743 gboolean open_default_display;
747 pre_parse_hook (GOptionContext *context,
752 do_pre_parse_initialization (NULL, NULL);
758 post_parse_hook (GOptionContext *context,
763 OptionGroupInfo *info = data;
766 do_post_parse_initialization (NULL, NULL);
768 if (info->open_default_display)
770 if (gdk_display_open_default_libgtk_only () == NULL)
772 const char *display_name = gdk_get_display_arg_name ();
775 G_OPTION_ERROR_FAILED,
776 _("Cannot open display: %s"),
777 display_name ? display_name : "" );
788 * gtk_get_option_group:
789 * @open_default_display: whether to open the default display
790 * when parsing the commandline arguments
792 * Returns a #GOptionGroup for the commandline arguments recognized
793 * by GTK+ and GDK. You should add this group to your #GOptionContext
794 * with g_option_context_add_group(), if you are using
795 * g_option_context_parse() to parse your commandline arguments.
797 * Returns: a #GOptionGroup for the commandline arguments recognized
803 gtk_get_option_group (gboolean open_default_display)
806 OptionGroupInfo *info;
808 gettext_initialization ();
810 info = g_new0 (OptionGroupInfo, 1);
811 info->open_default_display = open_default_display;
813 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
814 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
816 gdk_add_option_entries_libgtk_only (group);
817 g_option_group_add_entries (group, gtk_args);
818 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
824 * gtk_init_with_args:
825 * @argc: a pointer to the number of command line arguments.
826 * @argv: a pointer to the array of command line arguments.
827 * @parameter_string: a string which is displayed in
828 * the first line of <option>--help</option> output, after
829 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
830 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
831 * describing the options of your program
832 * @translation_domain: a translation domain to use for translating
833 * the <option>--help</option> output for the options in @entries
834 * with gettext(), or %NULL
835 * @error: a return location for errors
837 * This function does the same work as gtk_init_check().
838 * Additionally, it allows you to add your own commandline options,
839 * and it automatically generates nicely formatted
840 * <option>--help</option> output. Note that your program will
841 * be terminated after writing out the help output.
843 * Returns: %TRUE if the GUI has been successfully initialized,
849 gtk_init_with_args (int *argc,
851 const char *parameter_string,
852 GOptionEntry *entries,
853 const char *translation_domain,
856 GOptionContext *context;
857 GOptionGroup *gtk_group;
861 return gdk_display_open_default_libgtk_only () != NULL;
863 gettext_initialization ();
865 if (!check_setugid ())
868 gtk_group = gtk_get_option_group (TRUE);
870 context = g_option_context_new (parameter_string);
871 g_option_context_add_group (context, gtk_group);
874 g_option_context_add_main_entries (context, entries, translation_domain);
875 retval = g_option_context_parse (context, argc, argv, error);
877 g_option_context_free (context);
885 * @argc: (inout): a pointer to the number of command line arguments.
886 * @argv: (array) (inout): a pointer to the array of command line arguments.
888 * Parses command line arguments, and initializes global
889 * attributes of GTK+, but does not actually open a connection
890 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
892 * Any arguments used by GTK+ or GDK are removed from the array and
893 * @argc and @argv are updated accordingly.
895 * You shouldn't call this function explicitely if you are using
896 * gtk_init(), or gtk_init_check().
898 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
901 gtk_parse_args (int *argc,
904 GOptionContext *option_context;
905 GOptionGroup *gtk_group;
906 GError *error = NULL;
911 gettext_initialization ();
913 if (!check_setugid ())
916 option_context = g_option_context_new (NULL);
917 g_option_context_set_ignore_unknown_options (option_context, TRUE);
918 g_option_context_set_help_enabled (option_context, FALSE);
919 gtk_group = gtk_get_option_group (FALSE);
920 g_option_context_set_main_group (option_context, gtk_group);
921 if (!g_option_context_parse (option_context, argc, argv, &error))
923 g_warning ("%s", error->message);
924 g_error_free (error);
927 g_option_context_free (option_context);
932 #ifdef G_PLATFORM_WIN32
933 #undef gtk_init_check
938 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
939 * main() function. Changed if any arguments were handled.
940 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
941 * Any parameters understood by gtk_init() are stripped before return.
943 * This function does the same work as gtk_init() with only
944 * a single change: It does not terminate the program if the GUI can't be
945 * initialized. Instead it returns %FALSE on failure.
947 * This way the application can fall back to some other means of communication
948 * with the user - for example a curses or command line interface.
950 * Return value: %TRUE if the GUI has been successfully initialized,
954 gtk_init_check (int *argc,
957 if (!gtk_parse_args (argc, argv))
960 return gdk_display_open_default_libgtk_only () != NULL;
963 #ifdef G_PLATFORM_WIN32
969 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
970 * main() function. Changed if any arguments were handled.
971 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
972 * Any parameters understood by gtk_init() are stripped before return.
974 * Call this function before using any other GTK+ functions in your GUI
975 * applications. It will initialize everything needed to operate the
976 * toolkit and parses some standard command line options. @argc and
977 * @argv are adjusted accordingly so your own code will
978 * never see those standard arguments.
980 * Note that there are some alternative ways to initialize GTK+:
981 * if you are calling gtk_parse_args(), gtk_init_check(),
982 * gtk_init_with_args() or g_option_context_parse() with
983 * the option group returned by gtk_get_option_group(), you
984 * <emphasis>don't</emphasis> have to call gtk_init().
987 * This function will terminate your program if it was unable to initialize
988 * the GUI for some reason. If you want your program to fall back to a
989 * textual interface you want to call gtk_init_check() instead.
993 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
994 * during initialization, to ignore SIGPIPE signals, since these are
995 * almost never wanted in graphical applications. If you do need to
996 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
997 * but notice that other libraries (e.g. libdbus or gvfs) might do
1002 gtk_init (int *argc, char ***argv)
1004 if (!gtk_init_check (argc, argv))
1006 const char *display_name_arg = gdk_get_display_arg_name ();
1007 if (display_name_arg == NULL)
1008 display_name_arg = getenv("DISPLAY");
1009 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1014 #ifdef G_PLATFORM_WIN32
1017 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1019 if (sizeof_GtkWindow != sizeof (GtkWindow))
1020 g_error ("Incompatible build!\n"
1021 "The code using GTK+ thinks GtkWindow is of different\n"
1022 "size than it actually is in this build of GTK+.\n"
1023 "On Windows, this probably means that you have compiled\n"
1024 "your code with gcc without the -mms-bitfields switch,\n"
1025 "or that you are using an unsupported compiler.");
1028 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1029 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1030 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1031 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1032 * -fnative-struct still matters. GtkBox is one such.
1035 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1037 if (sizeof_GtkBox != sizeof (GtkBox))
1038 g_error ("Incompatible build!\n"
1039 "The code using GTK+ thinks GtkBox is of different\n"
1040 "size than it actually is in this build of GTK+.\n"
1041 "On Windows, this probably means that you have compiled\n"
1042 "your code with gcc without the -mms-bitfields switch,\n"
1043 "or that you are using an unsupported compiler.");
1046 /* These two functions might get more checks added later, thus pass
1047 * in the number of extra args.
1050 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1052 check_sizeof_GtkWindow (sizeof_GtkWindow);
1053 if (num_checks >= 2)
1054 check_sizeof_GtkBox (sizeof_GtkBox);
1055 gtk_init (argc, argv);
1059 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1061 check_sizeof_GtkWindow (sizeof_GtkWindow);
1062 if (num_checks >= 2)
1063 check_sizeof_GtkBox (sizeof_GtkBox);
1064 return gtk_init_check (argc, argv);
1070 gtk_exit (gint errorcode)
1079 * Initializes internationalization support for GTK+. gtk_init()
1080 * automatically does this, so there is typically no point
1081 * in calling this function.
1083 * If you are calling this function because you changed the locale
1084 * after GTK+ is was initialized, then calling this function
1085 * may help a bit. (Note, however, that changing the locale
1086 * after GTK+ is initialized may produce inconsistent results and
1087 * is not really supported.)
1089 * In detail - sets the current locale according to the
1090 * program environment. This is the same as calling the C library function
1091 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1092 * locale specific setup of the windowing system used by GDK.
1094 * Returns: a string corresponding to the locale set, typically in the
1095 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1096 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1097 * result of the setlocale(); it is also used on other machines, such as
1098 * Windows, where the C library returns a different result. The string is
1099 * owned by GTK+ and should not be modified or freed.
1102 gtk_set_locale (void)
1104 return gdk_set_locale ();
1108 * _gtk_get_lc_ctype:
1110 * Return the Unix-style locale string for the language currently in
1111 * effect. On Unix systems, this is the return value from
1112 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1113 * affect this through the environment variables LC_ALL, LC_CTYPE or
1114 * LANG (checked in that order). The locale strings typically is in
1115 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1116 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1117 * Swedish as written in Finland or pt_BR for Portuguese as written in
1120 * On Windows, the C library doesn't use any such environment
1121 * variables, and setting them won't affect the behaviour of functions
1122 * like ctime(). The user sets the locale through the Regional Options
1123 * in the Control Panel. The C library (in the setlocale() function)
1124 * does not use country and language codes, but country and language
1125 * names spelled out in English.
1126 * However, this function does check the above environment
1127 * variables, and does return a Unix-style locale string based on
1128 * either said environment variables or the thread's current locale.
1130 * Return value: a dynamically allocated string, free with g_free().
1134 _gtk_get_lc_ctype (void)
1137 /* Somebody might try to set the locale for this process using the
1138 * LANG or LC_ environment variables. The Microsoft C library
1139 * doesn't know anything about them. You set the locale in the
1140 * Control Panel. Setting these env vars won't have any affect on
1141 * locale-dependent C library functions like ctime(). But just for
1142 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1143 * it easier to test GTK and Pango in various default languages, you
1144 * don't have to clickety-click in the Control Panel, you can simply
1145 * start the program with LC_ALL=something on the command line.)
1149 p = getenv ("LC_ALL");
1151 return g_strdup (p);
1153 p = getenv ("LC_CTYPE");
1155 return g_strdup (p);
1157 p = getenv ("LANG");
1159 return g_strdup (p);
1161 return g_win32_getlocale ();
1163 return g_strdup (setlocale (LC_CTYPE, NULL));
1168 * gtk_get_default_language:
1170 * Returns the #PangoLanguage for the default language currently in
1171 * effect. (Note that this can change over the life of an
1172 * application.) The default language is derived from the current
1173 * locale. It determines, for example, whether GTK+ uses the
1174 * right-to-left or left-to-right text direction.
1176 * This function is equivalent to pango_language_get_default(). See
1177 * that function for details.
1179 * Return value: the default language as a #PangoLanguage, must not be
1183 gtk_get_default_language (void)
1185 return pango_language_get_default ();
1193 GtkInitFunction *init;
1196 gtk_main_loop_level++;
1198 loop = g_main_loop_new (NULL, TRUE);
1199 main_loops = g_slist_prepend (main_loops, loop);
1201 tmp_list = functions = init_functions;
1202 init_functions = NULL;
1206 init = tmp_list->data;
1207 tmp_list = tmp_list->next;
1209 (* init->function) (init->data);
1212 g_list_free (functions);
1214 if (g_main_loop_is_running (main_loops->data))
1216 GDK_THREADS_LEAVE ();
1217 g_main_loop_run (loop);
1218 GDK_THREADS_ENTER ();
1224 GList *reinvoke_list = NULL;
1225 GtkQuitFunction *quitf;
1227 while (quit_functions)
1229 quitf = quit_functions->data;
1231 tmp_list = quit_functions;
1232 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1233 g_list_free_1 (tmp_list);
1235 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1236 gtk_quit_invoke_function (quitf))
1238 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1242 gtk_quit_destroy (quitf);
1249 work = g_list_last (reinvoke_list);
1251 quit_functions->prev = work;
1252 work->next = quit_functions;
1253 quit_functions = work;
1259 main_loops = g_slist_remove (main_loops, loop);
1261 g_main_loop_unref (loop);
1263 gtk_main_loop_level--;
1265 if (gtk_main_loop_level == 0)
1267 /* Try storing all clipboard data we have */
1268 _gtk_clipboard_store_all ();
1270 /* Synchronize the recent manager singleton */
1271 _gtk_recent_manager_sync ();
1276 gtk_main_level (void)
1278 return gtk_main_loop_level;
1282 gtk_main_quit (void)
1284 g_return_if_fail (main_loops != NULL);
1286 g_main_loop_quit (main_loops->data);
1290 gtk_events_pending (void)
1294 GDK_THREADS_LEAVE ();
1295 result = g_main_context_pending (NULL);
1296 GDK_THREADS_ENTER ();
1302 gtk_main_iteration (void)
1304 GDK_THREADS_LEAVE ();
1305 g_main_context_iteration (NULL, TRUE);
1306 GDK_THREADS_ENTER ();
1309 return !g_main_loop_is_running (main_loops->data);
1315 gtk_main_iteration_do (gboolean blocking)
1317 GDK_THREADS_LEAVE ();
1318 g_main_context_iteration (NULL, blocking);
1319 GDK_THREADS_ENTER ();
1322 return !g_main_loop_is_running (main_loops->data);
1327 /* private libgtk to libgdk interfaces
1329 gboolean gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
1330 GdkWindow **grab_window,
1331 gboolean *owner_events);
1332 gboolean gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1333 GdkWindow **grab_window,
1334 gboolean *owner_events);
1337 rewrite_events_translate (GdkWindow *old_window,
1338 GdkWindow *new_window,
1342 gint old_origin_x, old_origin_y;
1343 gint new_origin_x, new_origin_y;
1345 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1346 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1348 *x += old_origin_x - new_origin_x;
1349 *y += old_origin_y - new_origin_y;
1353 rewrite_event_for_window (GdkEvent *event,
1354 GdkWindow *new_window)
1356 event = gdk_event_copy (event);
1358 switch (event->type)
1361 rewrite_events_translate (event->any.window,
1363 &event->scroll.x, &event->scroll.y);
1365 case GDK_BUTTON_PRESS:
1366 case GDK_2BUTTON_PRESS:
1367 case GDK_3BUTTON_PRESS:
1368 case GDK_BUTTON_RELEASE:
1369 rewrite_events_translate (event->any.window,
1371 &event->button.x, &event->button.y);
1373 case GDK_MOTION_NOTIFY:
1374 rewrite_events_translate (event->any.window,
1376 &event->motion.x, &event->motion.y);
1379 case GDK_KEY_RELEASE:
1380 case GDK_PROXIMITY_IN:
1381 case GDK_PROXIMITY_OUT:
1388 g_object_unref (event->any.window);
1389 event->any.window = g_object_ref (new_window);
1394 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1395 * then what X11 does is deliver the event normally if it was going to this
1396 * client, otherwise, delivers it in terms of the grab window. This function
1397 * rewrites events to the effect that events going to the same window group
1398 * are delivered normally, otherwise, the event is delivered in terms of the
1402 rewrite_event_for_grabs (GdkEvent *event)
1404 GdkWindow *grab_window;
1405 GtkWidget *event_widget, *grab_widget;
1406 gpointer grab_widget_ptr;
1407 gboolean owner_events;
1408 GdkDisplay *display;
1410 switch (event->type)
1413 case GDK_BUTTON_PRESS:
1414 case GDK_2BUTTON_PRESS:
1415 case GDK_3BUTTON_PRESS:
1416 case GDK_BUTTON_RELEASE:
1417 case GDK_MOTION_NOTIFY:
1418 case GDK_PROXIMITY_IN:
1419 case GDK_PROXIMITY_OUT:
1420 display = gdk_drawable_get_display (event->proximity.window);
1421 if (!gdk_pointer_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1427 case GDK_KEY_RELEASE:
1428 display = gdk_drawable_get_display (event->key.window);
1429 if (!gdk_keyboard_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1438 event_widget = gtk_get_event_widget (event);
1439 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1440 grab_widget = grab_widget_ptr;
1443 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1444 return rewrite_event_for_window (event, grab_window);
1450 gtk_main_do_event (GdkEvent *event)
1452 GtkWidget *event_widget;
1453 GtkWidget *grab_widget;
1454 GtkWindowGroup *window_group;
1455 GdkEvent *rewritten_event = NULL;
1458 if (event->type == GDK_SETTING)
1460 _gtk_settings_handle_event (&event->setting);
1464 if (event->type == GDK_OWNER_CHANGE)
1466 _gtk_clipboard_handle_event (&event->owner_change);
1470 /* Find the widget which got the event. We store the widget
1471 * in the user_data field of GdkWindow's.
1472 * Ignore the event if we don't have a widget for it, except
1473 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1474 * Though this happens rarely, bogus events can occour
1475 * for e.g. destroyed GdkWindows.
1477 event_widget = gtk_get_event_widget (event);
1480 /* To handle selection INCR transactions, we select
1481 * PropertyNotify events on the requestor window and create
1482 * a corresponding (fake) GdkWindow so that events get
1483 * here. There won't be a widget though, so we have to handle
1486 if (event->type == GDK_PROPERTY_NOTIFY)
1487 _gtk_selection_incr_event (event->any.window,
1493 /* If pointer or keyboard grabs are in effect, munge the events
1494 * so that each window group looks like a separate app.
1496 rewritten_event = rewrite_event_for_grabs (event);
1497 if (rewritten_event)
1499 event = rewritten_event;
1500 event_widget = gtk_get_event_widget (event);
1503 window_group = gtk_main_get_window_group (event_widget);
1505 /* Push the event onto a stack of current events for
1506 * gtk_current_event_get().
1508 current_events = g_list_prepend (current_events, event);
1510 /* If there is a grab in effect...
1512 if (window_group->grabs)
1514 grab_widget = window_group->grabs->data;
1516 /* If the grab widget is an ancestor of the event widget
1517 * then we send the event to the original event widget.
1518 * This is the key to implementing modality.
1520 if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
1521 gtk_widget_is_ancestor (event_widget, grab_widget))
1522 grab_widget = event_widget;
1526 grab_widget = event_widget;
1529 /* Not all events get sent to the grabbing widget.
1530 * The delete, destroy, expose, focus change and resize
1531 * events still get sent to the event widget because
1532 * 1) these events have no meaning for the grabbing widget
1533 * and 2) redirecting these events to the grabbing widget
1534 * could cause the display to be messed up.
1536 * Drag events are also not redirected, since it isn't
1537 * clear what the semantics of that would be.
1539 switch (event->type)
1545 g_object_ref (event_widget);
1546 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1547 !gtk_widget_event (event_widget, event))
1548 gtk_widget_destroy (event_widget);
1549 g_object_unref (event_widget);
1553 /* Unexpected GDK_DESTROY from the outside, ignore for
1554 * child windows, handle like a GDK_DELETE for toplevels
1556 if (!event_widget->parent)
1558 g_object_ref (event_widget);
1559 if (!gtk_widget_event (event_widget, event) &&
1560 GTK_WIDGET_REALIZED (event_widget))
1561 gtk_widget_destroy (event_widget);
1562 g_object_unref (event_widget);
1567 if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
1569 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1570 gtk_widget_send_expose (event_widget, event);
1571 gdk_window_end_paint (event->any.window);
1575 /* The app may paint with a previously allocated cairo_t,
1576 which will draw directly to the window. We can't catch cairo
1577 drap operatoins to automatically flush the window, thus we
1578 need to explicitly flush any outstanding moves or double
1580 gdk_window_flush (event->any.window);
1581 gtk_widget_send_expose (event_widget, event);
1585 case GDK_PROPERTY_NOTIFY:
1587 case GDK_FOCUS_CHANGE:
1591 case GDK_SELECTION_CLEAR:
1592 case GDK_SELECTION_REQUEST:
1593 case GDK_SELECTION_NOTIFY:
1594 case GDK_CLIENT_EVENT:
1595 case GDK_VISIBILITY_NOTIFY:
1596 case GDK_WINDOW_STATE:
1597 case GDK_GRAB_BROKEN:
1599 gtk_widget_event (event_widget, event);
1603 case GDK_BUTTON_PRESS:
1604 case GDK_2BUTTON_PRESS:
1605 case GDK_3BUTTON_PRESS:
1606 gtk_propagate_event (grab_widget, event);
1610 case GDK_KEY_RELEASE:
1613 if (gtk_invoke_key_snoopers (grab_widget, event))
1616 /* else fall through */
1617 case GDK_MOTION_NOTIFY:
1618 case GDK_BUTTON_RELEASE:
1619 case GDK_PROXIMITY_IN:
1620 case GDK_PROXIMITY_OUT:
1621 gtk_propagate_event (grab_widget, event);
1624 case GDK_ENTER_NOTIFY:
1625 GTK_PRIVATE_SET_FLAG (event_widget, GTK_HAS_POINTER);
1626 _gtk_widget_set_pointer_window (event_widget, event->any.window);
1627 if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1628 gtk_widget_event (grab_widget, event);
1631 case GDK_LEAVE_NOTIFY:
1632 GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_HAS_POINTER);
1633 if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1634 gtk_widget_event (grab_widget, event);
1637 case GDK_DRAG_STATUS:
1638 case GDK_DROP_FINISHED:
1639 _gtk_drag_source_handle_event (event_widget, event);
1641 case GDK_DRAG_ENTER:
1642 case GDK_DRAG_LEAVE:
1643 case GDK_DRAG_MOTION:
1644 case GDK_DROP_START:
1645 _gtk_drag_dest_handle_event (event_widget, event);
1648 g_assert_not_reached ();
1652 if (event->type == GDK_ENTER_NOTIFY
1653 || event->type == GDK_LEAVE_NOTIFY
1654 || event->type == GDK_BUTTON_PRESS
1655 || event->type == GDK_2BUTTON_PRESS
1656 || event->type == GDK_3BUTTON_PRESS
1657 || event->type == GDK_KEY_PRESS
1658 || event->type == GDK_DRAG_ENTER
1659 || event->type == GDK_GRAB_BROKEN
1660 || event->type == GDK_MOTION_NOTIFY
1661 || event->type == GDK_SCROLL)
1663 _gtk_tooltip_handle_event (event);
1666 tmp_list = current_events;
1667 current_events = g_list_remove_link (current_events, tmp_list);
1668 g_list_free_1 (tmp_list);
1670 if (rewritten_event)
1671 gdk_event_free (rewritten_event);
1686 static GtkWindowGroup *
1687 gtk_main_get_window_group (GtkWidget *widget)
1689 GtkWidget *toplevel = NULL;
1692 toplevel = gtk_widget_get_toplevel (widget);
1694 if (GTK_IS_WINDOW (toplevel))
1695 return gtk_window_get_group (GTK_WINDOW (toplevel));
1697 return gtk_window_get_group (NULL);
1702 GtkWidget *old_grab_widget;
1703 GtkWidget *new_grab_widget;
1704 gboolean was_grabbed;
1705 gboolean is_grabbed;
1710 gtk_grab_notify_foreach (GtkWidget *child,
1714 GrabNotifyInfo *info = data;
1716 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1718 was_grabbed = info->was_grabbed;
1719 is_grabbed = info->is_grabbed;
1721 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1722 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1724 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1725 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1727 g_object_ref (child);
1729 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1730 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1734 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1735 if (!was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1736 && GTK_WIDGET_IS_SENSITIVE (child))
1737 _gtk_widget_synthesize_crossing (child, info->new_grab_widget,
1738 GDK_CROSSING_GTK_GRAB);
1742 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1743 if (was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1744 && GTK_WIDGET_IS_SENSITIVE (child))
1745 _gtk_widget_synthesize_crossing (info->old_grab_widget, child,
1746 info->from_grab ? GDK_CROSSING_GTK_GRAB
1747 : GDK_CROSSING_GTK_UNGRAB);
1750 if (was_shadowed != is_shadowed)
1751 _gtk_widget_grab_notify (child, was_shadowed);
1753 g_object_unref (child);
1755 info->was_grabbed = was_grabbed;
1756 info->is_grabbed = is_grabbed;
1760 gtk_grab_notify (GtkWindowGroup *group,
1761 GtkWidget *old_grab_widget,
1762 GtkWidget *new_grab_widget,
1766 GrabNotifyInfo info;
1768 if (old_grab_widget == new_grab_widget)
1771 info.old_grab_widget = old_grab_widget;
1772 info.new_grab_widget = new_grab_widget;
1773 info.from_grab = from_grab;
1775 g_object_ref (group);
1777 toplevels = gtk_window_list_toplevels ();
1778 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1782 GtkWindow *toplevel = toplevels->data;
1783 toplevels = g_list_delete_link (toplevels, toplevels);
1785 info.was_grabbed = FALSE;
1786 info.is_grabbed = FALSE;
1788 if (group == gtk_window_get_group (toplevel))
1789 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1790 g_object_unref (toplevel);
1793 g_object_unref (group);
1797 gtk_grab_add (GtkWidget *widget)
1799 GtkWindowGroup *group;
1800 GtkWidget *old_grab_widget;
1802 g_return_if_fail (widget != NULL);
1804 if (!GTK_WIDGET_HAS_GRAB (widget) && GTK_WIDGET_IS_SENSITIVE (widget))
1806 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
1808 group = gtk_main_get_window_group (widget);
1811 old_grab_widget = (GtkWidget *)group->grabs->data;
1813 old_grab_widget = NULL;
1815 g_object_ref (widget);
1816 group->grabs = g_slist_prepend (group->grabs, widget);
1818 gtk_grab_notify (group, old_grab_widget, widget, TRUE);
1823 gtk_grab_get_current (void)
1825 GtkWindowGroup *group;
1827 group = gtk_main_get_window_group (NULL);
1830 return GTK_WIDGET (group->grabs->data);
1835 gtk_grab_remove (GtkWidget *widget)
1837 GtkWindowGroup *group;
1838 GtkWidget *new_grab_widget;
1840 g_return_if_fail (widget != NULL);
1842 if (GTK_WIDGET_HAS_GRAB (widget))
1844 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
1846 group = gtk_main_get_window_group (widget);
1847 group->grabs = g_slist_remove (group->grabs, widget);
1850 new_grab_widget = (GtkWidget *)group->grabs->data;
1852 new_grab_widget = NULL;
1854 gtk_grab_notify (group, widget, new_grab_widget, FALSE);
1856 g_object_unref (widget);
1861 gtk_init_add (GtkFunction function,
1864 GtkInitFunction *init;
1866 init = g_new (GtkInitFunction, 1);
1867 init->function = function;
1870 init_functions = g_list_prepend (init_functions, init);
1874 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
1877 GtkKeySnooperData *data;
1878 static guint snooper_id = 1;
1880 g_return_val_if_fail (snooper != NULL, 0);
1882 data = g_new (GtkKeySnooperData, 1);
1883 data->func = snooper;
1884 data->func_data = func_data;
1885 data->id = snooper_id++;
1886 key_snoopers = g_slist_prepend (key_snoopers, data);
1892 gtk_key_snooper_remove (guint snooper_id)
1894 GtkKeySnooperData *data = NULL;
1897 slist = key_snoopers;
1901 if (data->id == snooper_id)
1904 slist = slist->next;
1909 key_snoopers = g_slist_remove (key_snoopers, data);
1915 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
1919 gint return_val = FALSE;
1921 slist = key_snoopers;
1922 while (slist && !return_val)
1924 GtkKeySnooperData *data;
1927 slist = slist->next;
1928 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
1935 gtk_quit_add_full (guint main_level,
1936 GtkFunction function,
1937 GtkCallbackMarshal marshal,
1939 GDestroyNotify destroy)
1941 static guint quit_id = 1;
1942 GtkQuitFunction *quitf;
1944 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
1946 quitf = g_slice_new (GtkQuitFunction);
1948 quitf->id = quit_id++;
1949 quitf->main_level = main_level;
1950 quitf->function = function;
1951 quitf->marshal = marshal;
1953 quitf->destroy = destroy;
1955 quit_functions = g_list_prepend (quit_functions, quitf);
1961 gtk_quit_destroy (GtkQuitFunction *quitf)
1964 quitf->destroy (quitf->data);
1965 g_slice_free (GtkQuitFunction, quitf);
1969 gtk_quit_destructor (GtkObject **object_p)
1972 gtk_object_destroy (*object_p);
1979 gtk_quit_add_destroy (guint main_level,
1982 GtkObject **object_p;
1984 g_return_if_fail (main_level > 0);
1985 g_return_if_fail (GTK_IS_OBJECT (object));
1987 object_p = g_new (GtkObject*, 1);
1989 g_signal_connect (object,
1991 G_CALLBACK (gtk_widget_destroyed),
1993 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
1997 gtk_quit_add (guint main_level,
1998 GtkFunction function,
2001 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2005 gtk_quit_remove (guint id)
2007 GtkQuitFunction *quitf;
2010 tmp_list = quit_functions;
2013 quitf = tmp_list->data;
2015 if (quitf->id == id)
2017 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2018 g_list_free (tmp_list);
2019 gtk_quit_destroy (quitf);
2024 tmp_list = tmp_list->next;
2029 gtk_quit_remove_by_data (gpointer data)
2031 GtkQuitFunction *quitf;
2034 tmp_list = quit_functions;
2037 quitf = tmp_list->data;
2039 if (quitf->data == data)
2041 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2042 g_list_free (tmp_list);
2043 gtk_quit_destroy (quitf);
2048 tmp_list = tmp_list->next;
2053 gtk_timeout_add_full (guint32 interval,
2054 GtkFunction function,
2055 GtkCallbackMarshal marshal,
2057 GDestroyNotify destroy)
2061 GtkClosure *closure;
2063 closure = g_new (GtkClosure, 1);
2064 closure->marshal = marshal;
2065 closure->data = data;
2066 closure->destroy = destroy;
2068 return g_timeout_add_full (0, interval,
2069 gtk_invoke_idle_timeout,
2071 gtk_destroy_closure);
2074 return g_timeout_add_full (0, interval, function, data, destroy);
2078 gtk_timeout_add (guint32 interval,
2079 GtkFunction function,
2082 return g_timeout_add_full (0, interval, function, data, NULL);
2086 gtk_timeout_remove (guint tag)
2088 g_source_remove (tag);
2092 gtk_idle_add_full (gint priority,
2093 GtkFunction function,
2094 GtkCallbackMarshal marshal,
2096 GDestroyNotify destroy)
2100 GtkClosure *closure;
2102 closure = g_new (GtkClosure, 1);
2103 closure->marshal = marshal;
2104 closure->data = data;
2105 closure->destroy = destroy;
2107 return g_idle_add_full (priority,
2108 gtk_invoke_idle_timeout,
2110 gtk_destroy_closure);
2113 return g_idle_add_full (priority, function, data, destroy);
2117 gtk_idle_add (GtkFunction function,
2120 return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
2124 gtk_idle_add_priority (gint priority,
2125 GtkFunction function,
2128 return g_idle_add_full (priority, function, data, NULL);
2132 gtk_idle_remove (guint tag)
2134 g_source_remove (tag);
2138 gtk_idle_remove_by_data (gpointer data)
2140 if (!g_idle_remove_by_data (data))
2141 g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
2145 gtk_input_add_full (gint source,
2146 GdkInputCondition condition,
2147 GdkInputFunction function,
2148 GtkCallbackMarshal marshal,
2150 GDestroyNotify destroy)
2154 GtkClosure *closure;
2156 closure = g_new (GtkClosure, 1);
2157 closure->marshal = marshal;
2158 closure->data = data;
2159 closure->destroy = destroy;
2161 return gdk_input_add_full (source,
2163 (GdkInputFunction) gtk_invoke_input,
2165 (GDestroyNotify) gtk_destroy_closure);
2168 return gdk_input_add_full (source, condition, function, data, destroy);
2172 gtk_input_remove (guint tag)
2174 g_source_remove (tag);
2178 gtk_destroy_closure (gpointer data)
2180 GtkClosure *closure = data;
2182 if (closure->destroy)
2183 (closure->destroy) (closure->data);
2188 gtk_invoke_idle_timeout (gpointer data)
2190 GtkClosure *closure = data;
2193 gint ret_val = FALSE;
2194 args[0].name = NULL;
2195 args[0].type = G_TYPE_BOOLEAN;
2196 args[0].d.pointer_data = &ret_val;
2197 closure->marshal (NULL, closure->data, 0, args);
2202 gtk_invoke_input (gpointer data,
2204 GdkInputCondition condition)
2206 GtkClosure *closure = data;
2209 args[0].type = G_TYPE_INT;
2210 args[0].name = NULL;
2211 GTK_VALUE_INT (args[0]) = source;
2212 args[1].type = GDK_TYPE_INPUT_CONDITION;
2213 args[1].name = NULL;
2214 GTK_VALUE_FLAGS (args[1]) = condition;
2215 args[2].type = G_TYPE_NONE;
2216 args[2].name = NULL;
2218 closure->marshal (NULL, closure->data, 2, args);
2222 * gtk_get_current_event:
2224 * Obtains a copy of the event currently being processed by GTK+. For
2225 * example, if you get a "clicked" signal from #GtkButton, the current
2226 * event will be the #GdkEventButton that triggered the "clicked"
2227 * signal. The returned event must be freed with gdk_event_free().
2228 * If there is no current event, the function returns %NULL.
2230 * Return value: a copy of the current event, or %NULL if no current event.
2233 gtk_get_current_event (void)
2236 return gdk_event_copy (current_events->data);
2242 * gtk_get_current_event_time:
2244 * If there is a current event and it has a timestamp, return that
2245 * timestamp, otherwise return %GDK_CURRENT_TIME.
2247 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2250 gtk_get_current_event_time (void)
2253 return gdk_event_get_time (current_events->data);
2255 return GDK_CURRENT_TIME;
2259 * gtk_get_current_event_state:
2260 * @state: a location to store the state of the current event
2262 * If there is a current event and it has a state field, place
2263 * that state field in @state and return %TRUE, otherwise return
2266 * Return value: %TRUE if there was a current event and it had a state field
2269 gtk_get_current_event_state (GdkModifierType *state)
2271 g_return_val_if_fail (state != NULL, FALSE);
2274 return gdk_event_get_state (current_events->data, state);
2283 * gtk_get_event_widget:
2284 * @event: a #GdkEvent
2286 * If @event is %NULL or the event was not associated with any widget,
2287 * returns %NULL, otherwise returns the widget that received the event
2290 * Return value: the widget that originally received @event, or %NULL
2293 gtk_get_event_widget (GdkEvent *event)
2296 gpointer widget_ptr;
2299 if (event && event->any.window &&
2300 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2302 gdk_window_get_user_data (event->any.window, &widget_ptr);
2303 widget = widget_ptr;
2310 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2312 if (!quitf->marshal)
2313 return quitf->function (quitf->data);
2317 gint ret_val = FALSE;
2319 args[0].name = NULL;
2320 args[0].type = G_TYPE_BOOLEAN;
2321 args[0].d.pointer_data = &ret_val;
2322 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2330 * gtk_propagate_event:
2331 * @widget: a #GtkWidget
2334 * Sends an event to a widget, propagating the event to parent widgets
2335 * if the event remains unhandled. Events received by GTK+ from GDK
2336 * normally begin in gtk_main_do_event(). Depending on the type of
2337 * event, existence of modal dialogs, grabs, etc., the event may be
2338 * propagated; if so, this function is used. gtk_propagate_event()
2339 * calls gtk_widget_event() on each widget it decides to send the
2340 * event to. So gtk_widget_event() is the lowest-level function; it
2341 * simply emits the "event" and possibly an event-specific signal on a
2342 * widget. gtk_propagate_event() is a bit higher-level, and
2343 * gtk_main_do_event() is the highest level.
2345 * All that said, you most likely don't want to use any of these
2346 * functions; synthesizing events is rarely needed. Consider asking on
2347 * the mailing list for better ways to achieve your goals. For
2348 * example, use gdk_window_invalidate_rect() or
2349 * gtk_widget_queue_draw() instead of making up expose events.
2353 gtk_propagate_event (GtkWidget *widget,
2358 g_return_if_fail (GTK_IS_WIDGET (widget));
2359 g_return_if_fail (event != NULL);
2361 handled_event = FALSE;
2363 g_object_ref (widget);
2365 if ((event->type == GDK_KEY_PRESS) ||
2366 (event->type == GDK_KEY_RELEASE))
2368 /* Only send key events within Window widgets to the Window
2369 * The Window widget will in turn pass the
2370 * key event on to the currently focused widget
2375 window = gtk_widget_get_toplevel (widget);
2376 if (GTK_IS_WINDOW (window))
2378 /* If there is a grab within the window, give the grab widget
2379 * a first crack at the key event
2381 if (widget != window && GTK_WIDGET_HAS_GRAB (widget))
2382 handled_event = gtk_widget_event (widget, event);
2386 window = gtk_widget_get_toplevel (widget);
2387 if (GTK_IS_WINDOW (window))
2389 if (GTK_WIDGET_IS_SENSITIVE (window))
2390 gtk_widget_event (window, event);
2394 handled_event = TRUE; /* don't send to widget */
2398 /* Other events get propagated up the widget tree
2399 * so that parents can see the button and motion
2400 * events of the children.
2408 /* Scroll events are special cased here because it
2409 * feels wrong when scrolling a GtkViewport, say,
2410 * to have children of the viewport eat the scroll
2413 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2414 handled_event = event->type != GDK_SCROLL;
2416 handled_event = gtk_widget_event (widget, event);
2418 tmp = widget->parent;
2419 g_object_unref (widget);
2423 if (!handled_event && widget)
2424 g_object_ref (widget);
2430 g_object_unref (widget);
2435 gtk_error (gchar *str)
2441 gtk_warning (gchar *str)
2447 gtk_message (gchar *str)
2453 gtk_print (gchar *str)
2455 static GtkWidget *window = NULL;
2456 static GtkWidget *text;
2457 static int level = 0;
2461 GtkWidget *hscrollbar;
2462 GtkWidget *vscrollbar;
2463 GtkWidget *separator;
2468 fputs (str, stdout);
2475 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2477 gtk_signal_connect (GTK_OBJECT (window), "destroy",
2478 G_CALLBACK (gtk_widget_destroyed),
2481 gtk_window_set_title (GTK_WINDOW (window), "Messages");
2483 box1 = gtk_vbox_new (FALSE, 0);
2484 gtk_container_add (GTK_CONTAINER (window), box1);
2485 gtk_widget_show (box1);
2488 box2 = gtk_vbox_new (FALSE, 10);
2489 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2490 gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2491 gtk_widget_show (box2);
2494 table = gtk_table_new (2, 2, FALSE);
2495 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2496 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2497 gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2498 gtk_widget_show (table);
2500 text = gtk_text_new (NULL, NULL);
2501 gtk_text_set_editable (GTK_TEXT (text), FALSE);
2502 gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2503 gtk_widget_show (text);
2504 gtk_widget_realize (text);
2506 hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2507 gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2508 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2509 gtk_widget_show (hscrollbar);
2511 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2512 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2513 GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2514 gtk_widget_show (vscrollbar);
2516 separator = gtk_hseparator_new ();
2517 gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2518 gtk_widget_show (separator);
2521 box2 = gtk_vbox_new (FALSE, 10);
2522 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2523 gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2524 gtk_widget_show (box2);
2527 button = gtk_button_new_with_label ("close");
2528 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2529 G_CALLBACK (gtk_widget_hide),
2530 GTK_OBJECT (window));
2531 gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2532 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2533 gtk_widget_grab_default (button);
2534 gtk_widget_show (button);
2538 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2541 if (!GTK_WIDGET_VISIBLE (window))
2542 gtk_widget_show (window);
2547 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2548 GValue *return_accu,
2549 const GValue *handler_return,
2552 gboolean continue_emission;
2553 gboolean signal_handled;
2555 signal_handled = g_value_get_boolean (handler_return);
2556 g_value_set_boolean (return_accu, signal_handled);
2557 continue_emission = !signal_handled;
2559 return continue_emission;
2562 #define __GTK_MAIN_C__
2563 #include "gtkaliasdef.c"