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/gdkkeysyms.h"
69 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
73 static HMODULE gtk_dll;
76 DllMain (HINSTANCE hinstDLL,
82 case DLL_PROCESS_ATTACH:
83 gtk_dll = (HMODULE) hinstDLL;
90 /* These here before inclusion of gtkprivate.h so that the original
91 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
95 _gtk_get_libdir (void)
97 static char *gtk_libdir = NULL;
98 if (gtk_libdir == NULL)
100 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
101 gchar *slash = strrchr (root, '\\');
102 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
103 gtk_libdir = GTK_LIBDIR;
105 gtk_libdir = g_build_filename (root, "lib", NULL);
113 _gtk_get_localedir (void)
115 static char *gtk_localedir = NULL;
116 if (gtk_localedir == NULL)
121 /* GTK_LOCALEDIR ends in either /lib/locale or
122 * /share/locale. Scan for that slash.
124 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
130 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
131 temp = g_build_filename (root, p, NULL);
134 /* gtk_localedir is passed to bindtextdomain() which isn't
137 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
140 return gtk_localedir;
145 #include "gtkprivate.h"
147 /* Private type definitions
149 typedef struct _GtkInitFunction GtkInitFunction;
150 typedef struct _GtkQuitFunction GtkQuitFunction;
151 typedef struct _GtkClosure GtkClosure;
152 typedef struct _GtkKeySnooperData GtkKeySnooperData;
154 struct _GtkInitFunction
156 GtkFunction function;
160 struct _GtkQuitFunction
164 GtkCallbackMarshal marshal;
165 GtkFunction function;
167 GDestroyNotify destroy;
172 GtkCallbackMarshal marshal;
174 GDestroyNotify destroy;
177 struct _GtkKeySnooperData
179 GtkKeySnoopFunc func;
184 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
185 static void gtk_quit_destroy (GtkQuitFunction *quitf);
186 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
190 static void gtk_error (gchar *str);
191 static void gtk_warning (gchar *str);
192 static void gtk_message (gchar *str);
193 static void gtk_print (gchar *str);
196 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
198 const guint gtk_major_version = GTK_MAJOR_VERSION;
199 const guint gtk_minor_version = GTK_MINOR_VERSION;
200 const guint gtk_micro_version = GTK_MICRO_VERSION;
201 const guint gtk_binary_age = GTK_BINARY_AGE;
202 const guint gtk_interface_age = GTK_INTERFACE_AGE;
204 static guint gtk_main_loop_level = 0;
205 static gint pre_initialized = FALSE;
206 static gint gtk_initialized = FALSE;
207 static GList *current_events = NULL;
209 static GSList *main_loops = NULL; /* stack of currently executing main loops */
211 static GList *init_functions = NULL; /* A list of init functions.
213 static GList *quit_functions = NULL; /* A list of quit functions.
215 static GSList *key_snoopers = NULL;
217 guint gtk_debug_flags = 0; /* Global GTK debug flag */
219 #ifdef G_ENABLE_DEBUG
220 static const GDebugKey gtk_debug_keys[] = {
221 {"misc", GTK_DEBUG_MISC},
222 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
223 {"text", GTK_DEBUG_TEXT},
224 {"tree", GTK_DEBUG_TREE},
225 {"updates", GTK_DEBUG_UPDATES},
226 {"keybindings", GTK_DEBUG_KEYBINDINGS},
227 {"multihead", GTK_DEBUG_MULTIHEAD},
228 {"modules", GTK_DEBUG_MODULES},
229 {"geometry", GTK_DEBUG_GEOMETRY},
230 {"icontheme", GTK_DEBUG_ICONTHEME},
231 {"printing", GTK_DEBUG_PRINTING},
232 {"builder", GTK_DEBUG_BUILDER},
233 {"extended-layout", GTK_DEBUG_EXTENDED_LAYOUT},
235 #endif /* G_ENABLE_DEBUG */
239 * @required_major: the required major version.
240 * @required_minor: the required minor version.
241 * @required_micro: the required micro version.
243 * Checks that the GTK+ library in use is compatible with the
244 * given version. Generally you would pass in the constants
245 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
246 * as the three arguments to this function; that produces
247 * a check that the library in use is compatible with
248 * the version of GTK+ the application or module was compiled
251 * Compatibility is defined by two things: first the version
252 * of the running library is newer than the version
253 * @required_major.required_minor.@required_micro. Second
254 * the running library must be binary compatible with the
255 * version @required_major.required_minor.@required_micro
256 * (same major version.)
258 * This function is primarily for GTK+ modules; the module
259 * can call this function to check that it wasn't loaded
260 * into an incompatible version of GTK+. However, such a
261 * a check isn't completely reliable, since the module may be
262 * linked against an old version of GTK+ and calling the
263 * old version of gtk_check_version(), but still get loaded
264 * into an application using a newer version of GTK+.
266 * Return value: %NULL if the GTK+ library is compatible with the
267 * given version, or a string describing the version mismatch.
268 * The returned string is owned by GTK+ and should not be modified
272 gtk_check_version (guint required_major,
273 guint required_minor,
274 guint required_micro)
276 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
277 gint required_effective_micro = 100 * required_minor + required_micro;
279 if (required_major > GTK_MAJOR_VERSION)
280 return "Gtk+ version too old (major mismatch)";
281 if (required_major < GTK_MAJOR_VERSION)
282 return "Gtk+ version too new (major mismatch)";
283 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
284 return "Gtk+ version too new (micro mismatch)";
285 if (required_effective_micro > gtk_effective_micro)
286 return "Gtk+ version too old (micro mismatch)";
290 /* This checks to see if the process is running suid or sgid
291 * at the current time. If so, we don't allow GTK+ to be initialized.
292 * This is meant to be a mild check - we only error out if we
293 * can prove the programmer is doing something wrong, not if
294 * they could be doing something wrong. For this reason, we
295 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
300 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
302 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
303 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
305 #ifdef HAVE_GETRESUID
306 /* These aren't in the header files, so we prototype them here.
308 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
309 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
311 if (getresuid (&ruid, &euid, &suid) != 0 ||
312 getresgid (&rgid, &egid, &sgid) != 0)
313 #endif /* HAVE_GETRESUID */
315 suid = ruid = getuid ();
316 sgid = rgid = getgid ();
321 if (ruid != euid || ruid != suid ||
322 rgid != egid || rgid != sgid)
324 g_warning ("This process is currently running setuid or setgid.\n"
325 "This is not a supported use of GTK+. You must create a helper\n"
326 "program instead. For further details, see:\n\n"
327 " http://www.gtk.org/setuid.html\n\n"
328 "Refusing to initialize GTK+.");
338 _gtk_get_datadir (void)
340 static char *gtk_datadir = NULL;
341 if (gtk_datadir == NULL)
343 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
344 gtk_datadir = g_build_filename (root, "share", NULL);
352 _gtk_get_sysconfdir (void)
354 static char *gtk_sysconfdir = NULL;
355 if (gtk_sysconfdir == NULL)
357 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
358 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
362 return gtk_sysconfdir;
366 _gtk_get_data_prefix (void)
368 static char *gtk_data_prefix = NULL;
369 if (gtk_data_prefix == NULL)
370 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
372 return gtk_data_prefix;
375 #endif /* G_OS_WIN32 */
377 static gboolean do_setlocale = TRUE;
380 * gtk_disable_setlocale:
382 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
383 * gtk_parse_args() from automatically
384 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
385 * want to use this function if you wanted to set the locale for
386 * your program to something other than the user's locale, or if
387 * you wanted to set different values for different locale categories.
389 * Most programs should not need to call this function.
392 gtk_disable_setlocale (void)
395 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
397 do_setlocale = FALSE;
400 #ifdef G_PLATFORM_WIN32
401 #undef gtk_init_check
404 static GString *gtk_modules_string = NULL;
405 static gboolean g_fatal_warnings = FALSE;
407 #ifdef G_ENABLE_DEBUG
409 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
411 gtk_debug_flags |= g_parse_debug_string (value,
413 G_N_ELEMENTS (gtk_debug_keys));
419 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
421 gtk_debug_flags &= ~g_parse_debug_string (value,
423 G_N_ELEMENTS (gtk_debug_keys));
427 #endif /* G_ENABLE_DEBUG */
430 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
434 if (gtk_modules_string)
435 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
437 gtk_modules_string = g_string_new (NULL);
439 g_string_append (gtk_modules_string, value);
445 static const GOptionEntry gtk_args[] = {
446 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
447 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
448 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
449 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
450 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
451 #ifdef G_ENABLE_DEBUG
452 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
453 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
454 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
455 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
456 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
457 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
464 static char *iso639_to_check = NULL;
465 static char *iso3166_to_check = NULL;
466 static char *script_to_check = NULL;
467 static gboolean setlocale_called = FALSE;
470 enum_locale_proc (LPTSTR locale)
478 lcid = strtoul (locale, &endptr, 16);
479 if (*endptr == '\0' &&
480 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
481 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
483 if (strcmp (iso639, iso639_to_check) == 0 &&
484 ((iso3166_to_check != NULL &&
485 strcmp (iso3166, iso3166_to_check) == 0) ||
486 (iso3166_to_check == NULL &&
487 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
489 char language[100], country[100];
492 if (script_to_check != NULL)
494 /* If lcid is the "other" script for this language,
495 * return TRUE, i.e. continue looking.
497 if (strcmp (script_to_check, "Latn") == 0)
499 switch (LANGIDFROMLCID (lcid))
501 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
503 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
505 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
507 case MAKELANGID (LANG_SERBIAN, 0x07):
508 /* Serbian in Bosnia and Herzegovina, Cyrillic */
512 else if (strcmp (script_to_check, "Cyrl") == 0)
514 switch (LANGIDFROMLCID (lcid))
516 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
518 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
520 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
522 case MAKELANGID (LANG_SERBIAN, 0x06):
523 /* Serbian in Bosnia and Herzegovina, Latin */
529 SetThreadLocale (lcid);
531 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
532 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
534 strcpy (locale, language);
535 strcat (locale, "_");
536 strcat (locale, country);
538 if (setlocale (LC_ALL, locale) != NULL)
539 setlocale_called = TRUE;
552 setlocale_initialization (void)
554 static gboolean initialized = FALSE;
563 /* If some of the POSIXish environment variables are set, set
564 * the Win32 thread locale correspondingly.
566 char *p = getenv ("LC_ALL");
573 if (strcmp (p, "C") == 0)
574 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
577 /* Check if one of the supported locales match the
578 * environment variable. If so, use that locale.
581 iso3166_to_check = strchr (iso639_to_check, '_');
582 if (iso3166_to_check != NULL)
584 *iso3166_to_check++ = '\0';
586 script_to_check = strchr (iso3166_to_check, '@');
587 if (script_to_check != NULL)
588 *script_to_check++ = '\0';
590 /* Handle special cases. */
592 /* The standard code for Serbia and Montenegro was
593 * "CS", but MSFT uses for some reason "SP". By now
594 * (October 2006), SP has split into two, "RS" and
595 * "ME", but don't bother trying to handle those
596 * yet. Do handle the even older "YU", though.
598 if (strcmp (iso3166_to_check, "CS") == 0 ||
599 strcmp (iso3166_to_check, "YU") == 0)
600 iso3166_to_check = "SP";
604 script_to_check = strchr (iso639_to_check, '@');
605 if (script_to_check != NULL)
606 *script_to_check++ = '\0';
607 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
608 if (strcmp (iso639_to_check, "sr") == 0)
609 iso3166_to_check = "SP";
612 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
616 if (!setlocale_called)
617 setlocale (LC_ALL, "");
619 if (!setlocale (LC_ALL, ""))
620 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
626 do_pre_parse_initialization (int *argc,
629 const gchar *env_string;
632 g_set_error_handler (gtk_error);
633 g_set_warning_handler (gtk_warning);
634 g_set_message_handler (gtk_message);
635 g_set_print_handler (gtk_print);
641 pre_initialized = TRUE;
643 gdk_pre_parse_libgtk_only ();
644 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
646 #ifdef G_ENABLE_DEBUG
647 env_string = g_getenv ("GTK_DEBUG");
648 if (env_string != NULL)
650 gtk_debug_flags = g_parse_debug_string (env_string,
652 G_N_ELEMENTS (gtk_debug_keys));
655 #endif /* G_ENABLE_DEBUG */
657 env_string = g_getenv ("GTK_MODULES");
659 gtk_modules_string = g_string_new (env_string);
663 gettext_initialization (void)
665 setlocale_initialization ();
668 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
669 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
670 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
671 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
672 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
678 do_post_parse_initialization (int *argc,
684 gettext_initialization ();
687 signal (SIGPIPE, SIG_IGN);
690 if (g_fatal_warnings)
692 GLogLevelFlags fatal_mask;
694 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
695 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
696 g_log_set_always_fatal (fatal_mask);
699 if (gtk_debug_flags & GTK_DEBUG_UPDATES)
700 gdk_window_set_debug_updates (TRUE);
703 /* Translate to default:RTL if you want your widgets
704 * to be RTL, otherwise translate to default:LTR.
705 * Do *not* translate it to "predefinito:LTR", if it
706 * it isn't default:LTR or default:RTL it will not work
708 char *e = _("default:LTR");
709 if (strcmp (e, "default:RTL")==0)
710 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
711 else if (strcmp (e, "default:LTR"))
712 g_warning ("Whoever translated default:LTR did so wrongly.\n");
715 /* do what the call to gtk_type_init() used to do */
718 _gtk_accel_map_init ();
721 /* Set the 'initialized' flag.
723 gtk_initialized = TRUE;
725 /* load gtk modules */
726 if (gtk_modules_string)
728 _gtk_modules_init (argc, argv, gtk_modules_string->str);
729 g_string_free (gtk_modules_string, TRUE);
733 _gtk_modules_init (argc, argv, NULL);
740 gboolean open_default_display;
744 pre_parse_hook (GOptionContext *context,
749 do_pre_parse_initialization (NULL, NULL);
755 post_parse_hook (GOptionContext *context,
760 OptionGroupInfo *info = data;
763 do_post_parse_initialization (NULL, NULL);
765 if (info->open_default_display)
767 if (gdk_display_open_default_libgtk_only () == NULL)
769 const char *display_name = gdk_get_display_arg_name ();
772 G_OPTION_ERROR_FAILED,
773 _("Cannot open display: %s"),
774 display_name ? display_name : "" );
785 * gtk_get_option_group:
786 * @open_default_display: whether to open the default display
787 * when parsing the commandline arguments
789 * Returns a #GOptionGroup for the commandline arguments recognized
790 * by GTK+ and GDK. You should add this group to your #GOptionContext
791 * with g_option_context_add_group(), if you are using
792 * g_option_context_parse() to parse your commandline arguments.
794 * Returns: a #GOptionGroup for the commandline arguments recognized
800 gtk_get_option_group (gboolean open_default_display)
803 OptionGroupInfo *info;
805 gettext_initialization ();
807 info = g_new0 (OptionGroupInfo, 1);
808 info->open_default_display = open_default_display;
810 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
811 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
813 gdk_add_option_entries_libgtk_only (group);
814 g_option_group_add_entries (group, gtk_args);
815 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
821 * gtk_init_with_args:
822 * @argc: a pointer to the number of command line arguments.
823 * @argv: a pointer to the array of command line arguments.
824 * @parameter_string: a string which is displayed in
825 * the first line of <option>--help</option> output, after
826 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
827 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
828 * describing the options of your program
829 * @translation_domain: a translation domain to use for translating
830 * the <option>--help</option> output for the options in @entries
831 * with gettext(), or %NULL
832 * @error: a return location for errors
834 * This function does the same work as gtk_init_check().
835 * Additionally, it allows you to add your own commandline options,
836 * and it automatically generates nicely formatted
837 * <option>--help</option> output. Note that your program will
838 * be terminated after writing out the help output.
840 * Returns: %TRUE if the GUI has been successfully initialized,
846 gtk_init_with_args (int *argc,
848 const char *parameter_string,
849 GOptionEntry *entries,
850 const char *translation_domain,
853 GOptionContext *context;
854 GOptionGroup *gtk_group;
858 return gdk_display_open_default_libgtk_only () != NULL;
860 gettext_initialization ();
862 if (!check_setugid ())
865 gtk_group = gtk_get_option_group (TRUE);
867 context = g_option_context_new (parameter_string);
868 g_option_context_add_group (context, gtk_group);
871 g_option_context_add_main_entries (context, entries, translation_domain);
872 retval = g_option_context_parse (context, argc, argv, error);
874 g_option_context_free (context);
882 * @argc: (inout): a pointer to the number of command line arguments.
883 * @argv: (array) (inout): a pointer to the array of command line arguments.
885 * Parses command line arguments, and initializes global
886 * attributes of GTK+, but does not actually open a connection
887 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
889 * Any arguments used by GTK+ or GDK are removed from the array and
890 * @argc and @argv are updated accordingly.
892 * You shouldn't call this function explicitely if you are using
893 * gtk_init(), or gtk_init_check().
895 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
898 gtk_parse_args (int *argc,
901 GOptionContext *option_context;
902 GOptionGroup *gtk_group;
903 GError *error = NULL;
908 gettext_initialization ();
910 if (!check_setugid ())
913 option_context = g_option_context_new (NULL);
914 g_option_context_set_ignore_unknown_options (option_context, TRUE);
915 g_option_context_set_help_enabled (option_context, FALSE);
916 gtk_group = gtk_get_option_group (FALSE);
917 g_option_context_set_main_group (option_context, gtk_group);
918 if (!g_option_context_parse (option_context, argc, argv, &error))
920 g_warning ("%s", error->message);
921 g_error_free (error);
924 g_option_context_free (option_context);
929 #ifdef G_PLATFORM_WIN32
930 #undef gtk_init_check
935 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
936 * main() function. Changed if any arguments were handled.
937 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
938 * Any parameters understood by gtk_init() are stripped before return.
940 * This function does the same work as gtk_init() with only
941 * a single change: It does not terminate the program if the GUI can't be
942 * initialized. Instead it returns %FALSE on failure.
944 * This way the application can fall back to some other means of communication
945 * with the user - for example a curses or command line interface.
947 * Return value: %TRUE if the GUI has been successfully initialized,
951 gtk_init_check (int *argc,
954 if (!gtk_parse_args (argc, argv))
957 return gdk_display_open_default_libgtk_only () != NULL;
960 #ifdef G_PLATFORM_WIN32
966 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
967 * main() function. Changed if any arguments were handled.
968 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
969 * Any parameters understood by gtk_init() are stripped before return.
971 * Call this function before using any other GTK+ functions in your GUI
972 * applications. It will initialize everything needed to operate the
973 * toolkit and parses some standard command line options. @argc and
974 * @argv are adjusted accordingly so your own code will
975 * never see those standard arguments.
977 * Note that there are some alternative ways to initialize GTK+:
978 * if you are calling gtk_parse_args(), gtk_init_check(),
979 * gtk_init_with_args() or g_option_context_parse() with
980 * the option group returned by gtk_get_option_group(), you
981 * <emphasis>don't</emphasis> have to call gtk_init().
984 * This function will terminate your program if it was unable to initialize
985 * the GUI for some reason. If you want your program to fall back to a
986 * textual interface you want to call gtk_init_check() instead.
990 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
991 * during initialization, to ignore SIGPIPE signals, since these are
992 * almost never wanted in graphical applications. If you do need to
993 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
994 * but notice that other libraries (e.g. libdbus or gvfs) might do
999 gtk_init (int *argc, char ***argv)
1001 if (!gtk_init_check (argc, argv))
1003 const char *display_name_arg = gdk_get_display_arg_name ();
1004 if (display_name_arg == NULL)
1005 display_name_arg = getenv("DISPLAY");
1006 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1011 #ifdef G_PLATFORM_WIN32
1014 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1016 if (sizeof_GtkWindow != sizeof (GtkWindow))
1017 g_error ("Incompatible build!\n"
1018 "The code using GTK+ thinks GtkWindow is of different\n"
1019 "size than it actually is in this build of GTK+.\n"
1020 "On Windows, this probably means that you have compiled\n"
1021 "your code with gcc without the -mms-bitfields switch,\n"
1022 "or that you are using an unsupported compiler.");
1025 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1026 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1027 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1028 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1029 * -fnative-struct still matters. GtkBox is one such.
1032 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1034 if (sizeof_GtkBox != sizeof (GtkBox))
1035 g_error ("Incompatible build!\n"
1036 "The code using GTK+ thinks GtkBox is of different\n"
1037 "size than it actually is in this build of GTK+.\n"
1038 "On Windows, this probably means that you have compiled\n"
1039 "your code with gcc without the -mms-bitfields switch,\n"
1040 "or that you are using an unsupported compiler.");
1043 /* These two functions might get more checks added later, thus pass
1044 * in the number of extra args.
1047 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1049 check_sizeof_GtkWindow (sizeof_GtkWindow);
1050 if (num_checks >= 2)
1051 check_sizeof_GtkBox (sizeof_GtkBox);
1052 gtk_init (argc, argv);
1056 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1058 check_sizeof_GtkWindow (sizeof_GtkWindow);
1059 if (num_checks >= 2)
1060 check_sizeof_GtkBox (sizeof_GtkBox);
1061 return gtk_init_check (argc, argv);
1069 * Initializes internationalization support for GTK+. gtk_init()
1070 * automatically does this, so there is typically no point
1071 * in calling this function.
1073 * If you are calling this function because you changed the locale
1074 * after GTK+ is was initialized, then calling this function
1075 * may help a bit. (Note, however, that changing the locale
1076 * after GTK+ is initialized may produce inconsistent results and
1077 * is not really supported.)
1079 * In detail - sets the current locale according to the
1080 * program environment. This is the same as calling the C library function
1081 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1082 * locale specific setup of the windowing system used by GDK.
1084 * Returns: a string corresponding to the locale set, typically in the
1085 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1086 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1087 * result of the setlocale(); it is also used on other machines, such as
1088 * Windows, where the C library returns a different result. The string is
1089 * owned by GTK+ and should not be modified or freed.
1092 gtk_set_locale (void)
1094 return gdk_set_locale ();
1098 * _gtk_get_lc_ctype:
1100 * Return the Unix-style locale string for the language currently in
1101 * effect. On Unix systems, this is the return value from
1102 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1103 * affect this through the environment variables LC_ALL, LC_CTYPE or
1104 * LANG (checked in that order). The locale strings typically is in
1105 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1106 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1107 * Swedish as written in Finland or pt_BR for Portuguese as written in
1110 * On Windows, the C library doesn't use any such environment
1111 * variables, and setting them won't affect the behaviour of functions
1112 * like ctime(). The user sets the locale through the Regional Options
1113 * in the Control Panel. The C library (in the setlocale() function)
1114 * does not use country and language codes, but country and language
1115 * names spelled out in English.
1116 * However, this function does check the above environment
1117 * variables, and does return a Unix-style locale string based on
1118 * either said environment variables or the thread's current locale.
1120 * Return value: a dynamically allocated string, free with g_free().
1124 _gtk_get_lc_ctype (void)
1127 /* Somebody might try to set the locale for this process using the
1128 * LANG or LC_ environment variables. The Microsoft C library
1129 * doesn't know anything about them. You set the locale in the
1130 * Control Panel. Setting these env vars won't have any affect on
1131 * locale-dependent C library functions like ctime(). But just for
1132 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1133 * it easier to test GTK and Pango in various default languages, you
1134 * don't have to clickety-click in the Control Panel, you can simply
1135 * start the program with LC_ALL=something on the command line.)
1139 p = getenv ("LC_ALL");
1141 return g_strdup (p);
1143 p = getenv ("LC_CTYPE");
1145 return g_strdup (p);
1147 p = getenv ("LANG");
1149 return g_strdup (p);
1151 return g_win32_getlocale ();
1153 return g_strdup (setlocale (LC_CTYPE, NULL));
1158 * gtk_get_default_language:
1160 * Returns the #PangoLanguage for the default language currently in
1161 * effect. (Note that this can change over the life of an
1162 * application.) The default language is derived from the current
1163 * locale. It determines, for example, whether GTK+ uses the
1164 * right-to-left or left-to-right text direction.
1166 * This function is equivalent to pango_language_get_default(). See
1167 * that function for details.
1169 * Return value: the default language as a #PangoLanguage, must not be
1173 gtk_get_default_language (void)
1175 return pango_language_get_default ();
1183 GtkInitFunction *init;
1186 gtk_main_loop_level++;
1188 loop = g_main_loop_new (NULL, TRUE);
1189 main_loops = g_slist_prepend (main_loops, loop);
1191 tmp_list = functions = init_functions;
1192 init_functions = NULL;
1196 init = tmp_list->data;
1197 tmp_list = tmp_list->next;
1199 (* init->function) (init->data);
1202 g_list_free (functions);
1204 if (g_main_loop_is_running (main_loops->data))
1206 GDK_THREADS_LEAVE ();
1207 g_main_loop_run (loop);
1208 GDK_THREADS_ENTER ();
1214 GList *reinvoke_list = NULL;
1215 GtkQuitFunction *quitf;
1217 while (quit_functions)
1219 quitf = quit_functions->data;
1221 tmp_list = quit_functions;
1222 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1223 g_list_free_1 (tmp_list);
1225 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1226 gtk_quit_invoke_function (quitf))
1228 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1232 gtk_quit_destroy (quitf);
1239 work = g_list_last (reinvoke_list);
1241 quit_functions->prev = work;
1242 work->next = quit_functions;
1243 quit_functions = work;
1249 main_loops = g_slist_remove (main_loops, loop);
1251 g_main_loop_unref (loop);
1253 gtk_main_loop_level--;
1255 if (gtk_main_loop_level == 0)
1257 /* Try storing all clipboard data we have */
1258 _gtk_clipboard_store_all ();
1260 /* Synchronize the recent manager singleton */
1261 _gtk_recent_manager_sync ();
1266 gtk_main_level (void)
1268 return gtk_main_loop_level;
1272 gtk_main_quit (void)
1274 g_return_if_fail (main_loops != NULL);
1276 g_main_loop_quit (main_loops->data);
1280 gtk_events_pending (void)
1284 GDK_THREADS_LEAVE ();
1285 result = g_main_context_pending (NULL);
1286 GDK_THREADS_ENTER ();
1292 gtk_main_iteration (void)
1294 GDK_THREADS_LEAVE ();
1295 g_main_context_iteration (NULL, TRUE);
1296 GDK_THREADS_ENTER ();
1299 return !g_main_loop_is_running (main_loops->data);
1305 gtk_main_iteration_do (gboolean blocking)
1307 GDK_THREADS_LEAVE ();
1308 g_main_context_iteration (NULL, blocking);
1309 GDK_THREADS_ENTER ();
1312 return !g_main_loop_is_running (main_loops->data);
1317 /* private libgtk to libgdk interfaces
1319 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1321 GdkWindow **grab_window,
1322 gboolean *owner_events);
1325 rewrite_events_translate (GdkWindow *old_window,
1326 GdkWindow *new_window,
1330 gint old_origin_x, old_origin_y;
1331 gint new_origin_x, new_origin_y;
1333 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1334 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1336 *x += old_origin_x - new_origin_x;
1337 *y += old_origin_y - new_origin_y;
1341 rewrite_event_for_window (GdkEvent *event,
1342 GdkWindow *new_window)
1344 event = gdk_event_copy (event);
1346 switch (event->type)
1349 rewrite_events_translate (event->any.window,
1351 &event->scroll.x, &event->scroll.y);
1353 case GDK_BUTTON_PRESS:
1354 case GDK_2BUTTON_PRESS:
1355 case GDK_3BUTTON_PRESS:
1356 case GDK_BUTTON_RELEASE:
1357 rewrite_events_translate (event->any.window,
1359 &event->button.x, &event->button.y);
1361 case GDK_MOTION_NOTIFY:
1362 rewrite_events_translate (event->any.window,
1364 &event->motion.x, &event->motion.y);
1367 case GDK_KEY_RELEASE:
1368 case GDK_PROXIMITY_IN:
1369 case GDK_PROXIMITY_OUT:
1376 g_object_unref (event->any.window);
1377 event->any.window = g_object_ref (new_window);
1382 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1383 * then what X11 does is deliver the event normally if it was going to this
1384 * client, otherwise, delivers it in terms of the grab window. This function
1385 * rewrites events to the effect that events going to the same window group
1386 * are delivered normally, otherwise, the event is delivered in terms of the
1390 rewrite_event_for_grabs (GdkEvent *event)
1392 GdkWindow *grab_window;
1393 GtkWidget *event_widget, *grab_widget;
1394 gpointer grab_widget_ptr;
1395 gboolean owner_events;
1396 GdkDisplay *display;
1399 switch (event->type)
1402 case GDK_BUTTON_PRESS:
1403 case GDK_2BUTTON_PRESS:
1404 case GDK_3BUTTON_PRESS:
1405 case GDK_BUTTON_RELEASE:
1406 case GDK_MOTION_NOTIFY:
1407 case GDK_PROXIMITY_IN:
1408 case GDK_PROXIMITY_OUT:
1410 case GDK_KEY_RELEASE:
1411 display = gdk_drawable_get_display (event->any.window);
1412 device = gdk_event_get_device (event);
1414 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1422 event_widget = gtk_get_event_widget (event);
1423 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1424 grab_widget = grab_widget_ptr;
1427 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1428 return rewrite_event_for_window (event, grab_window);
1434 gtk_main_do_event (GdkEvent *event)
1436 GtkWidget *event_widget;
1437 GtkWidget *grab_widget = NULL;
1438 GtkWindowGroup *window_group;
1439 GdkEvent *rewritten_event = NULL;
1443 if (event->type == GDK_SETTING)
1445 _gtk_settings_handle_event (&event->setting);
1449 if (event->type == GDK_OWNER_CHANGE)
1451 _gtk_clipboard_handle_event (&event->owner_change);
1455 /* Find the widget which got the event. We store the widget
1456 * in the user_data field of GdkWindow's.
1457 * Ignore the event if we don't have a widget for it, except
1458 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1459 * Though this happens rarely, bogus events can occour
1460 * for e.g. destroyed GdkWindows.
1462 event_widget = gtk_get_event_widget (event);
1465 /* To handle selection INCR transactions, we select
1466 * PropertyNotify events on the requestor window and create
1467 * a corresponding (fake) GdkWindow so that events get
1468 * here. There won't be a widget though, so we have to handle
1471 if (event->type == GDK_PROPERTY_NOTIFY)
1472 _gtk_selection_incr_event (event->any.window,
1478 /* If pointer or keyboard grabs are in effect, munge the events
1479 * so that each window group looks like a separate app.
1481 rewritten_event = rewrite_event_for_grabs (event);
1482 if (rewritten_event)
1484 event = rewritten_event;
1485 event_widget = gtk_get_event_widget (event);
1488 window_group = gtk_main_get_window_group (event_widget);
1489 device = gdk_event_get_device (event);
1491 /* If there is a grab in effect...
1493 if (window_group->grabs)
1495 grab_widget = window_group->grabs->data;
1497 /* If the grab widget is an ancestor of the event widget
1498 * then we send the event to the original event widget.
1499 * This is the key to implementing modality.
1501 if (gtk_widget_is_sensitive (event_widget) &&
1502 gtk_widget_is_ancestor (event_widget, grab_widget))
1503 grab_widget = event_widget;
1507 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1510 gtk_widget_get_sensitive (event_widget) &&
1511 gtk_widget_is_ancestor (event_widget, grab_widget))
1512 grab_widget = event_widget;
1516 grab_widget = event_widget;
1518 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1520 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1522 if (rewritten_event)
1523 gdk_event_free (rewritten_event);
1528 /* Push the event onto a stack of current events for
1529 * gtk_current_event_get().
1531 current_events = g_list_prepend (current_events, event);
1533 /* Not all events get sent to the grabbing widget.
1534 * The delete, destroy, expose, focus change and resize
1535 * events still get sent to the event widget because
1536 * 1) these events have no meaning for the grabbing widget
1537 * and 2) redirecting these events to the grabbing widget
1538 * could cause the display to be messed up.
1540 * Drag events are also not redirected, since it isn't
1541 * clear what the semantics of that would be.
1543 switch (event->type)
1549 g_object_ref (event_widget);
1550 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1551 !gtk_widget_event (event_widget, event))
1552 gtk_widget_destroy (event_widget);
1553 g_object_unref (event_widget);
1557 /* Unexpected GDK_DESTROY from the outside, ignore for
1558 * child windows, handle like a GDK_DELETE for toplevels
1560 if (!event_widget->parent)
1562 g_object_ref (event_widget);
1563 if (!gtk_widget_event (event_widget, event) &&
1564 gtk_widget_get_realized (event_widget))
1565 gtk_widget_destroy (event_widget);
1566 g_object_unref (event_widget);
1571 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1573 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1574 gtk_widget_send_expose (event_widget, event);
1575 gdk_window_end_paint (event->any.window);
1579 /* The app may paint with a previously allocated cairo_t,
1580 which will draw directly to the window. We can't catch cairo
1581 drap operatoins to automatically flush the window, thus we
1582 need to explicitly flush any outstanding moves or double
1584 gdk_window_flush (event->any.window);
1585 gtk_widget_send_expose (event_widget, event);
1589 case GDK_PROPERTY_NOTIFY:
1591 case GDK_FOCUS_CHANGE:
1595 case GDK_SELECTION_CLEAR:
1596 case GDK_SELECTION_REQUEST:
1597 case GDK_SELECTION_NOTIFY:
1598 case GDK_CLIENT_EVENT:
1599 case GDK_VISIBILITY_NOTIFY:
1600 case GDK_WINDOW_STATE:
1601 case GDK_GRAB_BROKEN:
1603 gtk_widget_event (event_widget, event);
1607 case GDK_BUTTON_PRESS:
1608 case GDK_2BUTTON_PRESS:
1609 case GDK_3BUTTON_PRESS:
1610 gtk_propagate_event (grab_widget, event);
1614 case GDK_KEY_RELEASE:
1617 if (gtk_invoke_key_snoopers (grab_widget, event))
1620 /* Catch alt press to enable auto-mnemonics;
1621 * menus are handled elsewhere
1623 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1624 !GTK_IS_MENU_SHELL (grab_widget))
1626 gboolean auto_mnemonics;
1628 g_object_get (gtk_widget_get_settings (grab_widget),
1629 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1633 gboolean mnemonics_visible;
1636 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1638 window = gtk_widget_get_toplevel (grab_widget);
1640 if (GTK_IS_WINDOW (window))
1641 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1644 /* else fall through */
1645 case GDK_MOTION_NOTIFY:
1646 case GDK_BUTTON_RELEASE:
1647 case GDK_PROXIMITY_IN:
1648 case GDK_PROXIMITY_OUT:
1649 gtk_propagate_event (grab_widget, event);
1652 case GDK_ENTER_NOTIFY:
1653 _gtk_widget_set_device_window (event_widget,
1654 gdk_event_get_device (event),
1656 if (gtk_widget_is_sensitive (grab_widget))
1657 gtk_widget_event (grab_widget, event);
1660 case GDK_LEAVE_NOTIFY:
1661 _gtk_widget_set_device_window (event_widget,
1662 gdk_event_get_device (event),
1664 if (gtk_widget_is_sensitive (grab_widget))
1665 gtk_widget_event (grab_widget, event);
1668 case GDK_DRAG_STATUS:
1669 case GDK_DROP_FINISHED:
1670 _gtk_drag_source_handle_event (event_widget, event);
1672 case GDK_DRAG_ENTER:
1673 case GDK_DRAG_LEAVE:
1674 case GDK_DRAG_MOTION:
1675 case GDK_DROP_START:
1676 _gtk_drag_dest_handle_event (event_widget, event);
1679 g_assert_not_reached ();
1683 if (event->type == GDK_ENTER_NOTIFY
1684 || event->type == GDK_LEAVE_NOTIFY
1685 || event->type == GDK_BUTTON_PRESS
1686 || event->type == GDK_2BUTTON_PRESS
1687 || event->type == GDK_3BUTTON_PRESS
1688 || event->type == GDK_KEY_PRESS
1689 || event->type == GDK_DRAG_ENTER
1690 || event->type == GDK_GRAB_BROKEN
1691 || event->type == GDK_MOTION_NOTIFY
1692 || event->type == GDK_SCROLL)
1694 _gtk_tooltip_handle_event (event);
1697 tmp_list = current_events;
1698 current_events = g_list_remove_link (current_events, tmp_list);
1699 g_list_free_1 (tmp_list);
1701 if (rewritten_event)
1702 gdk_event_free (rewritten_event);
1717 static GtkWindowGroup *
1718 gtk_main_get_window_group (GtkWidget *widget)
1720 GtkWidget *toplevel = NULL;
1723 toplevel = gtk_widget_get_toplevel (widget);
1725 if (GTK_IS_WINDOW (toplevel))
1726 return gtk_window_get_group (GTK_WINDOW (toplevel));
1728 return gtk_window_get_group (NULL);
1733 GtkWidget *old_grab_widget;
1734 GtkWidget *new_grab_widget;
1735 gboolean was_grabbed;
1736 gboolean is_grabbed;
1738 GList *notified_windows;
1743 synth_crossing_for_grab_notify (GtkWidget *from,
1745 GrabNotifyInfo *info,
1747 GdkCrossingMode mode)
1751 GdkDevice *device = devices->data;
1752 GdkWindow *from_window, *to_window;
1754 /* Do not propagate events more than once to
1755 * the same windows if non-multidevice aware.
1761 from_window = _gtk_widget_get_device_window (from, device);
1764 !gdk_window_get_support_multidevice (from_window) &&
1765 g_list_find (info->notified_windows, from_window))
1773 to_window = _gtk_widget_get_device_window (to, device);
1776 !gdk_window_get_support_multidevice (to_window) &&
1777 g_list_find (info->notified_windows, to_window))
1781 if (from_window || to_window)
1783 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1784 (to_window) ? to : NULL,
1788 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1791 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1794 devices = devices->next;
1799 gtk_grab_notify_foreach (GtkWidget *child,
1802 GrabNotifyInfo *info = data;
1803 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1806 was_grabbed = info->was_grabbed;
1807 is_grabbed = info->is_grabbed;
1809 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1810 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1812 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1813 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1815 g_object_ref (child);
1817 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1818 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1821 _gtk_widget_get_device_window (child, info->device))
1823 /* Device specified and is on widget */
1824 devices = g_list_prepend (NULL, info->device);
1827 devices = _gtk_widget_list_devices (child);
1831 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1832 if (!was_shadowed && devices &&
1833 gtk_widget_is_sensitive (child))
1834 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1836 GDK_CROSSING_GTK_GRAB);
1840 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1841 if (was_shadowed && devices &&
1842 gtk_widget_is_sensitive (child))
1843 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1845 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1846 GDK_CROSSING_GTK_UNGRAB);
1849 if (was_shadowed != is_shadowed)
1850 _gtk_widget_grab_notify (child, was_shadowed);
1852 g_object_unref (child);
1853 g_list_free (devices);
1855 info->was_grabbed = was_grabbed;
1856 info->is_grabbed = is_grabbed;
1860 gtk_grab_notify (GtkWindowGroup *group,
1862 GtkWidget *old_grab_widget,
1863 GtkWidget *new_grab_widget,
1867 GrabNotifyInfo info = { 0 };
1869 if (old_grab_widget == new_grab_widget)
1872 info.old_grab_widget = old_grab_widget;
1873 info.new_grab_widget = new_grab_widget;
1874 info.from_grab = from_grab;
1875 info.device = device;
1877 g_object_ref (group);
1879 toplevels = gtk_window_list_toplevels ();
1880 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1884 GtkWindow *toplevel = toplevels->data;
1885 toplevels = g_list_delete_link (toplevels, toplevels);
1887 info.was_grabbed = FALSE;
1888 info.is_grabbed = FALSE;
1890 if (group == gtk_window_get_group (toplevel))
1891 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1892 g_object_unref (toplevel);
1895 g_list_free (info.notified_windows);
1896 g_object_unref (group);
1900 gtk_grab_add (GtkWidget *widget)
1902 GtkWindowGroup *group;
1903 GtkWidget *old_grab_widget;
1905 g_return_if_fail (widget != NULL);
1907 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1909 _gtk_widget_set_has_grab (widget, TRUE);
1911 group = gtk_main_get_window_group (widget);
1914 old_grab_widget = (GtkWidget *)group->grabs->data;
1916 old_grab_widget = NULL;
1918 g_object_ref (widget);
1919 group->grabs = g_slist_prepend (group->grabs, widget);
1921 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1926 gtk_grab_get_current (void)
1928 GtkWindowGroup *group;
1930 group = gtk_main_get_window_group (NULL);
1933 return GTK_WIDGET (group->grabs->data);
1938 gtk_grab_remove (GtkWidget *widget)
1940 GtkWindowGroup *group;
1941 GtkWidget *new_grab_widget;
1943 g_return_if_fail (widget != NULL);
1945 if (gtk_widget_has_grab (widget))
1947 _gtk_widget_set_has_grab (widget, FALSE);
1949 group = gtk_main_get_window_group (widget);
1950 group->grabs = g_slist_remove (group->grabs, widget);
1953 new_grab_widget = (GtkWidget *)group->grabs->data;
1955 new_grab_widget = NULL;
1957 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
1959 g_object_unref (widget);
1964 * gtk_device_grab_add:
1965 * @widget: a #GtkWidget
1966 * @device: a #GtkDevice to grab on.
1967 * @block_others: %TRUE to prevent other devices to interact with @widget.
1969 * Adds a GTK+ grab on @device, so all the events on @device and its
1970 * associated pointer or keyboard (if any) are delivered to @widget.
1971 * If the @block_others parameter is %TRUE, any other devices will be
1972 * unable to interact with @widget during the grab.
1977 gtk_device_grab_add (GtkWidget *widget,
1979 gboolean block_others)
1981 GtkWindowGroup *group;
1982 GtkWidget *old_grab_widget;
1984 g_return_if_fail (GTK_IS_WIDGET (widget));
1985 g_return_if_fail (GDK_IS_DEVICE (device));
1987 group = gtk_main_get_window_group (widget);
1988 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
1990 if (old_grab_widget != widget)
1991 _gtk_window_group_add_device_grab (group, widget, device, block_others);
1993 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
1997 * gtk_device_grab_remove:
1998 * @widget: a #GtkWidget
1999 * @device: a #GdkDevice
2001 * Removes a device grab from the given widget. You have to pair calls
2002 * to gtk_device_grab_add() and gtk_device_grab_remove().
2007 gtk_device_grab_remove (GtkWidget *widget,
2010 GtkWindowGroup *group;
2011 GtkWidget *new_grab_widget;
2013 g_return_if_fail (GTK_IS_WIDGET (widget));
2014 g_return_if_fail (GDK_IS_DEVICE (device));
2016 group = gtk_main_get_window_group (widget);
2017 _gtk_window_group_remove_device_grab (group, widget, device);
2018 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2020 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2024 gtk_init_add (GtkFunction function,
2027 GtkInitFunction *init;
2029 init = g_new (GtkInitFunction, 1);
2030 init->function = function;
2033 init_functions = g_list_prepend (init_functions, init);
2037 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2040 GtkKeySnooperData *data;
2041 static guint snooper_id = 1;
2043 g_return_val_if_fail (snooper != NULL, 0);
2045 data = g_new (GtkKeySnooperData, 1);
2046 data->func = snooper;
2047 data->func_data = func_data;
2048 data->id = snooper_id++;
2049 key_snoopers = g_slist_prepend (key_snoopers, data);
2055 gtk_key_snooper_remove (guint snooper_id)
2057 GtkKeySnooperData *data = NULL;
2060 slist = key_snoopers;
2064 if (data->id == snooper_id)
2067 slist = slist->next;
2072 key_snoopers = g_slist_remove (key_snoopers, data);
2078 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2082 gint return_val = FALSE;
2084 slist = key_snoopers;
2085 while (slist && !return_val)
2087 GtkKeySnooperData *data;
2090 slist = slist->next;
2091 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2098 gtk_quit_add_full (guint main_level,
2099 GtkFunction function,
2100 GtkCallbackMarshal marshal,
2102 GDestroyNotify destroy)
2104 static guint quit_id = 1;
2105 GtkQuitFunction *quitf;
2107 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2109 quitf = g_slice_new (GtkQuitFunction);
2111 quitf->id = quit_id++;
2112 quitf->main_level = main_level;
2113 quitf->function = function;
2114 quitf->marshal = marshal;
2116 quitf->destroy = destroy;
2118 quit_functions = g_list_prepend (quit_functions, quitf);
2124 gtk_quit_destroy (GtkQuitFunction *quitf)
2127 quitf->destroy (quitf->data);
2128 g_slice_free (GtkQuitFunction, quitf);
2132 gtk_quit_destructor (GtkObject **object_p)
2135 gtk_object_destroy (*object_p);
2142 gtk_quit_add_destroy (guint main_level,
2145 GtkObject **object_p;
2147 g_return_if_fail (main_level > 0);
2148 g_return_if_fail (GTK_IS_OBJECT (object));
2150 object_p = g_new (GtkObject*, 1);
2152 g_signal_connect (object,
2154 G_CALLBACK (gtk_widget_destroyed),
2156 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2160 gtk_quit_add (guint main_level,
2161 GtkFunction function,
2164 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2168 gtk_quit_remove (guint id)
2170 GtkQuitFunction *quitf;
2173 tmp_list = quit_functions;
2176 quitf = tmp_list->data;
2178 if (quitf->id == id)
2180 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2181 g_list_free (tmp_list);
2182 gtk_quit_destroy (quitf);
2187 tmp_list = tmp_list->next;
2192 gtk_quit_remove_by_data (gpointer data)
2194 GtkQuitFunction *quitf;
2197 tmp_list = quit_functions;
2200 quitf = tmp_list->data;
2202 if (quitf->data == data)
2204 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2205 g_list_free (tmp_list);
2206 gtk_quit_destroy (quitf);
2211 tmp_list = tmp_list->next;
2216 * gtk_get_current_event:
2218 * Obtains a copy of the event currently being processed by GTK+. For
2219 * example, if you get a "clicked" signal from #GtkButton, the current
2220 * event will be the #GdkEventButton that triggered the "clicked"
2221 * signal. The returned event must be freed with gdk_event_free().
2222 * If there is no current event, the function returns %NULL.
2224 * Return value: a copy of the current event, or %NULL if no current event.
2227 gtk_get_current_event (void)
2230 return gdk_event_copy (current_events->data);
2236 * gtk_get_current_event_time:
2238 * If there is a current event and it has a timestamp, return that
2239 * timestamp, otherwise return %GDK_CURRENT_TIME.
2241 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2244 gtk_get_current_event_time (void)
2247 return gdk_event_get_time (current_events->data);
2249 return GDK_CURRENT_TIME;
2253 * gtk_get_current_event_state:
2254 * @state: a location to store the state of the current event
2256 * If there is a current event and it has a state field, place
2257 * that state field in @state and return %TRUE, otherwise return
2260 * Return value: %TRUE if there was a current event and it had a state field
2263 gtk_get_current_event_state (GdkModifierType *state)
2265 g_return_val_if_fail (state != NULL, FALSE);
2268 return gdk_event_get_state (current_events->data, state);
2277 * gtk_get_current_event_device:
2279 * If there is a current event and it has a device, return that
2280 * device, otherwise return %NULL.
2282 * Returns: a #GdkDevice, or %NULL
2285 gtk_get_current_event_device (void)
2288 return gdk_event_get_device (current_events->data);
2294 * gtk_get_event_widget:
2295 * @event: a #GdkEvent
2297 * If @event is %NULL or the event was not associated with any widget,
2298 * returns %NULL, otherwise returns the widget that received the event
2301 * Return value: the widget that originally received @event, or %NULL
2304 gtk_get_event_widget (GdkEvent *event)
2307 gpointer widget_ptr;
2310 if (event && event->any.window &&
2311 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2313 gdk_window_get_user_data (event->any.window, &widget_ptr);
2314 widget = widget_ptr;
2321 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2323 if (!quitf->marshal)
2324 return quitf->function (quitf->data);
2328 gint ret_val = FALSE;
2330 args[0].name = NULL;
2331 args[0].type = G_TYPE_BOOLEAN;
2332 args[0].d.pointer_data = &ret_val;
2333 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2341 * gtk_propagate_event:
2342 * @widget: a #GtkWidget
2345 * Sends an event to a widget, propagating the event to parent widgets
2346 * if the event remains unhandled. Events received by GTK+ from GDK
2347 * normally begin in gtk_main_do_event(). Depending on the type of
2348 * event, existence of modal dialogs, grabs, etc., the event may be
2349 * propagated; if so, this function is used. gtk_propagate_event()
2350 * calls gtk_widget_event() on each widget it decides to send the
2351 * event to. So gtk_widget_event() is the lowest-level function; it
2352 * simply emits the "event" and possibly an event-specific signal on a
2353 * widget. gtk_propagate_event() is a bit higher-level, and
2354 * gtk_main_do_event() is the highest level.
2356 * All that said, you most likely don't want to use any of these
2357 * functions; synthesizing events is rarely needed. Consider asking on
2358 * the mailing list for better ways to achieve your goals. For
2359 * example, use gdk_window_invalidate_rect() or
2360 * gtk_widget_queue_draw() instead of making up expose events.
2364 gtk_propagate_event (GtkWidget *widget,
2369 g_return_if_fail (GTK_IS_WIDGET (widget));
2370 g_return_if_fail (event != NULL);
2372 handled_event = FALSE;
2374 g_object_ref (widget);
2376 if ((event->type == GDK_KEY_PRESS) ||
2377 (event->type == GDK_KEY_RELEASE))
2379 /* Only send key events within Window widgets to the Window
2380 * The Window widget will in turn pass the
2381 * key event on to the currently focused widget
2386 window = gtk_widget_get_toplevel (widget);
2387 if (GTK_IS_WINDOW (window))
2389 /* If there is a grab within the window, give the grab widget
2390 * a first crack at the key event
2392 if (widget != window && gtk_widget_has_grab (widget))
2393 handled_event = gtk_widget_event (widget, event);
2397 window = gtk_widget_get_toplevel (widget);
2398 if (GTK_IS_WINDOW (window))
2400 if (gtk_widget_is_sensitive (window))
2401 gtk_widget_event (window, event);
2405 handled_event = TRUE; /* don't send to widget */
2409 /* Other events get propagated up the widget tree
2410 * so that parents can see the button and motion
2411 * events of the children.
2419 /* Scroll events are special cased here because it
2420 * feels wrong when scrolling a GtkViewport, say,
2421 * to have children of the viewport eat the scroll
2424 if (!gtk_widget_is_sensitive (widget))
2425 handled_event = event->type != GDK_SCROLL;
2427 handled_event = gtk_widget_event (widget, event);
2429 tmp = widget->parent;
2430 g_object_unref (widget);
2434 if (!handled_event && widget)
2435 g_object_ref (widget);
2441 g_object_unref (widget);
2446 gtk_error (gchar *str)
2452 gtk_warning (gchar *str)
2458 gtk_message (gchar *str)
2464 gtk_print (gchar *str)
2466 static GtkWidget *window = NULL;
2467 static GtkWidget *text;
2468 static int level = 0;
2472 GtkWidget *hscrollbar;
2473 GtkWidget *vscrollbar;
2474 GtkWidget *separator;
2479 fputs (str, stdout);
2486 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2488 g_signal_connect (window, "destroy",
2489 G_CALLBACK (gtk_widget_destroyed), &window);
2491 gtk_window_set_title (GTK_WINDOW (window), "Messages");
2493 box1 = gtk_vbox_new (FALSE, 0);
2494 gtk_container_add (GTK_CONTAINER (window), box1);
2495 gtk_widget_show (box1);
2498 box2 = gtk_vbox_new (FALSE, 10);
2499 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2500 gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2501 gtk_widget_show (box2);
2504 table = gtk_table_new (2, 2, FALSE);
2505 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2506 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2507 gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2508 gtk_widget_show (table);
2510 text = gtk_text_new (NULL, NULL);
2511 gtk_text_set_editable (GTK_TEXT (text), FALSE);
2512 gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2513 gtk_widget_show (text);
2514 gtk_widget_realize (text);
2516 hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2517 gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2518 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2519 gtk_widget_show (hscrollbar);
2521 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2522 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2523 GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2524 gtk_widget_show (vscrollbar);
2526 separator = gtk_hseparator_new ();
2527 gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2528 gtk_widget_show (separator);
2531 box2 = gtk_vbox_new (FALSE, 10);
2532 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2533 gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2534 gtk_widget_show (box2);
2537 button = gtk_button_new_with_label ("close");
2538 g_signal_connect_swapped (button, "clicked",
2539 G_CALLBACK (gtk_widget_hide), window);
2540 gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2541 gtk_widget_set_can_default (button, TRUE);
2542 gtk_widget_grab_default (button);
2543 gtk_widget_show (button);
2547 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2550 if (!gtk_widget_get_visible (window))
2551 gtk_widget_show (window);
2556 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2557 GValue *return_accu,
2558 const GValue *handler_return,
2561 gboolean continue_emission;
2562 gboolean signal_handled;
2564 signal_handled = g_value_get_boolean (handler_return);
2565 g_value_set_boolean (return_accu, signal_handled);
2566 continue_emission = !signal_handled;
2568 return continue_emission;
2571 #define __GTK_MAIN_C__
2572 #include "gtkaliasdef.c"