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 _GtkKeySnooperData GtkKeySnooperData;
153 struct _GtkInitFunction
155 GtkFunction function;
159 struct _GtkQuitFunction
163 GtkCallbackMarshal marshal;
164 GtkFunction function;
166 GDestroyNotify destroy;
169 struct _GtkKeySnooperData
171 GtkKeySnoopFunc func;
176 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
177 static void gtk_quit_destroy (GtkQuitFunction *quitf);
178 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
182 static void gtk_error (gchar *str);
183 static void gtk_warning (gchar *str);
184 static void gtk_message (gchar *str);
185 static void gtk_print (gchar *str);
188 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
190 const guint gtk_major_version = GTK_MAJOR_VERSION;
191 const guint gtk_minor_version = GTK_MINOR_VERSION;
192 const guint gtk_micro_version = GTK_MICRO_VERSION;
193 const guint gtk_binary_age = GTK_BINARY_AGE;
194 const guint gtk_interface_age = GTK_INTERFACE_AGE;
196 static guint gtk_main_loop_level = 0;
197 static gint pre_initialized = FALSE;
198 static gint gtk_initialized = FALSE;
199 static GList *current_events = NULL;
201 static GSList *main_loops = NULL; /* stack of currently executing main loops */
203 static GList *init_functions = NULL; /* A list of init functions.
205 static GList *quit_functions = NULL; /* A list of quit functions.
207 static GSList *key_snoopers = NULL;
209 guint gtk_debug_flags = 0; /* Global GTK debug flag */
211 #ifdef G_ENABLE_DEBUG
212 static const GDebugKey gtk_debug_keys[] = {
213 {"misc", GTK_DEBUG_MISC},
214 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
215 {"text", GTK_DEBUG_TEXT},
216 {"tree", GTK_DEBUG_TREE},
217 {"updates", GTK_DEBUG_UPDATES},
218 {"keybindings", GTK_DEBUG_KEYBINDINGS},
219 {"multihead", GTK_DEBUG_MULTIHEAD},
220 {"modules", GTK_DEBUG_MODULES},
221 {"geometry", GTK_DEBUG_GEOMETRY},
222 {"icontheme", GTK_DEBUG_ICONTHEME},
223 {"printing", GTK_DEBUG_PRINTING},
224 {"builder", GTK_DEBUG_BUILDER},
225 {"extended-layout", GTK_DEBUG_EXTENDED_LAYOUT},
227 #endif /* G_ENABLE_DEBUG */
231 * @required_major: the required major version.
232 * @required_minor: the required minor version.
233 * @required_micro: the required micro version.
235 * Checks that the GTK+ library in use is compatible with the
236 * given version. Generally you would pass in the constants
237 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
238 * as the three arguments to this function; that produces
239 * a check that the library in use is compatible with
240 * the version of GTK+ the application or module was compiled
243 * Compatibility is defined by two things: first the version
244 * of the running library is newer than the version
245 * @required_major.required_minor.@required_micro. Second
246 * the running library must be binary compatible with the
247 * version @required_major.required_minor.@required_micro
248 * (same major version.)
250 * This function is primarily for GTK+ modules; the module
251 * can call this function to check that it wasn't loaded
252 * into an incompatible version of GTK+. However, such a
253 * a check isn't completely reliable, since the module may be
254 * linked against an old version of GTK+ and calling the
255 * old version of gtk_check_version(), but still get loaded
256 * into an application using a newer version of GTK+.
258 * Return value: %NULL if the GTK+ library is compatible with the
259 * given version, or a string describing the version mismatch.
260 * The returned string is owned by GTK+ and should not be modified
264 gtk_check_version (guint required_major,
265 guint required_minor,
266 guint required_micro)
268 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
269 gint required_effective_micro = 100 * required_minor + required_micro;
271 if (required_major > GTK_MAJOR_VERSION)
272 return "Gtk+ version too old (major mismatch)";
273 if (required_major < GTK_MAJOR_VERSION)
274 return "Gtk+ version too new (major mismatch)";
275 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
276 return "Gtk+ version too new (micro mismatch)";
277 if (required_effective_micro > gtk_effective_micro)
278 return "Gtk+ version too old (micro mismatch)";
282 /* This checks to see if the process is running suid or sgid
283 * at the current time. If so, we don't allow GTK+ to be initialized.
284 * This is meant to be a mild check - we only error out if we
285 * can prove the programmer is doing something wrong, not if
286 * they could be doing something wrong. For this reason, we
287 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
292 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
294 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
295 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
297 #ifdef HAVE_GETRESUID
298 /* These aren't in the header files, so we prototype them here.
300 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
301 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
303 if (getresuid (&ruid, &euid, &suid) != 0 ||
304 getresgid (&rgid, &egid, &sgid) != 0)
305 #endif /* HAVE_GETRESUID */
307 suid = ruid = getuid ();
308 sgid = rgid = getgid ();
313 if (ruid != euid || ruid != suid ||
314 rgid != egid || rgid != sgid)
316 g_warning ("This process is currently running setuid or setgid.\n"
317 "This is not a supported use of GTK+. You must create a helper\n"
318 "program instead. For further details, see:\n\n"
319 " http://www.gtk.org/setuid.html\n\n"
320 "Refusing to initialize GTK+.");
330 _gtk_get_datadir (void)
332 static char *gtk_datadir = NULL;
333 if (gtk_datadir == NULL)
335 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
336 gtk_datadir = g_build_filename (root, "share", NULL);
344 _gtk_get_sysconfdir (void)
346 static char *gtk_sysconfdir = NULL;
347 if (gtk_sysconfdir == NULL)
349 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
350 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
354 return gtk_sysconfdir;
358 _gtk_get_data_prefix (void)
360 static char *gtk_data_prefix = NULL;
361 if (gtk_data_prefix == NULL)
362 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
364 return gtk_data_prefix;
367 #endif /* G_OS_WIN32 */
369 static gboolean do_setlocale = TRUE;
372 * gtk_disable_setlocale:
374 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
375 * gtk_parse_args() from automatically
376 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
377 * want to use this function if you wanted to set the locale for
378 * your program to something other than the user's locale, or if
379 * you wanted to set different values for different locale categories.
381 * Most programs should not need to call this function.
384 gtk_disable_setlocale (void)
387 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
389 do_setlocale = FALSE;
392 #ifdef G_PLATFORM_WIN32
393 #undef gtk_init_check
396 static GString *gtk_modules_string = NULL;
397 static gboolean g_fatal_warnings = FALSE;
399 #ifdef G_ENABLE_DEBUG
401 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
403 gtk_debug_flags |= g_parse_debug_string (value,
405 G_N_ELEMENTS (gtk_debug_keys));
411 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
413 gtk_debug_flags &= ~g_parse_debug_string (value,
415 G_N_ELEMENTS (gtk_debug_keys));
419 #endif /* G_ENABLE_DEBUG */
422 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
426 if (gtk_modules_string)
427 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
429 gtk_modules_string = g_string_new (NULL);
431 g_string_append (gtk_modules_string, value);
437 static const GOptionEntry gtk_args[] = {
438 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
439 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
440 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
441 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
442 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
443 #ifdef G_ENABLE_DEBUG
444 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
445 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
446 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
447 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
448 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
449 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
456 static char *iso639_to_check = NULL;
457 static char *iso3166_to_check = NULL;
458 static char *script_to_check = NULL;
459 static gboolean setlocale_called = FALSE;
462 enum_locale_proc (LPTSTR locale)
470 lcid = strtoul (locale, &endptr, 16);
471 if (*endptr == '\0' &&
472 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
473 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
475 if (strcmp (iso639, iso639_to_check) == 0 &&
476 ((iso3166_to_check != NULL &&
477 strcmp (iso3166, iso3166_to_check) == 0) ||
478 (iso3166_to_check == NULL &&
479 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
481 char language[100], country[100];
484 if (script_to_check != NULL)
486 /* If lcid is the "other" script for this language,
487 * return TRUE, i.e. continue looking.
489 if (strcmp (script_to_check, "Latn") == 0)
491 switch (LANGIDFROMLCID (lcid))
493 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
495 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
497 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
499 case MAKELANGID (LANG_SERBIAN, 0x07):
500 /* Serbian in Bosnia and Herzegovina, Cyrillic */
504 else if (strcmp (script_to_check, "Cyrl") == 0)
506 switch (LANGIDFROMLCID (lcid))
508 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
510 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
512 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
514 case MAKELANGID (LANG_SERBIAN, 0x06):
515 /* Serbian in Bosnia and Herzegovina, Latin */
521 SetThreadLocale (lcid);
523 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
524 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
526 strcpy (locale, language);
527 strcat (locale, "_");
528 strcat (locale, country);
530 if (setlocale (LC_ALL, locale) != NULL)
531 setlocale_called = TRUE;
544 setlocale_initialization (void)
546 static gboolean initialized = FALSE;
555 /* If some of the POSIXish environment variables are set, set
556 * the Win32 thread locale correspondingly.
558 char *p = getenv ("LC_ALL");
565 if (strcmp (p, "C") == 0)
566 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
569 /* Check if one of the supported locales match the
570 * environment variable. If so, use that locale.
573 iso3166_to_check = strchr (iso639_to_check, '_');
574 if (iso3166_to_check != NULL)
576 *iso3166_to_check++ = '\0';
578 script_to_check = strchr (iso3166_to_check, '@');
579 if (script_to_check != NULL)
580 *script_to_check++ = '\0';
582 /* Handle special cases. */
584 /* The standard code for Serbia and Montenegro was
585 * "CS", but MSFT uses for some reason "SP". By now
586 * (October 2006), SP has split into two, "RS" and
587 * "ME", but don't bother trying to handle those
588 * yet. Do handle the even older "YU", though.
590 if (strcmp (iso3166_to_check, "CS") == 0 ||
591 strcmp (iso3166_to_check, "YU") == 0)
592 iso3166_to_check = "SP";
596 script_to_check = strchr (iso639_to_check, '@');
597 if (script_to_check != NULL)
598 *script_to_check++ = '\0';
599 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
600 if (strcmp (iso639_to_check, "sr") == 0)
601 iso3166_to_check = "SP";
604 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
608 if (!setlocale_called)
609 setlocale (LC_ALL, "");
611 if (!setlocale (LC_ALL, ""))
612 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
618 do_pre_parse_initialization (int *argc,
621 const gchar *env_string;
624 g_set_error_handler (gtk_error);
625 g_set_warning_handler (gtk_warning);
626 g_set_message_handler (gtk_message);
627 g_set_print_handler (gtk_print);
633 pre_initialized = TRUE;
635 gdk_pre_parse_libgtk_only ();
636 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
638 #ifdef G_ENABLE_DEBUG
639 env_string = g_getenv ("GTK_DEBUG");
640 if (env_string != NULL)
642 gtk_debug_flags = g_parse_debug_string (env_string,
644 G_N_ELEMENTS (gtk_debug_keys));
647 #endif /* G_ENABLE_DEBUG */
649 env_string = g_getenv ("GTK_MODULES");
651 gtk_modules_string = g_string_new (env_string);
655 gettext_initialization (void)
657 setlocale_initialization ();
660 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
661 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
662 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
663 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
664 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
670 do_post_parse_initialization (int *argc,
676 gettext_initialization ();
679 signal (SIGPIPE, SIG_IGN);
682 if (g_fatal_warnings)
684 GLogLevelFlags fatal_mask;
686 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
687 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
688 g_log_set_always_fatal (fatal_mask);
691 if (gtk_debug_flags & GTK_DEBUG_UPDATES)
692 gdk_window_set_debug_updates (TRUE);
695 /* Translate to default:RTL if you want your widgets
696 * to be RTL, otherwise translate to default:LTR.
697 * Do *not* translate it to "predefinito:LTR", if it
698 * it isn't default:LTR or default:RTL it will not work
700 char *e = _("default:LTR");
701 if (strcmp (e, "default:RTL")==0)
702 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
703 else if (strcmp (e, "default:LTR"))
704 g_warning ("Whoever translated default:LTR did so wrongly.\n");
707 /* do what the call to gtk_type_init() used to do */
710 _gtk_accel_map_init ();
713 /* Set the 'initialized' flag.
715 gtk_initialized = TRUE;
717 /* load gtk modules */
718 if (gtk_modules_string)
720 _gtk_modules_init (argc, argv, gtk_modules_string->str);
721 g_string_free (gtk_modules_string, TRUE);
725 _gtk_modules_init (argc, argv, NULL);
732 gboolean open_default_display;
736 pre_parse_hook (GOptionContext *context,
741 do_pre_parse_initialization (NULL, NULL);
747 post_parse_hook (GOptionContext *context,
752 OptionGroupInfo *info = data;
755 do_post_parse_initialization (NULL, NULL);
757 if (info->open_default_display)
759 if (gdk_display_open_default_libgtk_only () == NULL)
761 const char *display_name = gdk_get_display_arg_name ();
764 G_OPTION_ERROR_FAILED,
765 _("Cannot open display: %s"),
766 display_name ? display_name : "" );
777 * gtk_get_option_group:
778 * @open_default_display: whether to open the default display
779 * when parsing the commandline arguments
781 * Returns a #GOptionGroup for the commandline arguments recognized
782 * by GTK+ and GDK. You should add this group to your #GOptionContext
783 * with g_option_context_add_group(), if you are using
784 * g_option_context_parse() to parse your commandline arguments.
786 * Returns: a #GOptionGroup for the commandline arguments recognized
792 gtk_get_option_group (gboolean open_default_display)
795 OptionGroupInfo *info;
797 gettext_initialization ();
799 info = g_new0 (OptionGroupInfo, 1);
800 info->open_default_display = open_default_display;
802 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
803 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
805 gdk_add_option_entries_libgtk_only (group);
806 g_option_group_add_entries (group, gtk_args);
807 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
813 * gtk_init_with_args:
814 * @argc: a pointer to the number of command line arguments.
815 * @argv: a pointer to the array of command line arguments.
816 * @parameter_string: a string which is displayed in
817 * the first line of <option>--help</option> output, after
818 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
819 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
820 * describing the options of your program
821 * @translation_domain: a translation domain to use for translating
822 * the <option>--help</option> output for the options in @entries
823 * with gettext(), or %NULL
824 * @error: a return location for errors
826 * This function does the same work as gtk_init_check().
827 * Additionally, it allows you to add your own commandline options,
828 * and it automatically generates nicely formatted
829 * <option>--help</option> output. Note that your program will
830 * be terminated after writing out the help output.
832 * Returns: %TRUE if the GUI has been successfully initialized,
838 gtk_init_with_args (int *argc,
840 const char *parameter_string,
841 GOptionEntry *entries,
842 const char *translation_domain,
845 GOptionContext *context;
846 GOptionGroup *gtk_group;
850 return gdk_display_open_default_libgtk_only () != NULL;
852 gettext_initialization ();
854 if (!check_setugid ())
857 gtk_group = gtk_get_option_group (TRUE);
859 context = g_option_context_new (parameter_string);
860 g_option_context_add_group (context, gtk_group);
863 g_option_context_add_main_entries (context, entries, translation_domain);
864 retval = g_option_context_parse (context, argc, argv, error);
866 g_option_context_free (context);
874 * @argc: (inout): a pointer to the number of command line arguments.
875 * @argv: (array) (inout): a pointer to the array of command line arguments.
877 * Parses command line arguments, and initializes global
878 * attributes of GTK+, but does not actually open a connection
879 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
881 * Any arguments used by GTK+ or GDK are removed from the array and
882 * @argc and @argv are updated accordingly.
884 * You shouldn't call this function explicitely if you are using
885 * gtk_init(), or gtk_init_check().
887 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
890 gtk_parse_args (int *argc,
893 GOptionContext *option_context;
894 GOptionGroup *gtk_group;
895 GError *error = NULL;
900 gettext_initialization ();
902 if (!check_setugid ())
905 option_context = g_option_context_new (NULL);
906 g_option_context_set_ignore_unknown_options (option_context, TRUE);
907 g_option_context_set_help_enabled (option_context, FALSE);
908 gtk_group = gtk_get_option_group (FALSE);
909 g_option_context_set_main_group (option_context, gtk_group);
910 if (!g_option_context_parse (option_context, argc, argv, &error))
912 g_warning ("%s", error->message);
913 g_error_free (error);
916 g_option_context_free (option_context);
921 #ifdef G_PLATFORM_WIN32
922 #undef gtk_init_check
927 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
928 * main() function. Changed if any arguments were handled.
929 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
930 * Any parameters understood by gtk_init() are stripped before return.
932 * This function does the same work as gtk_init() with only
933 * a single change: It does not terminate the program if the GUI can't be
934 * initialized. Instead it returns %FALSE on failure.
936 * This way the application can fall back to some other means of communication
937 * with the user - for example a curses or command line interface.
939 * Return value: %TRUE if the GUI has been successfully initialized,
943 gtk_init_check (int *argc,
946 if (!gtk_parse_args (argc, argv))
949 return gdk_display_open_default_libgtk_only () != NULL;
952 #ifdef G_PLATFORM_WIN32
958 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
959 * main() function. Changed if any arguments were handled.
960 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
961 * Any parameters understood by gtk_init() are stripped before return.
963 * Call this function before using any other GTK+ functions in your GUI
964 * applications. It will initialize everything needed to operate the
965 * toolkit and parses some standard command line options. @argc and
966 * @argv are adjusted accordingly so your own code will
967 * never see those standard arguments.
969 * Note that there are some alternative ways to initialize GTK+:
970 * if you are calling gtk_parse_args(), gtk_init_check(),
971 * gtk_init_with_args() or g_option_context_parse() with
972 * the option group returned by gtk_get_option_group(), you
973 * <emphasis>don't</emphasis> have to call gtk_init().
976 * This function will terminate your program if it was unable to initialize
977 * the GUI for some reason. If you want your program to fall back to a
978 * textual interface you want to call gtk_init_check() instead.
982 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
983 * during initialization, to ignore SIGPIPE signals, since these are
984 * almost never wanted in graphical applications. If you do need to
985 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
986 * but notice that other libraries (e.g. libdbus or gvfs) might do
991 gtk_init (int *argc, char ***argv)
993 if (!gtk_init_check (argc, argv))
995 const char *display_name_arg = gdk_get_display_arg_name ();
996 if (display_name_arg == NULL)
997 display_name_arg = getenv("DISPLAY");
998 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1003 #ifdef G_PLATFORM_WIN32
1006 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1008 if (sizeof_GtkWindow != sizeof (GtkWindow))
1009 g_error ("Incompatible build!\n"
1010 "The code using GTK+ thinks GtkWindow is of different\n"
1011 "size than it actually is in this build of GTK+.\n"
1012 "On Windows, this probably means that you have compiled\n"
1013 "your code with gcc without the -mms-bitfields switch,\n"
1014 "or that you are using an unsupported compiler.");
1017 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1018 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1019 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1020 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1021 * -fnative-struct still matters. GtkBox is one such.
1024 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1026 if (sizeof_GtkBox != sizeof (GtkBox))
1027 g_error ("Incompatible build!\n"
1028 "The code using GTK+ thinks GtkBox is of different\n"
1029 "size than it actually is in this build of GTK+.\n"
1030 "On Windows, this probably means that you have compiled\n"
1031 "your code with gcc without the -mms-bitfields switch,\n"
1032 "or that you are using an unsupported compiler.");
1035 /* These two functions might get more checks added later, thus pass
1036 * in the number of extra args.
1039 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1041 check_sizeof_GtkWindow (sizeof_GtkWindow);
1042 if (num_checks >= 2)
1043 check_sizeof_GtkBox (sizeof_GtkBox);
1044 gtk_init (argc, argv);
1048 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1050 check_sizeof_GtkWindow (sizeof_GtkWindow);
1051 if (num_checks >= 2)
1052 check_sizeof_GtkBox (sizeof_GtkBox);
1053 return gtk_init_check (argc, argv);
1061 * Initializes internationalization support for GTK+. gtk_init()
1062 * automatically does this, so there is typically no point
1063 * in calling this function.
1065 * If you are calling this function because you changed the locale
1066 * after GTK+ is was initialized, then calling this function
1067 * may help a bit. (Note, however, that changing the locale
1068 * after GTK+ is initialized may produce inconsistent results and
1069 * is not really supported.)
1071 * In detail - sets the current locale according to the
1072 * program environment. This is the same as calling the C library function
1073 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1074 * locale specific setup of the windowing system used by GDK.
1076 * Returns: a string corresponding to the locale set, typically in the
1077 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1078 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1079 * result of the setlocale(); it is also used on other machines, such as
1080 * Windows, where the C library returns a different result. The string is
1081 * owned by GTK+ and should not be modified or freed.
1084 gtk_set_locale (void)
1086 return gdk_set_locale ();
1090 * _gtk_get_lc_ctype:
1092 * Return the Unix-style locale string for the language currently in
1093 * effect. On Unix systems, this is the return value from
1094 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1095 * affect this through the environment variables LC_ALL, LC_CTYPE or
1096 * LANG (checked in that order). The locale strings typically is in
1097 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1098 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1099 * Swedish as written in Finland or pt_BR for Portuguese as written in
1102 * On Windows, the C library doesn't use any such environment
1103 * variables, and setting them won't affect the behaviour of functions
1104 * like ctime(). The user sets the locale through the Regional Options
1105 * in the Control Panel. The C library (in the setlocale() function)
1106 * does not use country and language codes, but country and language
1107 * names spelled out in English.
1108 * However, this function does check the above environment
1109 * variables, and does return a Unix-style locale string based on
1110 * either said environment variables or the thread's current locale.
1112 * Return value: a dynamically allocated string, free with g_free().
1116 _gtk_get_lc_ctype (void)
1119 /* Somebody might try to set the locale for this process using the
1120 * LANG or LC_ environment variables. The Microsoft C library
1121 * doesn't know anything about them. You set the locale in the
1122 * Control Panel. Setting these env vars won't have any affect on
1123 * locale-dependent C library functions like ctime(). But just for
1124 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1125 * it easier to test GTK and Pango in various default languages, you
1126 * don't have to clickety-click in the Control Panel, you can simply
1127 * start the program with LC_ALL=something on the command line.)
1131 p = getenv ("LC_ALL");
1133 return g_strdup (p);
1135 p = getenv ("LC_CTYPE");
1137 return g_strdup (p);
1139 p = getenv ("LANG");
1141 return g_strdup (p);
1143 return g_win32_getlocale ();
1145 return g_strdup (setlocale (LC_CTYPE, NULL));
1150 * gtk_get_default_language:
1152 * Returns the #PangoLanguage for the default language currently in
1153 * effect. (Note that this can change over the life of an
1154 * application.) The default language is derived from the current
1155 * locale. It determines, for example, whether GTK+ uses the
1156 * right-to-left or left-to-right text direction.
1158 * This function is equivalent to pango_language_get_default(). See
1159 * that function for details.
1161 * Return value: the default language as a #PangoLanguage, must not be
1165 gtk_get_default_language (void)
1167 return pango_language_get_default ();
1175 GtkInitFunction *init;
1178 gtk_main_loop_level++;
1180 loop = g_main_loop_new (NULL, TRUE);
1181 main_loops = g_slist_prepend (main_loops, loop);
1183 tmp_list = functions = init_functions;
1184 init_functions = NULL;
1188 init = tmp_list->data;
1189 tmp_list = tmp_list->next;
1191 (* init->function) (init->data);
1194 g_list_free (functions);
1196 if (g_main_loop_is_running (main_loops->data))
1198 GDK_THREADS_LEAVE ();
1199 g_main_loop_run (loop);
1200 GDK_THREADS_ENTER ();
1206 GList *reinvoke_list = NULL;
1207 GtkQuitFunction *quitf;
1209 while (quit_functions)
1211 quitf = quit_functions->data;
1213 tmp_list = quit_functions;
1214 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1215 g_list_free_1 (tmp_list);
1217 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1218 gtk_quit_invoke_function (quitf))
1220 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1224 gtk_quit_destroy (quitf);
1231 work = g_list_last (reinvoke_list);
1233 quit_functions->prev = work;
1234 work->next = quit_functions;
1235 quit_functions = work;
1241 main_loops = g_slist_remove (main_loops, loop);
1243 g_main_loop_unref (loop);
1245 gtk_main_loop_level--;
1247 if (gtk_main_loop_level == 0)
1249 /* Try storing all clipboard data we have */
1250 _gtk_clipboard_store_all ();
1252 /* Synchronize the recent manager singleton */
1253 _gtk_recent_manager_sync ();
1258 gtk_main_level (void)
1260 return gtk_main_loop_level;
1264 gtk_main_quit (void)
1266 g_return_if_fail (main_loops != NULL);
1268 g_main_loop_quit (main_loops->data);
1272 gtk_events_pending (void)
1276 GDK_THREADS_LEAVE ();
1277 result = g_main_context_pending (NULL);
1278 GDK_THREADS_ENTER ();
1284 gtk_main_iteration (void)
1286 GDK_THREADS_LEAVE ();
1287 g_main_context_iteration (NULL, TRUE);
1288 GDK_THREADS_ENTER ();
1291 return !g_main_loop_is_running (main_loops->data);
1297 gtk_main_iteration_do (gboolean blocking)
1299 GDK_THREADS_LEAVE ();
1300 g_main_context_iteration (NULL, blocking);
1301 GDK_THREADS_ENTER ();
1304 return !g_main_loop_is_running (main_loops->data);
1309 /* private libgtk to libgdk interfaces
1311 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1313 GdkWindow **grab_window,
1314 gboolean *owner_events);
1317 rewrite_events_translate (GdkWindow *old_window,
1318 GdkWindow *new_window,
1322 gint old_origin_x, old_origin_y;
1323 gint new_origin_x, new_origin_y;
1325 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1326 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1328 *x += old_origin_x - new_origin_x;
1329 *y += old_origin_y - new_origin_y;
1333 rewrite_event_for_window (GdkEvent *event,
1334 GdkWindow *new_window)
1336 event = gdk_event_copy (event);
1338 switch (event->type)
1341 rewrite_events_translate (event->any.window,
1343 &event->scroll.x, &event->scroll.y);
1345 case GDK_BUTTON_PRESS:
1346 case GDK_2BUTTON_PRESS:
1347 case GDK_3BUTTON_PRESS:
1348 case GDK_BUTTON_RELEASE:
1349 rewrite_events_translate (event->any.window,
1351 &event->button.x, &event->button.y);
1353 case GDK_MOTION_NOTIFY:
1354 rewrite_events_translate (event->any.window,
1356 &event->motion.x, &event->motion.y);
1359 case GDK_KEY_RELEASE:
1360 case GDK_PROXIMITY_IN:
1361 case GDK_PROXIMITY_OUT:
1368 g_object_unref (event->any.window);
1369 event->any.window = g_object_ref (new_window);
1374 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1375 * then what X11 does is deliver the event normally if it was going to this
1376 * client, otherwise, delivers it in terms of the grab window. This function
1377 * rewrites events to the effect that events going to the same window group
1378 * are delivered normally, otherwise, the event is delivered in terms of the
1382 rewrite_event_for_grabs (GdkEvent *event)
1384 GdkWindow *grab_window;
1385 GtkWidget *event_widget, *grab_widget;
1386 gpointer grab_widget_ptr;
1387 gboolean owner_events;
1388 GdkDisplay *display;
1391 switch (event->type)
1394 case GDK_BUTTON_PRESS:
1395 case GDK_2BUTTON_PRESS:
1396 case GDK_3BUTTON_PRESS:
1397 case GDK_BUTTON_RELEASE:
1398 case GDK_MOTION_NOTIFY:
1399 case GDK_PROXIMITY_IN:
1400 case GDK_PROXIMITY_OUT:
1402 case GDK_KEY_RELEASE:
1403 display = gdk_drawable_get_display (event->any.window);
1404 device = gdk_event_get_device (event);
1406 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1414 event_widget = gtk_get_event_widget (event);
1415 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1416 grab_widget = grab_widget_ptr;
1419 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1420 return rewrite_event_for_window (event, grab_window);
1426 gtk_main_do_event (GdkEvent *event)
1428 GtkWidget *event_widget;
1429 GtkWidget *grab_widget = NULL;
1430 GtkWindowGroup *window_group;
1431 GdkEvent *rewritten_event = NULL;
1435 if (event->type == GDK_SETTING)
1437 _gtk_settings_handle_event (&event->setting);
1441 if (event->type == GDK_OWNER_CHANGE)
1443 _gtk_clipboard_handle_event (&event->owner_change);
1447 /* Find the widget which got the event. We store the widget
1448 * in the user_data field of GdkWindow's.
1449 * Ignore the event if we don't have a widget for it, except
1450 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1451 * Though this happens rarely, bogus events can occour
1452 * for e.g. destroyed GdkWindows.
1454 event_widget = gtk_get_event_widget (event);
1457 /* To handle selection INCR transactions, we select
1458 * PropertyNotify events on the requestor window and create
1459 * a corresponding (fake) GdkWindow so that events get
1460 * here. There won't be a widget though, so we have to handle
1463 if (event->type == GDK_PROPERTY_NOTIFY)
1464 _gtk_selection_incr_event (event->any.window,
1470 /* If pointer or keyboard grabs are in effect, munge the events
1471 * so that each window group looks like a separate app.
1473 rewritten_event = rewrite_event_for_grabs (event);
1474 if (rewritten_event)
1476 event = rewritten_event;
1477 event_widget = gtk_get_event_widget (event);
1480 window_group = gtk_main_get_window_group (event_widget);
1481 device = gdk_event_get_device (event);
1483 /* If there is a grab in effect...
1485 if (window_group->grabs)
1487 grab_widget = window_group->grabs->data;
1489 /* If the grab widget is an ancestor of the event widget
1490 * then we send the event to the original event widget.
1491 * This is the key to implementing modality.
1493 if (gtk_widget_is_sensitive (event_widget) &&
1494 gtk_widget_is_ancestor (event_widget, grab_widget))
1495 grab_widget = event_widget;
1499 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1502 gtk_widget_get_sensitive (event_widget) &&
1503 gtk_widget_is_ancestor (event_widget, grab_widget))
1504 grab_widget = event_widget;
1508 grab_widget = event_widget;
1510 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1512 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1514 if (rewritten_event)
1515 gdk_event_free (rewritten_event);
1520 /* Push the event onto a stack of current events for
1521 * gtk_current_event_get().
1523 current_events = g_list_prepend (current_events, event);
1525 /* Not all events get sent to the grabbing widget.
1526 * The delete, destroy, expose, focus change and resize
1527 * events still get sent to the event widget because
1528 * 1) these events have no meaning for the grabbing widget
1529 * and 2) redirecting these events to the grabbing widget
1530 * could cause the display to be messed up.
1532 * Drag events are also not redirected, since it isn't
1533 * clear what the semantics of that would be.
1535 switch (event->type)
1541 g_object_ref (event_widget);
1542 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1543 !gtk_widget_event (event_widget, event))
1544 gtk_widget_destroy (event_widget);
1545 g_object_unref (event_widget);
1549 /* Unexpected GDK_DESTROY from the outside, ignore for
1550 * child windows, handle like a GDK_DELETE for toplevels
1552 if (!event_widget->parent)
1554 g_object_ref (event_widget);
1555 if (!gtk_widget_event (event_widget, event) &&
1556 gtk_widget_get_realized (event_widget))
1557 gtk_widget_destroy (event_widget);
1558 g_object_unref (event_widget);
1563 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1565 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1566 gtk_widget_send_expose (event_widget, event);
1567 gdk_window_end_paint (event->any.window);
1571 /* The app may paint with a previously allocated cairo_t,
1572 which will draw directly to the window. We can't catch cairo
1573 drap operatoins to automatically flush the window, thus we
1574 need to explicitly flush any outstanding moves or double
1576 gdk_window_flush (event->any.window);
1577 gtk_widget_send_expose (event_widget, event);
1581 case GDK_PROPERTY_NOTIFY:
1583 case GDK_FOCUS_CHANGE:
1587 case GDK_SELECTION_CLEAR:
1588 case GDK_SELECTION_REQUEST:
1589 case GDK_SELECTION_NOTIFY:
1590 case GDK_CLIENT_EVENT:
1591 case GDK_VISIBILITY_NOTIFY:
1592 case GDK_WINDOW_STATE:
1593 case GDK_GRAB_BROKEN:
1595 gtk_widget_event (event_widget, event);
1599 case GDK_BUTTON_PRESS:
1600 case GDK_2BUTTON_PRESS:
1601 case GDK_3BUTTON_PRESS:
1602 gtk_propagate_event (grab_widget, event);
1606 case GDK_KEY_RELEASE:
1609 if (gtk_invoke_key_snoopers (grab_widget, event))
1612 /* Catch alt press to enable auto-mnemonics;
1613 * menus are handled elsewhere
1615 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1616 !GTK_IS_MENU_SHELL (grab_widget))
1618 gboolean auto_mnemonics;
1620 g_object_get (gtk_widget_get_settings (grab_widget),
1621 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1625 gboolean mnemonics_visible;
1628 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1630 window = gtk_widget_get_toplevel (grab_widget);
1632 if (GTK_IS_WINDOW (window))
1633 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1636 /* else fall through */
1637 case GDK_MOTION_NOTIFY:
1638 case GDK_BUTTON_RELEASE:
1639 case GDK_PROXIMITY_IN:
1640 case GDK_PROXIMITY_OUT:
1641 gtk_propagate_event (grab_widget, event);
1644 case GDK_ENTER_NOTIFY:
1645 _gtk_widget_set_device_window (event_widget,
1646 gdk_event_get_device (event),
1648 if (gtk_widget_is_sensitive (grab_widget))
1649 gtk_widget_event (grab_widget, event);
1652 case GDK_LEAVE_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_DRAG_STATUS:
1661 case GDK_DROP_FINISHED:
1662 _gtk_drag_source_handle_event (event_widget, event);
1664 case GDK_DRAG_ENTER:
1665 case GDK_DRAG_LEAVE:
1666 case GDK_DRAG_MOTION:
1667 case GDK_DROP_START:
1668 _gtk_drag_dest_handle_event (event_widget, event);
1671 g_assert_not_reached ();
1675 if (event->type == GDK_ENTER_NOTIFY
1676 || event->type == GDK_LEAVE_NOTIFY
1677 || event->type == GDK_BUTTON_PRESS
1678 || event->type == GDK_2BUTTON_PRESS
1679 || event->type == GDK_3BUTTON_PRESS
1680 || event->type == GDK_KEY_PRESS
1681 || event->type == GDK_DRAG_ENTER
1682 || event->type == GDK_GRAB_BROKEN
1683 || event->type == GDK_MOTION_NOTIFY
1684 || event->type == GDK_SCROLL)
1686 _gtk_tooltip_handle_event (event);
1689 tmp_list = current_events;
1690 current_events = g_list_remove_link (current_events, tmp_list);
1691 g_list_free_1 (tmp_list);
1693 if (rewritten_event)
1694 gdk_event_free (rewritten_event);
1709 static GtkWindowGroup *
1710 gtk_main_get_window_group (GtkWidget *widget)
1712 GtkWidget *toplevel = NULL;
1715 toplevel = gtk_widget_get_toplevel (widget);
1717 if (GTK_IS_WINDOW (toplevel))
1718 return gtk_window_get_group (GTK_WINDOW (toplevel));
1720 return gtk_window_get_group (NULL);
1725 GtkWidget *old_grab_widget;
1726 GtkWidget *new_grab_widget;
1727 gboolean was_grabbed;
1728 gboolean is_grabbed;
1730 GList *notified_windows;
1735 synth_crossing_for_grab_notify (GtkWidget *from,
1737 GrabNotifyInfo *info,
1739 GdkCrossingMode mode)
1743 GdkDevice *device = devices->data;
1744 GdkWindow *from_window, *to_window;
1746 /* Do not propagate events more than once to
1747 * the same windows if non-multidevice aware.
1753 from_window = _gtk_widget_get_device_window (from, device);
1756 !gdk_window_get_support_multidevice (from_window) &&
1757 g_list_find (info->notified_windows, from_window))
1765 to_window = _gtk_widget_get_device_window (to, device);
1768 !gdk_window_get_support_multidevice (to_window) &&
1769 g_list_find (info->notified_windows, to_window))
1773 if (from_window || to_window)
1775 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1776 (to_window) ? to : NULL,
1780 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1783 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1786 devices = devices->next;
1791 gtk_grab_notify_foreach (GtkWidget *child,
1794 GrabNotifyInfo *info = data;
1795 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1798 was_grabbed = info->was_grabbed;
1799 is_grabbed = info->is_grabbed;
1801 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1802 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1804 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1805 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1807 g_object_ref (child);
1809 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1810 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1813 _gtk_widget_get_device_window (child, info->device))
1815 /* Device specified and is on widget */
1816 devices = g_list_prepend (NULL, info->device);
1819 devices = _gtk_widget_list_devices (child);
1823 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1824 if (!was_shadowed && devices &&
1825 gtk_widget_is_sensitive (child))
1826 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1828 GDK_CROSSING_GTK_GRAB);
1832 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1833 if (was_shadowed && devices &&
1834 gtk_widget_is_sensitive (child))
1835 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1837 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1838 GDK_CROSSING_GTK_UNGRAB);
1841 if (was_shadowed != is_shadowed)
1842 _gtk_widget_grab_notify (child, was_shadowed);
1844 g_object_unref (child);
1845 g_list_free (devices);
1847 info->was_grabbed = was_grabbed;
1848 info->is_grabbed = is_grabbed;
1852 gtk_grab_notify (GtkWindowGroup *group,
1854 GtkWidget *old_grab_widget,
1855 GtkWidget *new_grab_widget,
1859 GrabNotifyInfo info = { 0 };
1861 if (old_grab_widget == new_grab_widget)
1864 info.old_grab_widget = old_grab_widget;
1865 info.new_grab_widget = new_grab_widget;
1866 info.from_grab = from_grab;
1867 info.device = device;
1869 g_object_ref (group);
1871 toplevels = gtk_window_list_toplevels ();
1872 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1876 GtkWindow *toplevel = toplevels->data;
1877 toplevels = g_list_delete_link (toplevels, toplevels);
1879 info.was_grabbed = FALSE;
1880 info.is_grabbed = FALSE;
1882 if (group == gtk_window_get_group (toplevel))
1883 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1884 g_object_unref (toplevel);
1887 g_list_free (info.notified_windows);
1888 g_object_unref (group);
1892 gtk_grab_add (GtkWidget *widget)
1894 GtkWindowGroup *group;
1895 GtkWidget *old_grab_widget;
1897 g_return_if_fail (widget != NULL);
1899 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1901 _gtk_widget_set_has_grab (widget, TRUE);
1903 group = gtk_main_get_window_group (widget);
1906 old_grab_widget = (GtkWidget *)group->grabs->data;
1908 old_grab_widget = NULL;
1910 g_object_ref (widget);
1911 group->grabs = g_slist_prepend (group->grabs, widget);
1913 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1918 gtk_grab_get_current (void)
1920 GtkWindowGroup *group;
1922 group = gtk_main_get_window_group (NULL);
1925 return GTK_WIDGET (group->grabs->data);
1930 gtk_grab_remove (GtkWidget *widget)
1932 GtkWindowGroup *group;
1933 GtkWidget *new_grab_widget;
1935 g_return_if_fail (widget != NULL);
1937 if (gtk_widget_has_grab (widget))
1939 _gtk_widget_set_has_grab (widget, FALSE);
1941 group = gtk_main_get_window_group (widget);
1942 group->grabs = g_slist_remove (group->grabs, widget);
1945 new_grab_widget = (GtkWidget *)group->grabs->data;
1947 new_grab_widget = NULL;
1949 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
1951 g_object_unref (widget);
1956 * gtk_device_grab_add:
1957 * @widget: a #GtkWidget
1958 * @device: a #GtkDevice to grab on.
1959 * @block_others: %TRUE to prevent other devices to interact with @widget.
1961 * Adds a GTK+ grab on @device, so all the events on @device and its
1962 * associated pointer or keyboard (if any) are delivered to @widget.
1963 * If the @block_others parameter is %TRUE, any other devices will be
1964 * unable to interact with @widget during the grab.
1969 gtk_device_grab_add (GtkWidget *widget,
1971 gboolean block_others)
1973 GtkWindowGroup *group;
1974 GtkWidget *old_grab_widget;
1976 g_return_if_fail (GTK_IS_WIDGET (widget));
1977 g_return_if_fail (GDK_IS_DEVICE (device));
1979 group = gtk_main_get_window_group (widget);
1980 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
1982 if (old_grab_widget != widget)
1983 _gtk_window_group_add_device_grab (group, widget, device, block_others);
1985 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
1989 * gtk_device_grab_remove:
1990 * @widget: a #GtkWidget
1991 * @device: a #GdkDevice
1993 * Removes a device grab from the given widget. You have to pair calls
1994 * to gtk_device_grab_add() and gtk_device_grab_remove().
1999 gtk_device_grab_remove (GtkWidget *widget,
2002 GtkWindowGroup *group;
2003 GtkWidget *new_grab_widget;
2005 g_return_if_fail (GTK_IS_WIDGET (widget));
2006 g_return_if_fail (GDK_IS_DEVICE (device));
2008 group = gtk_main_get_window_group (widget);
2009 _gtk_window_group_remove_device_grab (group, widget, device);
2010 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2012 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2016 gtk_init_add (GtkFunction function,
2019 GtkInitFunction *init;
2021 init = g_new (GtkInitFunction, 1);
2022 init->function = function;
2025 init_functions = g_list_prepend (init_functions, init);
2029 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2032 GtkKeySnooperData *data;
2033 static guint snooper_id = 1;
2035 g_return_val_if_fail (snooper != NULL, 0);
2037 data = g_new (GtkKeySnooperData, 1);
2038 data->func = snooper;
2039 data->func_data = func_data;
2040 data->id = snooper_id++;
2041 key_snoopers = g_slist_prepend (key_snoopers, data);
2047 gtk_key_snooper_remove (guint snooper_id)
2049 GtkKeySnooperData *data = NULL;
2052 slist = key_snoopers;
2056 if (data->id == snooper_id)
2059 slist = slist->next;
2064 key_snoopers = g_slist_remove (key_snoopers, data);
2070 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2074 gint return_val = FALSE;
2076 slist = key_snoopers;
2077 while (slist && !return_val)
2079 GtkKeySnooperData *data;
2082 slist = slist->next;
2083 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2090 gtk_quit_add_full (guint main_level,
2091 GtkFunction function,
2092 GtkCallbackMarshal marshal,
2094 GDestroyNotify destroy)
2096 static guint quit_id = 1;
2097 GtkQuitFunction *quitf;
2099 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2101 quitf = g_slice_new (GtkQuitFunction);
2103 quitf->id = quit_id++;
2104 quitf->main_level = main_level;
2105 quitf->function = function;
2106 quitf->marshal = marshal;
2108 quitf->destroy = destroy;
2110 quit_functions = g_list_prepend (quit_functions, quitf);
2116 gtk_quit_destroy (GtkQuitFunction *quitf)
2119 quitf->destroy (quitf->data);
2120 g_slice_free (GtkQuitFunction, quitf);
2124 gtk_quit_destructor (GtkObject **object_p)
2127 gtk_object_destroy (*object_p);
2134 gtk_quit_add_destroy (guint main_level,
2137 GtkObject **object_p;
2139 g_return_if_fail (main_level > 0);
2140 g_return_if_fail (GTK_IS_OBJECT (object));
2142 object_p = g_new (GtkObject*, 1);
2144 g_signal_connect (object,
2146 G_CALLBACK (gtk_widget_destroyed),
2148 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2152 gtk_quit_add (guint main_level,
2153 GtkFunction function,
2156 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2160 gtk_quit_remove (guint id)
2162 GtkQuitFunction *quitf;
2165 tmp_list = quit_functions;
2168 quitf = tmp_list->data;
2170 if (quitf->id == id)
2172 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2173 g_list_free (tmp_list);
2174 gtk_quit_destroy (quitf);
2179 tmp_list = tmp_list->next;
2184 gtk_quit_remove_by_data (gpointer data)
2186 GtkQuitFunction *quitf;
2189 tmp_list = quit_functions;
2192 quitf = tmp_list->data;
2194 if (quitf->data == data)
2196 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2197 g_list_free (tmp_list);
2198 gtk_quit_destroy (quitf);
2203 tmp_list = tmp_list->next;
2208 * gtk_get_current_event:
2210 * Obtains a copy of the event currently being processed by GTK+. For
2211 * example, if you get a "clicked" signal from #GtkButton, the current
2212 * event will be the #GdkEventButton that triggered the "clicked"
2213 * signal. The returned event must be freed with gdk_event_free().
2214 * If there is no current event, the function returns %NULL.
2216 * Return value: a copy of the current event, or %NULL if no current event.
2219 gtk_get_current_event (void)
2222 return gdk_event_copy (current_events->data);
2228 * gtk_get_current_event_time:
2230 * If there is a current event and it has a timestamp, return that
2231 * timestamp, otherwise return %GDK_CURRENT_TIME.
2233 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2236 gtk_get_current_event_time (void)
2239 return gdk_event_get_time (current_events->data);
2241 return GDK_CURRENT_TIME;
2245 * gtk_get_current_event_state:
2246 * @state: a location to store the state of the current event
2248 * If there is a current event and it has a state field, place
2249 * that state field in @state and return %TRUE, otherwise return
2252 * Return value: %TRUE if there was a current event and it had a state field
2255 gtk_get_current_event_state (GdkModifierType *state)
2257 g_return_val_if_fail (state != NULL, FALSE);
2260 return gdk_event_get_state (current_events->data, state);
2269 * gtk_get_current_event_device:
2271 * If there is a current event and it has a device, return that
2272 * device, otherwise return %NULL.
2274 * Returns: a #GdkDevice, or %NULL
2277 gtk_get_current_event_device (void)
2280 return gdk_event_get_device (current_events->data);
2286 * gtk_get_event_widget:
2287 * @event: a #GdkEvent
2289 * If @event is %NULL or the event was not associated with any widget,
2290 * returns %NULL, otherwise returns the widget that received the event
2293 * Return value: the widget that originally received @event, or %NULL
2296 gtk_get_event_widget (GdkEvent *event)
2299 gpointer widget_ptr;
2302 if (event && event->any.window &&
2303 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2305 gdk_window_get_user_data (event->any.window, &widget_ptr);
2306 widget = widget_ptr;
2313 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2315 if (!quitf->marshal)
2316 return quitf->function (quitf->data);
2320 gint ret_val = FALSE;
2322 args[0].name = NULL;
2323 args[0].type = G_TYPE_BOOLEAN;
2324 args[0].d.pointer_data = &ret_val;
2325 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2333 * gtk_propagate_event:
2334 * @widget: a #GtkWidget
2337 * Sends an event to a widget, propagating the event to parent widgets
2338 * if the event remains unhandled. Events received by GTK+ from GDK
2339 * normally begin in gtk_main_do_event(). Depending on the type of
2340 * event, existence of modal dialogs, grabs, etc., the event may be
2341 * propagated; if so, this function is used. gtk_propagate_event()
2342 * calls gtk_widget_event() on each widget it decides to send the
2343 * event to. So gtk_widget_event() is the lowest-level function; it
2344 * simply emits the "event" and possibly an event-specific signal on a
2345 * widget. gtk_propagate_event() is a bit higher-level, and
2346 * gtk_main_do_event() is the highest level.
2348 * All that said, you most likely don't want to use any of these
2349 * functions; synthesizing events is rarely needed. Consider asking on
2350 * the mailing list for better ways to achieve your goals. For
2351 * example, use gdk_window_invalidate_rect() or
2352 * gtk_widget_queue_draw() instead of making up expose events.
2356 gtk_propagate_event (GtkWidget *widget,
2361 g_return_if_fail (GTK_IS_WIDGET (widget));
2362 g_return_if_fail (event != NULL);
2364 handled_event = FALSE;
2366 g_object_ref (widget);
2368 if ((event->type == GDK_KEY_PRESS) ||
2369 (event->type == GDK_KEY_RELEASE))
2371 /* Only send key events within Window widgets to the Window
2372 * The Window widget will in turn pass the
2373 * key event on to the currently focused widget
2378 window = gtk_widget_get_toplevel (widget);
2379 if (GTK_IS_WINDOW (window))
2381 /* If there is a grab within the window, give the grab widget
2382 * a first crack at the key event
2384 if (widget != window && gtk_widget_has_grab (widget))
2385 handled_event = gtk_widget_event (widget, event);
2389 window = gtk_widget_get_toplevel (widget);
2390 if (GTK_IS_WINDOW (window))
2392 if (gtk_widget_is_sensitive (window))
2393 gtk_widget_event (window, event);
2397 handled_event = TRUE; /* don't send to widget */
2401 /* Other events get propagated up the widget tree
2402 * so that parents can see the button and motion
2403 * events of the children.
2411 /* Scroll events are special cased here because it
2412 * feels wrong when scrolling a GtkViewport, say,
2413 * to have children of the viewport eat the scroll
2416 if (!gtk_widget_is_sensitive (widget))
2417 handled_event = event->type != GDK_SCROLL;
2419 handled_event = gtk_widget_event (widget, event);
2421 tmp = widget->parent;
2422 g_object_unref (widget);
2426 if (!handled_event && widget)
2427 g_object_ref (widget);
2433 g_object_unref (widget);
2438 gtk_error (gchar *str)
2444 gtk_warning (gchar *str)
2450 gtk_message (gchar *str)
2456 gtk_print (gchar *str)
2458 static GtkWidget *window = NULL;
2459 static GtkWidget *text;
2460 static int level = 0;
2464 GtkWidget *hscrollbar;
2465 GtkWidget *vscrollbar;
2466 GtkWidget *separator;
2471 fputs (str, stdout);
2478 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2480 g_signal_connect (window, "destroy",
2481 G_CALLBACK (gtk_widget_destroyed), &window);
2483 gtk_window_set_title (GTK_WINDOW (window), "Messages");
2485 box1 = gtk_vbox_new (FALSE, 0);
2486 gtk_container_add (GTK_CONTAINER (window), box1);
2487 gtk_widget_show (box1);
2490 box2 = gtk_vbox_new (FALSE, 10);
2491 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2492 gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2493 gtk_widget_show (box2);
2496 table = gtk_table_new (2, 2, FALSE);
2497 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2498 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2499 gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2500 gtk_widget_show (table);
2502 text = gtk_text_new (NULL, NULL);
2503 gtk_text_set_editable (GTK_TEXT (text), FALSE);
2504 gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2505 gtk_widget_show (text);
2506 gtk_widget_realize (text);
2508 hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2509 gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2510 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2511 gtk_widget_show (hscrollbar);
2513 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2514 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2515 GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2516 gtk_widget_show (vscrollbar);
2518 separator = gtk_hseparator_new ();
2519 gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2520 gtk_widget_show (separator);
2523 box2 = gtk_vbox_new (FALSE, 10);
2524 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2525 gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2526 gtk_widget_show (box2);
2529 button = gtk_button_new_with_label ("close");
2530 g_signal_connect_swapped (button, "clicked",
2531 G_CALLBACK (gtk_widget_hide), window);
2532 gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2533 gtk_widget_set_can_default (button, TRUE);
2534 gtk_widget_grab_default (button);
2535 gtk_widget_show (button);
2539 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2542 if (!gtk_widget_get_visible (window))
2543 gtk_widget_show (window);
2548 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2549 GValue *return_accu,
2550 const GValue *handler_return,
2553 gboolean continue_emission;
2554 gboolean signal_handled;
2556 signal_handled = g_value_get_boolean (handler_return);
2557 g_value_set_boolean (return_accu, signal_handled);
2558 continue_emission = !signal_handled;
2560 return continue_emission;
2563 #define __GTK_MAIN_C__
2564 #include "gtkaliasdef.c"