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,
189 static void gtk_destroy_closure (gpointer data);
190 static gboolean gtk_invoke_idle_timeout (gpointer data);
191 static void gtk_invoke_input (gpointer data,
193 GdkInputCondition condition);
196 static void gtk_error (gchar *str);
197 static void gtk_warning (gchar *str);
198 static void gtk_message (gchar *str);
199 static void gtk_print (gchar *str);
202 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
204 const guint gtk_major_version = GTK_MAJOR_VERSION;
205 const guint gtk_minor_version = GTK_MINOR_VERSION;
206 const guint gtk_micro_version = GTK_MICRO_VERSION;
207 const guint gtk_binary_age = GTK_BINARY_AGE;
208 const guint gtk_interface_age = GTK_INTERFACE_AGE;
210 static guint gtk_main_loop_level = 0;
211 static gint pre_initialized = FALSE;
212 static gint gtk_initialized = FALSE;
213 static GList *current_events = NULL;
215 static GSList *main_loops = NULL; /* stack of currently executing main loops */
217 static GList *init_functions = NULL; /* A list of init functions.
219 static GList *quit_functions = NULL; /* A list of quit functions.
221 static GSList *key_snoopers = NULL;
223 guint gtk_debug_flags = 0; /* Global GTK debug flag */
225 #ifdef G_ENABLE_DEBUG
226 static const GDebugKey gtk_debug_keys[] = {
227 {"misc", GTK_DEBUG_MISC},
228 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
229 {"text", GTK_DEBUG_TEXT},
230 {"tree", GTK_DEBUG_TREE},
231 {"updates", GTK_DEBUG_UPDATES},
232 {"keybindings", GTK_DEBUG_KEYBINDINGS},
233 {"multihead", GTK_DEBUG_MULTIHEAD},
234 {"modules", GTK_DEBUG_MODULES},
235 {"geometry", GTK_DEBUG_GEOMETRY},
236 {"icontheme", GTK_DEBUG_ICONTHEME},
237 {"printing", GTK_DEBUG_PRINTING},
238 {"builder", GTK_DEBUG_BUILDER}
240 #endif /* G_ENABLE_DEBUG */
244 * @required_major: the required major version.
245 * @required_minor: the required minor version.
246 * @required_micro: the required micro version.
248 * Checks that the GTK+ library in use is compatible with the
249 * given version. Generally you would pass in the constants
250 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
251 * as the three arguments to this function; that produces
252 * a check that the library in use is compatible with
253 * the version of GTK+ the application or module was compiled
256 * Compatibility is defined by two things: first the version
257 * of the running library is newer than the version
258 * @required_major.required_minor.@required_micro. Second
259 * the running library must be binary compatible with the
260 * version @required_major.required_minor.@required_micro
261 * (same major version.)
263 * This function is primarily for GTK+ modules; the module
264 * can call this function to check that it wasn't loaded
265 * into an incompatible version of GTK+. However, such a
266 * a check isn't completely reliable, since the module may be
267 * linked against an old version of GTK+ and calling the
268 * old version of gtk_check_version(), but still get loaded
269 * into an application using a newer version of GTK+.
271 * Return value: %NULL if the GTK+ library is compatible with the
272 * given version, or a string describing the version mismatch.
273 * The returned string is owned by GTK+ and should not be modified
277 gtk_check_version (guint required_major,
278 guint required_minor,
279 guint required_micro)
281 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
282 gint required_effective_micro = 100 * required_minor + required_micro;
284 if (required_major > GTK_MAJOR_VERSION)
285 return "Gtk+ version too old (major mismatch)";
286 if (required_major < GTK_MAJOR_VERSION)
287 return "Gtk+ version too new (major mismatch)";
288 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
289 return "Gtk+ version too new (micro mismatch)";
290 if (required_effective_micro > gtk_effective_micro)
291 return "Gtk+ version too old (micro mismatch)";
295 /* This checks to see if the process is running suid or sgid
296 * at the current time. If so, we don't allow GTK+ to be initialized.
297 * This is meant to be a mild check - we only error out if we
298 * can prove the programmer is doing something wrong, not if
299 * they could be doing something wrong. For this reason, we
300 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
305 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
307 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
308 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
310 #ifdef HAVE_GETRESUID
311 /* These aren't in the header files, so we prototype them here.
313 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
314 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
316 if (getresuid (&ruid, &euid, &suid) != 0 ||
317 getresgid (&rgid, &egid, &sgid) != 0)
318 #endif /* HAVE_GETRESUID */
320 suid = ruid = getuid ();
321 sgid = rgid = getgid ();
326 if (ruid != euid || ruid != suid ||
327 rgid != egid || rgid != sgid)
329 g_warning ("This process is currently running setuid or setgid.\n"
330 "This is not a supported use of GTK+. You must create a helper\n"
331 "program instead. For further details, see:\n\n"
332 " http://www.gtk.org/setuid.html\n\n"
333 "Refusing to initialize GTK+.");
343 _gtk_get_datadir (void)
345 static char *gtk_datadir = NULL;
346 if (gtk_datadir == NULL)
348 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
349 gtk_datadir = g_build_filename (root, "share", NULL);
357 _gtk_get_sysconfdir (void)
359 static char *gtk_sysconfdir = NULL;
360 if (gtk_sysconfdir == NULL)
362 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
363 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
367 return gtk_sysconfdir;
371 _gtk_get_data_prefix (void)
373 static char *gtk_data_prefix = NULL;
374 if (gtk_data_prefix == NULL)
375 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
377 return gtk_data_prefix;
380 #endif /* G_OS_WIN32 */
382 static gboolean do_setlocale = TRUE;
385 * gtk_disable_setlocale:
387 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
388 * gtk_parse_args() from automatically
389 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
390 * want to use this function if you wanted to set the locale for
391 * your program to something other than the user's locale, or if
392 * you wanted to set different values for different locale categories.
394 * Most programs should not need to call this function.
397 gtk_disable_setlocale (void)
400 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
402 do_setlocale = FALSE;
405 #ifdef G_PLATFORM_WIN32
406 #undef gtk_init_check
409 static GString *gtk_modules_string = NULL;
410 static gboolean g_fatal_warnings = FALSE;
412 #ifdef G_ENABLE_DEBUG
414 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
416 gtk_debug_flags |= g_parse_debug_string (value,
418 G_N_ELEMENTS (gtk_debug_keys));
424 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
426 gtk_debug_flags &= ~g_parse_debug_string (value,
428 G_N_ELEMENTS (gtk_debug_keys));
432 #endif /* G_ENABLE_DEBUG */
435 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
439 if (gtk_modules_string)
440 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
442 gtk_modules_string = g_string_new (NULL);
444 g_string_append (gtk_modules_string, value);
450 static const GOptionEntry gtk_args[] = {
451 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
452 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
453 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
454 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
455 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
456 #ifdef G_ENABLE_DEBUG
457 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
458 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
459 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
460 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
461 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
462 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
469 static char *iso639_to_check = NULL;
470 static char *iso3166_to_check = NULL;
471 static char *script_to_check = NULL;
472 static gboolean setlocale_called = FALSE;
475 enum_locale_proc (LPTSTR locale)
483 lcid = strtoul (locale, &endptr, 16);
484 if (*endptr == '\0' &&
485 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
486 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
488 if (strcmp (iso639, iso639_to_check) == 0 &&
489 ((iso3166_to_check != NULL &&
490 strcmp (iso3166, iso3166_to_check) == 0) ||
491 (iso3166_to_check == NULL &&
492 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
494 char language[100], country[100];
497 if (script_to_check != NULL)
499 /* If lcid is the "other" script for this language,
500 * return TRUE, i.e. continue looking.
502 if (strcmp (script_to_check, "Latn") == 0)
504 switch (LANGIDFROMLCID (lcid))
506 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
508 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
510 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
512 case MAKELANGID (LANG_SERBIAN, 0x07):
513 /* Serbian in Bosnia and Herzegovina, Cyrillic */
517 else if (strcmp (script_to_check, "Cyrl") == 0)
519 switch (LANGIDFROMLCID (lcid))
521 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
523 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
525 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
527 case MAKELANGID (LANG_SERBIAN, 0x06):
528 /* Serbian in Bosnia and Herzegovina, Latin */
534 SetThreadLocale (lcid);
536 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
537 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
539 strcpy (locale, language);
540 strcat (locale, "_");
541 strcat (locale, country);
543 if (setlocale (LC_ALL, locale) != NULL)
544 setlocale_called = TRUE;
557 setlocale_initialization (void)
559 static gboolean initialized = FALSE;
568 /* If some of the POSIXish environment variables are set, set
569 * the Win32 thread locale correspondingly.
571 char *p = getenv ("LC_ALL");
578 if (strcmp (p, "C") == 0)
579 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
582 /* Check if one of the supported locales match the
583 * environment variable. If so, use that locale.
586 iso3166_to_check = strchr (iso639_to_check, '_');
587 if (iso3166_to_check != NULL)
589 *iso3166_to_check++ = '\0';
591 script_to_check = strchr (iso3166_to_check, '@');
592 if (script_to_check != NULL)
593 *script_to_check++ = '\0';
595 /* Handle special cases. */
597 /* The standard code for Serbia and Montenegro was
598 * "CS", but MSFT uses for some reason "SP". By now
599 * (October 2006), SP has split into two, "RS" and
600 * "ME", but don't bother trying to handle those
601 * yet. Do handle the even older "YU", though.
603 if (strcmp (iso3166_to_check, "CS") == 0 ||
604 strcmp (iso3166_to_check, "YU") == 0)
605 iso3166_to_check = "SP";
609 script_to_check = strchr (iso639_to_check, '@');
610 if (script_to_check != NULL)
611 *script_to_check++ = '\0';
612 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
613 if (strcmp (iso639_to_check, "sr") == 0)
614 iso3166_to_check = "SP";
617 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
621 if (!setlocale_called)
622 setlocale (LC_ALL, "");
624 if (!setlocale (LC_ALL, ""))
625 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
631 do_pre_parse_initialization (int *argc,
634 const gchar *env_string;
637 g_set_error_handler (gtk_error);
638 g_set_warning_handler (gtk_warning);
639 g_set_message_handler (gtk_message);
640 g_set_print_handler (gtk_print);
646 pre_initialized = TRUE;
648 gdk_pre_parse_libgtk_only ();
649 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
651 #ifdef G_ENABLE_DEBUG
652 env_string = g_getenv ("GTK_DEBUG");
653 if (env_string != NULL)
655 gtk_debug_flags = g_parse_debug_string (env_string,
657 G_N_ELEMENTS (gtk_debug_keys));
660 #endif /* G_ENABLE_DEBUG */
662 env_string = g_getenv ("GTK_MODULES");
664 gtk_modules_string = g_string_new (env_string);
668 gettext_initialization (void)
670 setlocale_initialization ();
673 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
674 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
675 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
676 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
677 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
683 do_post_parse_initialization (int *argc,
689 gettext_initialization ();
692 signal (SIGPIPE, SIG_IGN);
695 if (g_fatal_warnings)
697 GLogLevelFlags fatal_mask;
699 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
700 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
701 g_log_set_always_fatal (fatal_mask);
704 if (gtk_debug_flags & GTK_DEBUG_UPDATES)
705 gdk_window_set_debug_updates (TRUE);
708 /* Translate to default:RTL if you want your widgets
709 * to be RTL, otherwise translate to default:LTR.
710 * Do *not* translate it to "predefinito:LTR", if it
711 * it isn't default:LTR or default:RTL it will not work
713 char *e = _("default:LTR");
714 if (strcmp (e, "default:RTL")==0)
715 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
716 else if (strcmp (e, "default:LTR"))
717 g_warning ("Whoever translated default:LTR did so wrongly.\n");
720 /* do what the call to gtk_type_init() used to do */
723 _gtk_accel_map_init ();
726 /* Set the 'initialized' flag.
728 gtk_initialized = TRUE;
730 /* load gtk modules */
731 if (gtk_modules_string)
733 _gtk_modules_init (argc, argv, gtk_modules_string->str);
734 g_string_free (gtk_modules_string, TRUE);
738 _gtk_modules_init (argc, argv, NULL);
745 gboolean open_default_display;
749 pre_parse_hook (GOptionContext *context,
754 do_pre_parse_initialization (NULL, NULL);
760 post_parse_hook (GOptionContext *context,
765 OptionGroupInfo *info = data;
768 do_post_parse_initialization (NULL, NULL);
770 if (info->open_default_display)
772 if (gdk_display_open_default_libgtk_only () == NULL)
774 const char *display_name = gdk_get_display_arg_name ();
777 G_OPTION_ERROR_FAILED,
778 _("Cannot open display: %s"),
779 display_name ? display_name : "" );
790 * gtk_get_option_group:
791 * @open_default_display: whether to open the default display
792 * when parsing the commandline arguments
794 * Returns a #GOptionGroup for the commandline arguments recognized
795 * by GTK+ and GDK. You should add this group to your #GOptionContext
796 * with g_option_context_add_group(), if you are using
797 * g_option_context_parse() to parse your commandline arguments.
799 * Returns: a #GOptionGroup for the commandline arguments recognized
805 gtk_get_option_group (gboolean open_default_display)
808 OptionGroupInfo *info;
810 gettext_initialization ();
812 info = g_new0 (OptionGroupInfo, 1);
813 info->open_default_display = open_default_display;
815 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
816 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
818 gdk_add_option_entries_libgtk_only (group);
819 g_option_group_add_entries (group, gtk_args);
820 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
826 * gtk_init_with_args:
827 * @argc: a pointer to the number of command line arguments.
828 * @argv: a pointer to the array of command line arguments.
829 * @parameter_string: a string which is displayed in
830 * the first line of <option>--help</option> output, after
831 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
832 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
833 * describing the options of your program
834 * @translation_domain: a translation domain to use for translating
835 * the <option>--help</option> output for the options in @entries
836 * with gettext(), or %NULL
837 * @error: a return location for errors
839 * This function does the same work as gtk_init_check().
840 * Additionally, it allows you to add your own commandline options,
841 * and it automatically generates nicely formatted
842 * <option>--help</option> output. Note that your program will
843 * be terminated after writing out the help output.
845 * Returns: %TRUE if the GUI has been successfully initialized,
851 gtk_init_with_args (int *argc,
853 const char *parameter_string,
854 GOptionEntry *entries,
855 const char *translation_domain,
858 GOptionContext *context;
859 GOptionGroup *gtk_group;
863 return gdk_display_open_default_libgtk_only () != NULL;
865 gettext_initialization ();
867 if (!check_setugid ())
870 gtk_group = gtk_get_option_group (TRUE);
872 context = g_option_context_new (parameter_string);
873 g_option_context_add_group (context, gtk_group);
876 g_option_context_add_main_entries (context, entries, translation_domain);
877 retval = g_option_context_parse (context, argc, argv, error);
879 g_option_context_free (context);
887 * @argc: (inout): a pointer to the number of command line arguments.
888 * @argv: (array) (inout): a pointer to the array of command line arguments.
890 * Parses command line arguments, and initializes global
891 * attributes of GTK+, but does not actually open a connection
892 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
894 * Any arguments used by GTK+ or GDK are removed from the array and
895 * @argc and @argv are updated accordingly.
897 * You shouldn't call this function explicitely if you are using
898 * gtk_init(), or gtk_init_check().
900 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
903 gtk_parse_args (int *argc,
906 GOptionContext *option_context;
907 GOptionGroup *gtk_group;
908 GError *error = NULL;
913 gettext_initialization ();
915 if (!check_setugid ())
918 option_context = g_option_context_new (NULL);
919 g_option_context_set_ignore_unknown_options (option_context, TRUE);
920 g_option_context_set_help_enabled (option_context, FALSE);
921 gtk_group = gtk_get_option_group (FALSE);
922 g_option_context_set_main_group (option_context, gtk_group);
923 if (!g_option_context_parse (option_context, argc, argv, &error))
925 g_warning ("%s", error->message);
926 g_error_free (error);
929 g_option_context_free (option_context);
934 #ifdef G_PLATFORM_WIN32
935 #undef gtk_init_check
940 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
941 * main() function. Changed if any arguments were handled.
942 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
943 * Any parameters understood by gtk_init() are stripped before return.
945 * This function does the same work as gtk_init() with only
946 * a single change: It does not terminate the program if the GUI can't be
947 * initialized. Instead it returns %FALSE on failure.
949 * This way the application can fall back to some other means of communication
950 * with the user - for example a curses or command line interface.
952 * Return value: %TRUE if the GUI has been successfully initialized,
956 gtk_init_check (int *argc,
959 if (!gtk_parse_args (argc, argv))
962 return gdk_display_open_default_libgtk_only () != NULL;
965 #ifdef G_PLATFORM_WIN32
971 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
972 * main() function. Changed if any arguments were handled.
973 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
974 * Any parameters understood by gtk_init() are stripped before return.
976 * Call this function before using any other GTK+ functions in your GUI
977 * applications. It will initialize everything needed to operate the
978 * toolkit and parses some standard command line options. @argc and
979 * @argv are adjusted accordingly so your own code will
980 * never see those standard arguments.
982 * Note that there are some alternative ways to initialize GTK+:
983 * if you are calling gtk_parse_args(), gtk_init_check(),
984 * gtk_init_with_args() or g_option_context_parse() with
985 * the option group returned by gtk_get_option_group(), you
986 * <emphasis>don't</emphasis> have to call gtk_init().
989 * This function will terminate your program if it was unable to initialize
990 * the GUI for some reason. If you want your program to fall back to a
991 * textual interface you want to call gtk_init_check() instead.
995 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
996 * during initialization, to ignore SIGPIPE signals, since these are
997 * almost never wanted in graphical applications. If you do need to
998 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
999 * but notice that other libraries (e.g. libdbus or gvfs) might do
1004 gtk_init (int *argc, char ***argv)
1006 if (!gtk_init_check (argc, argv))
1008 const char *display_name_arg = gdk_get_display_arg_name ();
1009 if (display_name_arg == NULL)
1010 display_name_arg = getenv("DISPLAY");
1011 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1016 #ifdef G_PLATFORM_WIN32
1019 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1021 if (sizeof_GtkWindow != sizeof (GtkWindow))
1022 g_error ("Incompatible build!\n"
1023 "The code using GTK+ thinks GtkWindow is of different\n"
1024 "size than it actually is in this build of GTK+.\n"
1025 "On Windows, this probably means that you have compiled\n"
1026 "your code with gcc without the -mms-bitfields switch,\n"
1027 "or that you are using an unsupported compiler.");
1030 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1031 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1032 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1033 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1034 * -fnative-struct still matters. GtkBox is one such.
1037 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1039 if (sizeof_GtkBox != sizeof (GtkBox))
1040 g_error ("Incompatible build!\n"
1041 "The code using GTK+ thinks GtkBox is of different\n"
1042 "size than it actually is in this build of GTK+.\n"
1043 "On Windows, this probably means that you have compiled\n"
1044 "your code with gcc without the -mms-bitfields switch,\n"
1045 "or that you are using an unsupported compiler.");
1048 /* These two functions might get more checks added later, thus pass
1049 * in the number of extra args.
1052 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1054 check_sizeof_GtkWindow (sizeof_GtkWindow);
1055 if (num_checks >= 2)
1056 check_sizeof_GtkBox (sizeof_GtkBox);
1057 gtk_init (argc, argv);
1061 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1063 check_sizeof_GtkWindow (sizeof_GtkWindow);
1064 if (num_checks >= 2)
1065 check_sizeof_GtkBox (sizeof_GtkBox);
1066 return gtk_init_check (argc, argv);
1072 gtk_exit (gint errorcode)
1081 * Initializes internationalization support for GTK+. gtk_init()
1082 * automatically does this, so there is typically no point
1083 * in calling this function.
1085 * If you are calling this function because you changed the locale
1086 * after GTK+ is was initialized, then calling this function
1087 * may help a bit. (Note, however, that changing the locale
1088 * after GTK+ is initialized may produce inconsistent results and
1089 * is not really supported.)
1091 * In detail - sets the current locale according to the
1092 * program environment. This is the same as calling the C library function
1093 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1094 * locale specific setup of the windowing system used by GDK.
1096 * Returns: a string corresponding to the locale set, typically in the
1097 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1098 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1099 * result of the setlocale(); it is also used on other machines, such as
1100 * Windows, where the C library returns a different result. The string is
1101 * owned by GTK+ and should not be modified or freed.
1104 gtk_set_locale (void)
1106 return gdk_set_locale ();
1110 * _gtk_get_lc_ctype:
1112 * Return the Unix-style locale string for the language currently in
1113 * effect. On Unix systems, this is the return value from
1114 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1115 * affect this through the environment variables LC_ALL, LC_CTYPE or
1116 * LANG (checked in that order). The locale strings typically is in
1117 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1118 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1119 * Swedish as written in Finland or pt_BR for Portuguese as written in
1122 * On Windows, the C library doesn't use any such environment
1123 * variables, and setting them won't affect the behaviour of functions
1124 * like ctime(). The user sets the locale through the Regional Options
1125 * in the Control Panel. The C library (in the setlocale() function)
1126 * does not use country and language codes, but country and language
1127 * names spelled out in English.
1128 * However, this function does check the above environment
1129 * variables, and does return a Unix-style locale string based on
1130 * either said environment variables or the thread's current locale.
1132 * Return value: a dynamically allocated string, free with g_free().
1136 _gtk_get_lc_ctype (void)
1139 /* Somebody might try to set the locale for this process using the
1140 * LANG or LC_ environment variables. The Microsoft C library
1141 * doesn't know anything about them. You set the locale in the
1142 * Control Panel. Setting these env vars won't have any affect on
1143 * locale-dependent C library functions like ctime(). But just for
1144 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1145 * it easier to test GTK and Pango in various default languages, you
1146 * don't have to clickety-click in the Control Panel, you can simply
1147 * start the program with LC_ALL=something on the command line.)
1151 p = getenv ("LC_ALL");
1153 return g_strdup (p);
1155 p = getenv ("LC_CTYPE");
1157 return g_strdup (p);
1159 p = getenv ("LANG");
1161 return g_strdup (p);
1163 return g_win32_getlocale ();
1165 return g_strdup (setlocale (LC_CTYPE, NULL));
1170 * gtk_get_default_language:
1172 * Returns the #PangoLanguage for the default language currently in
1173 * effect. (Note that this can change over the life of an
1174 * application.) The default language is derived from the current
1175 * locale. It determines, for example, whether GTK+ uses the
1176 * right-to-left or left-to-right text direction.
1178 * This function is equivalent to pango_language_get_default(). See
1179 * that function for details.
1181 * Return value: the default language as a #PangoLanguage, must not be
1185 gtk_get_default_language (void)
1187 return pango_language_get_default ();
1195 GtkInitFunction *init;
1198 gtk_main_loop_level++;
1200 loop = g_main_loop_new (NULL, TRUE);
1201 main_loops = g_slist_prepend (main_loops, loop);
1203 tmp_list = functions = init_functions;
1204 init_functions = NULL;
1208 init = tmp_list->data;
1209 tmp_list = tmp_list->next;
1211 (* init->function) (init->data);
1214 g_list_free (functions);
1216 if (g_main_loop_is_running (main_loops->data))
1218 GDK_THREADS_LEAVE ();
1219 g_main_loop_run (loop);
1220 GDK_THREADS_ENTER ();
1226 GList *reinvoke_list = NULL;
1227 GtkQuitFunction *quitf;
1229 while (quit_functions)
1231 quitf = quit_functions->data;
1233 tmp_list = quit_functions;
1234 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1235 g_list_free_1 (tmp_list);
1237 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1238 gtk_quit_invoke_function (quitf))
1240 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1244 gtk_quit_destroy (quitf);
1251 work = g_list_last (reinvoke_list);
1253 quit_functions->prev = work;
1254 work->next = quit_functions;
1255 quit_functions = work;
1261 main_loops = g_slist_remove (main_loops, loop);
1263 g_main_loop_unref (loop);
1265 gtk_main_loop_level--;
1267 if (gtk_main_loop_level == 0)
1269 /* Try storing all clipboard data we have */
1270 _gtk_clipboard_store_all ();
1272 /* Synchronize the recent manager singleton */
1273 _gtk_recent_manager_sync ();
1278 gtk_main_level (void)
1280 return gtk_main_loop_level;
1284 gtk_main_quit (void)
1286 g_return_if_fail (main_loops != NULL);
1288 g_main_loop_quit (main_loops->data);
1292 gtk_events_pending (void)
1296 GDK_THREADS_LEAVE ();
1297 result = g_main_context_pending (NULL);
1298 GDK_THREADS_ENTER ();
1304 gtk_main_iteration (void)
1306 GDK_THREADS_LEAVE ();
1307 g_main_context_iteration (NULL, TRUE);
1308 GDK_THREADS_ENTER ();
1311 return !g_main_loop_is_running (main_loops->data);
1317 gtk_main_iteration_do (gboolean blocking)
1319 GDK_THREADS_LEAVE ();
1320 g_main_context_iteration (NULL, blocking);
1321 GDK_THREADS_ENTER ();
1324 return !g_main_loop_is_running (main_loops->data);
1329 /* private libgtk to libgdk interfaces
1331 gboolean gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
1332 GdkWindow **grab_window,
1333 gboolean *owner_events);
1334 gboolean gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1335 GdkWindow **grab_window,
1336 gboolean *owner_events);
1339 rewrite_events_translate (GdkWindow *old_window,
1340 GdkWindow *new_window,
1344 gint old_origin_x, old_origin_y;
1345 gint new_origin_x, new_origin_y;
1347 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1348 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1350 *x += old_origin_x - new_origin_x;
1351 *y += old_origin_y - new_origin_y;
1355 rewrite_event_for_window (GdkEvent *event,
1356 GdkWindow *new_window)
1358 event = gdk_event_copy (event);
1360 switch (event->type)
1363 rewrite_events_translate (event->any.window,
1365 &event->scroll.x, &event->scroll.y);
1367 case GDK_BUTTON_PRESS:
1368 case GDK_2BUTTON_PRESS:
1369 case GDK_3BUTTON_PRESS:
1370 case GDK_BUTTON_RELEASE:
1371 rewrite_events_translate (event->any.window,
1373 &event->button.x, &event->button.y);
1375 case GDK_MOTION_NOTIFY:
1376 rewrite_events_translate (event->any.window,
1378 &event->motion.x, &event->motion.y);
1381 case GDK_KEY_RELEASE:
1382 case GDK_PROXIMITY_IN:
1383 case GDK_PROXIMITY_OUT:
1390 g_object_unref (event->any.window);
1391 event->any.window = g_object_ref (new_window);
1396 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1397 * then what X11 does is deliver the event normally if it was going to this
1398 * client, otherwise, delivers it in terms of the grab window. This function
1399 * rewrites events to the effect that events going to the same window group
1400 * are delivered normally, otherwise, the event is delivered in terms of the
1404 rewrite_event_for_grabs (GdkEvent *event)
1406 GdkWindow *grab_window;
1407 GtkWidget *event_widget, *grab_widget;
1408 gpointer grab_widget_ptr;
1409 gboolean owner_events;
1410 GdkDisplay *display;
1412 switch (event->type)
1415 case GDK_BUTTON_PRESS:
1416 case GDK_2BUTTON_PRESS:
1417 case GDK_3BUTTON_PRESS:
1418 case GDK_BUTTON_RELEASE:
1419 case GDK_MOTION_NOTIFY:
1420 case GDK_PROXIMITY_IN:
1421 case GDK_PROXIMITY_OUT:
1422 display = gdk_drawable_get_display (event->proximity.window);
1423 if (!gdk_pointer_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1429 case GDK_KEY_RELEASE:
1430 display = gdk_drawable_get_display (event->key.window);
1431 if (!gdk_keyboard_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1440 event_widget = gtk_get_event_widget (event);
1441 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1442 grab_widget = grab_widget_ptr;
1445 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1446 return rewrite_event_for_window (event, grab_window);
1452 gtk_main_do_event (GdkEvent *event)
1454 GtkWidget *event_widget;
1455 GtkWidget *grab_widget;
1456 GtkWindowGroup *window_group;
1457 GdkEvent *rewritten_event = NULL;
1460 if (event->type == GDK_SETTING)
1462 _gtk_settings_handle_event (&event->setting);
1466 if (event->type == GDK_OWNER_CHANGE)
1468 _gtk_clipboard_handle_event (&event->owner_change);
1472 /* Find the widget which got the event. We store the widget
1473 * in the user_data field of GdkWindow's.
1474 * Ignore the event if we don't have a widget for it, except
1475 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1476 * Though this happens rarely, bogus events can occour
1477 * for e.g. destroyed GdkWindows.
1479 event_widget = gtk_get_event_widget (event);
1482 /* To handle selection INCR transactions, we select
1483 * PropertyNotify events on the requestor window and create
1484 * a corresponding (fake) GdkWindow so that events get
1485 * here. There won't be a widget though, so we have to handle
1488 if (event->type == GDK_PROPERTY_NOTIFY)
1489 _gtk_selection_incr_event (event->any.window,
1495 /* If pointer or keyboard grabs are in effect, munge the events
1496 * so that each window group looks like a separate app.
1498 rewritten_event = rewrite_event_for_grabs (event);
1499 if (rewritten_event)
1501 event = rewritten_event;
1502 event_widget = gtk_get_event_widget (event);
1505 window_group = gtk_main_get_window_group (event_widget);
1507 /* Push the event onto a stack of current events for
1508 * gtk_current_event_get().
1510 current_events = g_list_prepend (current_events, event);
1512 /* If there is a grab in effect...
1514 if (window_group->grabs)
1516 grab_widget = window_group->grabs->data;
1518 /* If the grab widget is an ancestor of the event widget
1519 * then we send the event to the original event widget.
1520 * This is the key to implementing modality.
1522 if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
1523 gtk_widget_is_ancestor (event_widget, grab_widget))
1524 grab_widget = event_widget;
1528 grab_widget = event_widget;
1531 /* Not all events get sent to the grabbing widget.
1532 * The delete, destroy, expose, focus change and resize
1533 * events still get sent to the event widget because
1534 * 1) these events have no meaning for the grabbing widget
1535 * and 2) redirecting these events to the grabbing widget
1536 * could cause the display to be messed up.
1538 * Drag events are also not redirected, since it isn't
1539 * clear what the semantics of that would be.
1541 switch (event->type)
1547 g_object_ref (event_widget);
1548 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1549 !gtk_widget_event (event_widget, event))
1550 gtk_widget_destroy (event_widget);
1551 g_object_unref (event_widget);
1555 /* Unexpected GDK_DESTROY from the outside, ignore for
1556 * child windows, handle like a GDK_DELETE for toplevels
1558 if (!event_widget->parent)
1560 g_object_ref (event_widget);
1561 if (!gtk_widget_event (event_widget, event) &&
1562 GTK_WIDGET_REALIZED (event_widget))
1563 gtk_widget_destroy (event_widget);
1564 g_object_unref (event_widget);
1569 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1571 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1572 gtk_widget_send_expose (event_widget, event);
1573 gdk_window_end_paint (event->any.window);
1577 /* The app may paint with a previously allocated cairo_t,
1578 which will draw directly to the window. We can't catch cairo
1579 drap operatoins to automatically flush the window, thus we
1580 need to explicitly flush any outstanding moves or double
1582 gdk_window_flush (event->any.window);
1583 gtk_widget_send_expose (event_widget, event);
1587 case GDK_PROPERTY_NOTIFY:
1589 case GDK_FOCUS_CHANGE:
1593 case GDK_SELECTION_CLEAR:
1594 case GDK_SELECTION_REQUEST:
1595 case GDK_SELECTION_NOTIFY:
1596 case GDK_CLIENT_EVENT:
1597 case GDK_VISIBILITY_NOTIFY:
1598 case GDK_WINDOW_STATE:
1599 case GDK_GRAB_BROKEN:
1601 gtk_widget_event (event_widget, event);
1605 case GDK_BUTTON_PRESS:
1606 case GDK_2BUTTON_PRESS:
1607 case GDK_3BUTTON_PRESS:
1608 gtk_propagate_event (grab_widget, event);
1612 case GDK_KEY_RELEASE:
1615 if (gtk_invoke_key_snoopers (grab_widget, event))
1618 /* Catch alt press to enable auto-mnemonics;
1619 * menus are handled elsewhere
1621 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1622 !GTK_IS_MENU_SHELL (grab_widget))
1624 gboolean auto_mnemonics;
1626 g_object_get (gtk_widget_get_settings (grab_widget),
1627 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1631 gboolean mnemonics_visible;
1634 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1636 window = gtk_widget_get_toplevel (grab_widget);
1638 if (GTK_IS_WINDOW (window))
1639 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1642 /* else fall through */
1643 case GDK_MOTION_NOTIFY:
1644 case GDK_BUTTON_RELEASE:
1645 case GDK_PROXIMITY_IN:
1646 case GDK_PROXIMITY_OUT:
1647 gtk_propagate_event (grab_widget, event);
1650 case GDK_ENTER_NOTIFY:
1651 GTK_PRIVATE_SET_FLAG (event_widget, GTK_HAS_POINTER);
1652 _gtk_widget_set_pointer_window (event_widget, event->any.window);
1653 if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1654 gtk_widget_event (grab_widget, event);
1657 case GDK_LEAVE_NOTIFY:
1658 GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_HAS_POINTER);
1659 if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1660 gtk_widget_event (grab_widget, event);
1663 case GDK_DRAG_STATUS:
1664 case GDK_DROP_FINISHED:
1665 _gtk_drag_source_handle_event (event_widget, event);
1667 case GDK_DRAG_ENTER:
1668 case GDK_DRAG_LEAVE:
1669 case GDK_DRAG_MOTION:
1670 case GDK_DROP_START:
1671 _gtk_drag_dest_handle_event (event_widget, event);
1674 g_assert_not_reached ();
1678 if (event->type == GDK_ENTER_NOTIFY
1679 || event->type == GDK_LEAVE_NOTIFY
1680 || event->type == GDK_BUTTON_PRESS
1681 || event->type == GDK_2BUTTON_PRESS
1682 || event->type == GDK_3BUTTON_PRESS
1683 || event->type == GDK_KEY_PRESS
1684 || event->type == GDK_DRAG_ENTER
1685 || event->type == GDK_GRAB_BROKEN
1686 || event->type == GDK_MOTION_NOTIFY
1687 || event->type == GDK_SCROLL)
1689 _gtk_tooltip_handle_event (event);
1692 tmp_list = current_events;
1693 current_events = g_list_remove_link (current_events, tmp_list);
1694 g_list_free_1 (tmp_list);
1696 if (rewritten_event)
1697 gdk_event_free (rewritten_event);
1712 static GtkWindowGroup *
1713 gtk_main_get_window_group (GtkWidget *widget)
1715 GtkWidget *toplevel = NULL;
1718 toplevel = gtk_widget_get_toplevel (widget);
1720 if (GTK_IS_WINDOW (toplevel))
1721 return gtk_window_get_group (GTK_WINDOW (toplevel));
1723 return gtk_window_get_group (NULL);
1728 GtkWidget *old_grab_widget;
1729 GtkWidget *new_grab_widget;
1730 gboolean was_grabbed;
1731 gboolean is_grabbed;
1736 gtk_grab_notify_foreach (GtkWidget *child,
1740 GrabNotifyInfo *info = data;
1742 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1744 was_grabbed = info->was_grabbed;
1745 is_grabbed = info->is_grabbed;
1747 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1748 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1750 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1751 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1753 g_object_ref (child);
1755 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1756 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1760 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1761 if (!was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1762 && GTK_WIDGET_IS_SENSITIVE (child))
1763 _gtk_widget_synthesize_crossing (child, info->new_grab_widget,
1764 GDK_CROSSING_GTK_GRAB);
1768 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1769 if (was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1770 && GTK_WIDGET_IS_SENSITIVE (child))
1771 _gtk_widget_synthesize_crossing (info->old_grab_widget, child,
1772 info->from_grab ? GDK_CROSSING_GTK_GRAB
1773 : GDK_CROSSING_GTK_UNGRAB);
1776 if (was_shadowed != is_shadowed)
1777 _gtk_widget_grab_notify (child, was_shadowed);
1779 g_object_unref (child);
1781 info->was_grabbed = was_grabbed;
1782 info->is_grabbed = is_grabbed;
1786 gtk_grab_notify (GtkWindowGroup *group,
1787 GtkWidget *old_grab_widget,
1788 GtkWidget *new_grab_widget,
1792 GrabNotifyInfo info;
1794 if (old_grab_widget == new_grab_widget)
1797 info.old_grab_widget = old_grab_widget;
1798 info.new_grab_widget = new_grab_widget;
1799 info.from_grab = from_grab;
1801 g_object_ref (group);
1803 toplevels = gtk_window_list_toplevels ();
1804 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1808 GtkWindow *toplevel = toplevels->data;
1809 toplevels = g_list_delete_link (toplevels, toplevels);
1811 info.was_grabbed = FALSE;
1812 info.is_grabbed = FALSE;
1814 if (group == gtk_window_get_group (toplevel))
1815 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1816 g_object_unref (toplevel);
1819 g_object_unref (group);
1823 gtk_grab_add (GtkWidget *widget)
1825 GtkWindowGroup *group;
1826 GtkWidget *old_grab_widget;
1828 g_return_if_fail (widget != NULL);
1830 if (!gtk_widget_has_grab (widget) && GTK_WIDGET_IS_SENSITIVE (widget))
1832 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
1834 group = gtk_main_get_window_group (widget);
1837 old_grab_widget = (GtkWidget *)group->grabs->data;
1839 old_grab_widget = NULL;
1841 g_object_ref (widget);
1842 group->grabs = g_slist_prepend (group->grabs, widget);
1844 gtk_grab_notify (group, old_grab_widget, widget, TRUE);
1849 gtk_grab_get_current (void)
1851 GtkWindowGroup *group;
1853 group = gtk_main_get_window_group (NULL);
1856 return GTK_WIDGET (group->grabs->data);
1861 gtk_grab_remove (GtkWidget *widget)
1863 GtkWindowGroup *group;
1864 GtkWidget *new_grab_widget;
1866 g_return_if_fail (widget != NULL);
1868 if (gtk_widget_has_grab (widget))
1870 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
1872 group = gtk_main_get_window_group (widget);
1873 group->grabs = g_slist_remove (group->grabs, widget);
1876 new_grab_widget = (GtkWidget *)group->grabs->data;
1878 new_grab_widget = NULL;
1880 gtk_grab_notify (group, widget, new_grab_widget, FALSE);
1882 g_object_unref (widget);
1887 gtk_init_add (GtkFunction function,
1890 GtkInitFunction *init;
1892 init = g_new (GtkInitFunction, 1);
1893 init->function = function;
1896 init_functions = g_list_prepend (init_functions, init);
1900 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
1903 GtkKeySnooperData *data;
1904 static guint snooper_id = 1;
1906 g_return_val_if_fail (snooper != NULL, 0);
1908 data = g_new (GtkKeySnooperData, 1);
1909 data->func = snooper;
1910 data->func_data = func_data;
1911 data->id = snooper_id++;
1912 key_snoopers = g_slist_prepend (key_snoopers, data);
1918 gtk_key_snooper_remove (guint snooper_id)
1920 GtkKeySnooperData *data = NULL;
1923 slist = key_snoopers;
1927 if (data->id == snooper_id)
1930 slist = slist->next;
1935 key_snoopers = g_slist_remove (key_snoopers, data);
1941 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
1945 gint return_val = FALSE;
1947 slist = key_snoopers;
1948 while (slist && !return_val)
1950 GtkKeySnooperData *data;
1953 slist = slist->next;
1954 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
1961 gtk_quit_add_full (guint main_level,
1962 GtkFunction function,
1963 GtkCallbackMarshal marshal,
1965 GDestroyNotify destroy)
1967 static guint quit_id = 1;
1968 GtkQuitFunction *quitf;
1970 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
1972 quitf = g_slice_new (GtkQuitFunction);
1974 quitf->id = quit_id++;
1975 quitf->main_level = main_level;
1976 quitf->function = function;
1977 quitf->marshal = marshal;
1979 quitf->destroy = destroy;
1981 quit_functions = g_list_prepend (quit_functions, quitf);
1987 gtk_quit_destroy (GtkQuitFunction *quitf)
1990 quitf->destroy (quitf->data);
1991 g_slice_free (GtkQuitFunction, quitf);
1995 gtk_quit_destructor (GtkObject **object_p)
1998 gtk_object_destroy (*object_p);
2005 gtk_quit_add_destroy (guint main_level,
2008 GtkObject **object_p;
2010 g_return_if_fail (main_level > 0);
2011 g_return_if_fail (GTK_IS_OBJECT (object));
2013 object_p = g_new (GtkObject*, 1);
2015 g_signal_connect (object,
2017 G_CALLBACK (gtk_widget_destroyed),
2019 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2023 gtk_quit_add (guint main_level,
2024 GtkFunction function,
2027 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2031 gtk_quit_remove (guint id)
2033 GtkQuitFunction *quitf;
2036 tmp_list = quit_functions;
2039 quitf = tmp_list->data;
2041 if (quitf->id == id)
2043 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2044 g_list_free (tmp_list);
2045 gtk_quit_destroy (quitf);
2050 tmp_list = tmp_list->next;
2055 gtk_quit_remove_by_data (gpointer data)
2057 GtkQuitFunction *quitf;
2060 tmp_list = quit_functions;
2063 quitf = tmp_list->data;
2065 if (quitf->data == data)
2067 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2068 g_list_free (tmp_list);
2069 gtk_quit_destroy (quitf);
2074 tmp_list = tmp_list->next;
2079 gtk_timeout_add_full (guint32 interval,
2080 GtkFunction function,
2081 GtkCallbackMarshal marshal,
2083 GDestroyNotify destroy)
2087 GtkClosure *closure;
2089 closure = g_new (GtkClosure, 1);
2090 closure->marshal = marshal;
2091 closure->data = data;
2092 closure->destroy = destroy;
2094 return g_timeout_add_full (0, interval,
2095 gtk_invoke_idle_timeout,
2097 gtk_destroy_closure);
2100 return g_timeout_add_full (0, interval, function, data, destroy);
2104 gtk_timeout_add (guint32 interval,
2105 GtkFunction function,
2108 return g_timeout_add_full (0, interval, function, data, NULL);
2112 gtk_timeout_remove (guint tag)
2114 g_source_remove (tag);
2118 gtk_idle_add_full (gint priority,
2119 GtkFunction function,
2120 GtkCallbackMarshal marshal,
2122 GDestroyNotify destroy)
2126 GtkClosure *closure;
2128 closure = g_new (GtkClosure, 1);
2129 closure->marshal = marshal;
2130 closure->data = data;
2131 closure->destroy = destroy;
2133 return g_idle_add_full (priority,
2134 gtk_invoke_idle_timeout,
2136 gtk_destroy_closure);
2139 return g_idle_add_full (priority, function, data, destroy);
2143 gtk_idle_add (GtkFunction function,
2146 return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
2150 gtk_idle_add_priority (gint priority,
2151 GtkFunction function,
2154 return g_idle_add_full (priority, function, data, NULL);
2158 gtk_idle_remove (guint tag)
2160 g_source_remove (tag);
2164 gtk_idle_remove_by_data (gpointer data)
2166 if (!g_idle_remove_by_data (data))
2167 g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
2171 gtk_input_add_full (gint source,
2172 GdkInputCondition condition,
2173 GdkInputFunction function,
2174 GtkCallbackMarshal marshal,
2176 GDestroyNotify destroy)
2180 GtkClosure *closure;
2182 closure = g_new (GtkClosure, 1);
2183 closure->marshal = marshal;
2184 closure->data = data;
2185 closure->destroy = destroy;
2187 return gdk_input_add_full (source,
2189 (GdkInputFunction) gtk_invoke_input,
2191 (GDestroyNotify) gtk_destroy_closure);
2194 return gdk_input_add_full (source, condition, function, data, destroy);
2198 gtk_input_remove (guint tag)
2200 g_source_remove (tag);
2204 gtk_destroy_closure (gpointer data)
2206 GtkClosure *closure = data;
2208 if (closure->destroy)
2209 (closure->destroy) (closure->data);
2214 gtk_invoke_idle_timeout (gpointer data)
2216 GtkClosure *closure = data;
2219 gint ret_val = FALSE;
2220 args[0].name = NULL;
2221 args[0].type = G_TYPE_BOOLEAN;
2222 args[0].d.pointer_data = &ret_val;
2223 closure->marshal (NULL, closure->data, 0, args);
2228 gtk_invoke_input (gpointer data,
2230 GdkInputCondition condition)
2232 GtkClosure *closure = data;
2235 args[0].type = G_TYPE_INT;
2236 args[0].name = NULL;
2237 GTK_VALUE_INT (args[0]) = source;
2238 args[1].type = GDK_TYPE_INPUT_CONDITION;
2239 args[1].name = NULL;
2240 GTK_VALUE_FLAGS (args[1]) = condition;
2241 args[2].type = G_TYPE_NONE;
2242 args[2].name = NULL;
2244 closure->marshal (NULL, closure->data, 2, args);
2248 * gtk_get_current_event:
2250 * Obtains a copy of the event currently being processed by GTK+. For
2251 * example, if you get a "clicked" signal from #GtkButton, the current
2252 * event will be the #GdkEventButton that triggered the "clicked"
2253 * signal. The returned event must be freed with gdk_event_free().
2254 * If there is no current event, the function returns %NULL.
2256 * Return value: a copy of the current event, or %NULL if no current event.
2259 gtk_get_current_event (void)
2262 return gdk_event_copy (current_events->data);
2268 * gtk_get_current_event_time:
2270 * If there is a current event and it has a timestamp, return that
2271 * timestamp, otherwise return %GDK_CURRENT_TIME.
2273 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2276 gtk_get_current_event_time (void)
2279 return gdk_event_get_time (current_events->data);
2281 return GDK_CURRENT_TIME;
2285 * gtk_get_current_event_state:
2286 * @state: a location to store the state of the current event
2288 * If there is a current event and it has a state field, place
2289 * that state field in @state and return %TRUE, otherwise return
2292 * Return value: %TRUE if there was a current event and it had a state field
2295 gtk_get_current_event_state (GdkModifierType *state)
2297 g_return_val_if_fail (state != NULL, FALSE);
2300 return gdk_event_get_state (current_events->data, state);
2309 * gtk_get_event_widget:
2310 * @event: a #GdkEvent
2312 * If @event is %NULL or the event was not associated with any widget,
2313 * returns %NULL, otherwise returns the widget that received the event
2316 * Return value: the widget that originally received @event, or %NULL
2319 gtk_get_event_widget (GdkEvent *event)
2322 gpointer widget_ptr;
2325 if (event && event->any.window &&
2326 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2328 gdk_window_get_user_data (event->any.window, &widget_ptr);
2329 widget = widget_ptr;
2336 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2338 if (!quitf->marshal)
2339 return quitf->function (quitf->data);
2343 gint ret_val = FALSE;
2345 args[0].name = NULL;
2346 args[0].type = G_TYPE_BOOLEAN;
2347 args[0].d.pointer_data = &ret_val;
2348 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2356 * gtk_propagate_event:
2357 * @widget: a #GtkWidget
2360 * Sends an event to a widget, propagating the event to parent widgets
2361 * if the event remains unhandled. Events received by GTK+ from GDK
2362 * normally begin in gtk_main_do_event(). Depending on the type of
2363 * event, existence of modal dialogs, grabs, etc., the event may be
2364 * propagated; if so, this function is used. gtk_propagate_event()
2365 * calls gtk_widget_event() on each widget it decides to send the
2366 * event to. So gtk_widget_event() is the lowest-level function; it
2367 * simply emits the "event" and possibly an event-specific signal on a
2368 * widget. gtk_propagate_event() is a bit higher-level, and
2369 * gtk_main_do_event() is the highest level.
2371 * All that said, you most likely don't want to use any of these
2372 * functions; synthesizing events is rarely needed. Consider asking on
2373 * the mailing list for better ways to achieve your goals. For
2374 * example, use gdk_window_invalidate_rect() or
2375 * gtk_widget_queue_draw() instead of making up expose events.
2379 gtk_propagate_event (GtkWidget *widget,
2384 g_return_if_fail (GTK_IS_WIDGET (widget));
2385 g_return_if_fail (event != NULL);
2387 handled_event = FALSE;
2389 g_object_ref (widget);
2391 if ((event->type == GDK_KEY_PRESS) ||
2392 (event->type == GDK_KEY_RELEASE))
2394 /* Only send key events within Window widgets to the Window
2395 * The Window widget will in turn pass the
2396 * key event on to the currently focused widget
2401 window = gtk_widget_get_toplevel (widget);
2402 if (GTK_IS_WINDOW (window))
2404 /* If there is a grab within the window, give the grab widget
2405 * a first crack at the key event
2407 if (widget != window && gtk_widget_has_grab (widget))
2408 handled_event = gtk_widget_event (widget, event);
2412 window = gtk_widget_get_toplevel (widget);
2413 if (GTK_IS_WINDOW (window))
2415 if (GTK_WIDGET_IS_SENSITIVE (window))
2416 gtk_widget_event (window, event);
2420 handled_event = TRUE; /* don't send to widget */
2424 /* Other events get propagated up the widget tree
2425 * so that parents can see the button and motion
2426 * events of the children.
2434 /* Scroll events are special cased here because it
2435 * feels wrong when scrolling a GtkViewport, say,
2436 * to have children of the viewport eat the scroll
2439 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2440 handled_event = event->type != GDK_SCROLL;
2442 handled_event = gtk_widget_event (widget, event);
2444 tmp = widget->parent;
2445 g_object_unref (widget);
2449 if (!handled_event && widget)
2450 g_object_ref (widget);
2456 g_object_unref (widget);
2461 gtk_error (gchar *str)
2467 gtk_warning (gchar *str)
2473 gtk_message (gchar *str)
2479 gtk_print (gchar *str)
2481 static GtkWidget *window = NULL;
2482 static GtkWidget *text;
2483 static int level = 0;
2487 GtkWidget *hscrollbar;
2488 GtkWidget *vscrollbar;
2489 GtkWidget *separator;
2494 fputs (str, stdout);
2501 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2503 gtk_signal_connect (GTK_OBJECT (window), "destroy",
2504 G_CALLBACK (gtk_widget_destroyed),
2507 gtk_window_set_title (GTK_WINDOW (window), "Messages");
2509 box1 = gtk_vbox_new (FALSE, 0);
2510 gtk_container_add (GTK_CONTAINER (window), box1);
2511 gtk_widget_show (box1);
2514 box2 = gtk_vbox_new (FALSE, 10);
2515 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2516 gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2517 gtk_widget_show (box2);
2520 table = gtk_table_new (2, 2, FALSE);
2521 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2522 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2523 gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2524 gtk_widget_show (table);
2526 text = gtk_text_new (NULL, NULL);
2527 gtk_text_set_editable (GTK_TEXT (text), FALSE);
2528 gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2529 gtk_widget_show (text);
2530 gtk_widget_realize (text);
2532 hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2533 gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2534 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2535 gtk_widget_show (hscrollbar);
2537 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2538 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2539 GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2540 gtk_widget_show (vscrollbar);
2542 separator = gtk_hseparator_new ();
2543 gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2544 gtk_widget_show (separator);
2547 box2 = gtk_vbox_new (FALSE, 10);
2548 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2549 gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2550 gtk_widget_show (box2);
2553 button = gtk_button_new_with_label ("close");
2554 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2555 G_CALLBACK (gtk_widget_hide),
2556 GTK_OBJECT (window));
2557 gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2558 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2559 gtk_widget_grab_default (button);
2560 gtk_widget_show (button);
2564 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2567 if (!GTK_WIDGET_VISIBLE (window))
2568 gtk_widget_show (window);
2573 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2574 GValue *return_accu,
2575 const GValue *handler_return,
2578 gboolean continue_emission;
2579 gboolean signal_handled;
2581 signal_handled = g_value_get_boolean (handler_return);
2582 g_value_set_boolean (return_accu, signal_handled);
2583 continue_emission = !signal_handled;
2585 return continue_emission;
2588 #define __GTK_MAIN_C__
2589 #include "gtkaliasdef.c"