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},
239 {"extended-layout", GTK_DEBUG_EXTENDED_LAYOUT},
241 #endif /* G_ENABLE_DEBUG */
245 * @required_major: the required major version.
246 * @required_minor: the required minor version.
247 * @required_micro: the required micro version.
249 * Checks that the GTK+ library in use is compatible with the
250 * given version. Generally you would pass in the constants
251 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
252 * as the three arguments to this function; that produces
253 * a check that the library in use is compatible with
254 * the version of GTK+ the application or module was compiled
257 * Compatibility is defined by two things: first the version
258 * of the running library is newer than the version
259 * @required_major.required_minor.@required_micro. Second
260 * the running library must be binary compatible with the
261 * version @required_major.required_minor.@required_micro
262 * (same major version.)
264 * This function is primarily for GTK+ modules; the module
265 * can call this function to check that it wasn't loaded
266 * into an incompatible version of GTK+. However, such a
267 * a check isn't completely reliable, since the module may be
268 * linked against an old version of GTK+ and calling the
269 * old version of gtk_check_version(), but still get loaded
270 * into an application using a newer version of GTK+.
272 * Return value: %NULL if the GTK+ library is compatible with the
273 * given version, or a string describing the version mismatch.
274 * The returned string is owned by GTK+ and should not be modified
278 gtk_check_version (guint required_major,
279 guint required_minor,
280 guint required_micro)
282 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
283 gint required_effective_micro = 100 * required_minor + required_micro;
285 if (required_major > GTK_MAJOR_VERSION)
286 return "Gtk+ version too old (major mismatch)";
287 if (required_major < GTK_MAJOR_VERSION)
288 return "Gtk+ version too new (major mismatch)";
289 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
290 return "Gtk+ version too new (micro mismatch)";
291 if (required_effective_micro > gtk_effective_micro)
292 return "Gtk+ version too old (micro mismatch)";
296 /* This checks to see if the process is running suid or sgid
297 * at the current time. If so, we don't allow GTK+ to be initialized.
298 * This is meant to be a mild check - we only error out if we
299 * can prove the programmer is doing something wrong, not if
300 * they could be doing something wrong. For this reason, we
301 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
306 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
308 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
309 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
311 #ifdef HAVE_GETRESUID
312 /* These aren't in the header files, so we prototype them here.
314 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
315 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
317 if (getresuid (&ruid, &euid, &suid) != 0 ||
318 getresgid (&rgid, &egid, &sgid) != 0)
319 #endif /* HAVE_GETRESUID */
321 suid = ruid = getuid ();
322 sgid = rgid = getgid ();
327 if (ruid != euid || ruid != suid ||
328 rgid != egid || rgid != sgid)
330 g_warning ("This process is currently running setuid or setgid.\n"
331 "This is not a supported use of GTK+. You must create a helper\n"
332 "program instead. For further details, see:\n\n"
333 " http://www.gtk.org/setuid.html\n\n"
334 "Refusing to initialize GTK+.");
344 _gtk_get_datadir (void)
346 static char *gtk_datadir = NULL;
347 if (gtk_datadir == NULL)
349 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
350 gtk_datadir = g_build_filename (root, "share", NULL);
358 _gtk_get_sysconfdir (void)
360 static char *gtk_sysconfdir = NULL;
361 if (gtk_sysconfdir == NULL)
363 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
364 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
368 return gtk_sysconfdir;
372 _gtk_get_data_prefix (void)
374 static char *gtk_data_prefix = NULL;
375 if (gtk_data_prefix == NULL)
376 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
378 return gtk_data_prefix;
381 #endif /* G_OS_WIN32 */
383 static gboolean do_setlocale = TRUE;
386 * gtk_disable_setlocale:
388 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
389 * gtk_parse_args() from automatically
390 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
391 * want to use this function if you wanted to set the locale for
392 * your program to something other than the user's locale, or if
393 * you wanted to set different values for different locale categories.
395 * Most programs should not need to call this function.
398 gtk_disable_setlocale (void)
401 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
403 do_setlocale = FALSE;
406 #ifdef G_PLATFORM_WIN32
407 #undef gtk_init_check
410 static GString *gtk_modules_string = NULL;
411 static gboolean g_fatal_warnings = FALSE;
413 #ifdef G_ENABLE_DEBUG
415 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
417 gtk_debug_flags |= g_parse_debug_string (value,
419 G_N_ELEMENTS (gtk_debug_keys));
425 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
427 gtk_debug_flags &= ~g_parse_debug_string (value,
429 G_N_ELEMENTS (gtk_debug_keys));
433 #endif /* G_ENABLE_DEBUG */
436 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
440 if (gtk_modules_string)
441 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
443 gtk_modules_string = g_string_new (NULL);
445 g_string_append (gtk_modules_string, value);
451 static const GOptionEntry gtk_args[] = {
452 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
453 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
454 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
455 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
456 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
457 #ifdef G_ENABLE_DEBUG
458 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
459 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
460 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
461 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
462 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
463 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
470 static char *iso639_to_check = NULL;
471 static char *iso3166_to_check = NULL;
472 static char *script_to_check = NULL;
473 static gboolean setlocale_called = FALSE;
476 enum_locale_proc (LPTSTR locale)
484 lcid = strtoul (locale, &endptr, 16);
485 if (*endptr == '\0' &&
486 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
487 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
489 if (strcmp (iso639, iso639_to_check) == 0 &&
490 ((iso3166_to_check != NULL &&
491 strcmp (iso3166, iso3166_to_check) == 0) ||
492 (iso3166_to_check == NULL &&
493 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
495 char language[100], country[100];
498 if (script_to_check != NULL)
500 /* If lcid is the "other" script for this language,
501 * return TRUE, i.e. continue looking.
503 if (strcmp (script_to_check, "Latn") == 0)
505 switch (LANGIDFROMLCID (lcid))
507 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
509 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
511 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
513 case MAKELANGID (LANG_SERBIAN, 0x07):
514 /* Serbian in Bosnia and Herzegovina, Cyrillic */
518 else if (strcmp (script_to_check, "Cyrl") == 0)
520 switch (LANGIDFROMLCID (lcid))
522 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
524 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
526 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
528 case MAKELANGID (LANG_SERBIAN, 0x06):
529 /* Serbian in Bosnia and Herzegovina, Latin */
535 SetThreadLocale (lcid);
537 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
538 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
540 strcpy (locale, language);
541 strcat (locale, "_");
542 strcat (locale, country);
544 if (setlocale (LC_ALL, locale) != NULL)
545 setlocale_called = TRUE;
558 setlocale_initialization (void)
560 static gboolean initialized = FALSE;
569 /* If some of the POSIXish environment variables are set, set
570 * the Win32 thread locale correspondingly.
572 char *p = getenv ("LC_ALL");
579 if (strcmp (p, "C") == 0)
580 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
583 /* Check if one of the supported locales match the
584 * environment variable. If so, use that locale.
587 iso3166_to_check = strchr (iso639_to_check, '_');
588 if (iso3166_to_check != NULL)
590 *iso3166_to_check++ = '\0';
592 script_to_check = strchr (iso3166_to_check, '@');
593 if (script_to_check != NULL)
594 *script_to_check++ = '\0';
596 /* Handle special cases. */
598 /* The standard code for Serbia and Montenegro was
599 * "CS", but MSFT uses for some reason "SP". By now
600 * (October 2006), SP has split into two, "RS" and
601 * "ME", but don't bother trying to handle those
602 * yet. Do handle the even older "YU", though.
604 if (strcmp (iso3166_to_check, "CS") == 0 ||
605 strcmp (iso3166_to_check, "YU") == 0)
606 iso3166_to_check = "SP";
610 script_to_check = strchr (iso639_to_check, '@');
611 if (script_to_check != NULL)
612 *script_to_check++ = '\0';
613 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
614 if (strcmp (iso639_to_check, "sr") == 0)
615 iso3166_to_check = "SP";
618 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
622 if (!setlocale_called)
623 setlocale (LC_ALL, "");
625 if (!setlocale (LC_ALL, ""))
626 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
632 do_pre_parse_initialization (int *argc,
635 const gchar *env_string;
638 g_set_error_handler (gtk_error);
639 g_set_warning_handler (gtk_warning);
640 g_set_message_handler (gtk_message);
641 g_set_print_handler (gtk_print);
647 pre_initialized = TRUE;
649 gdk_pre_parse_libgtk_only ();
650 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
652 #ifdef G_ENABLE_DEBUG
653 env_string = g_getenv ("GTK_DEBUG");
654 if (env_string != NULL)
656 gtk_debug_flags = g_parse_debug_string (env_string,
658 G_N_ELEMENTS (gtk_debug_keys));
661 #endif /* G_ENABLE_DEBUG */
663 env_string = g_getenv ("GTK_MODULES");
665 gtk_modules_string = g_string_new (env_string);
669 gettext_initialization (void)
671 setlocale_initialization ();
674 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
675 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
676 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
677 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
678 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
684 do_post_parse_initialization (int *argc,
690 gettext_initialization ();
693 signal (SIGPIPE, SIG_IGN);
696 if (g_fatal_warnings)
698 GLogLevelFlags fatal_mask;
700 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
701 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
702 g_log_set_always_fatal (fatal_mask);
705 if (gtk_debug_flags & GTK_DEBUG_UPDATES)
706 gdk_window_set_debug_updates (TRUE);
709 /* Translate to default:RTL if you want your widgets
710 * to be RTL, otherwise translate to default:LTR.
711 * Do *not* translate it to "predefinito:LTR", if it
712 * it isn't default:LTR or default:RTL it will not work
714 char *e = _("default:LTR");
715 if (strcmp (e, "default:RTL")==0)
716 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
717 else if (strcmp (e, "default:LTR"))
718 g_warning ("Whoever translated default:LTR did so wrongly.\n");
721 /* do what the call to gtk_type_init() used to do */
724 _gtk_accel_map_init ();
727 /* Set the 'initialized' flag.
729 gtk_initialized = TRUE;
731 /* load gtk modules */
732 if (gtk_modules_string)
734 _gtk_modules_init (argc, argv, gtk_modules_string->str);
735 g_string_free (gtk_modules_string, TRUE);
739 _gtk_modules_init (argc, argv, NULL);
746 gboolean open_default_display;
750 pre_parse_hook (GOptionContext *context,
755 do_pre_parse_initialization (NULL, NULL);
761 post_parse_hook (GOptionContext *context,
766 OptionGroupInfo *info = data;
769 do_post_parse_initialization (NULL, NULL);
771 if (info->open_default_display)
773 if (gdk_display_open_default_libgtk_only () == NULL)
775 const char *display_name = gdk_get_display_arg_name ();
778 G_OPTION_ERROR_FAILED,
779 _("Cannot open display: %s"),
780 display_name ? display_name : "" );
791 * gtk_get_option_group:
792 * @open_default_display: whether to open the default display
793 * when parsing the commandline arguments
795 * Returns a #GOptionGroup for the commandline arguments recognized
796 * by GTK+ and GDK. You should add this group to your #GOptionContext
797 * with g_option_context_add_group(), if you are using
798 * g_option_context_parse() to parse your commandline arguments.
800 * Returns: a #GOptionGroup for the commandline arguments recognized
806 gtk_get_option_group (gboolean open_default_display)
809 OptionGroupInfo *info;
811 gettext_initialization ();
813 info = g_new0 (OptionGroupInfo, 1);
814 info->open_default_display = open_default_display;
816 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
817 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
819 gdk_add_option_entries_libgtk_only (group);
820 g_option_group_add_entries (group, gtk_args);
821 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
827 * gtk_init_with_args:
828 * @argc: a pointer to the number of command line arguments.
829 * @argv: a pointer to the array of command line arguments.
830 * @parameter_string: a string which is displayed in
831 * the first line of <option>--help</option> output, after
832 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
833 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
834 * describing the options of your program
835 * @translation_domain: a translation domain to use for translating
836 * the <option>--help</option> output for the options in @entries
837 * with gettext(), or %NULL
838 * @error: a return location for errors
840 * This function does the same work as gtk_init_check().
841 * Additionally, it allows you to add your own commandline options,
842 * and it automatically generates nicely formatted
843 * <option>--help</option> output. Note that your program will
844 * be terminated after writing out the help output.
846 * Returns: %TRUE if the GUI has been successfully initialized,
852 gtk_init_with_args (int *argc,
854 const char *parameter_string,
855 GOptionEntry *entries,
856 const char *translation_domain,
859 GOptionContext *context;
860 GOptionGroup *gtk_group;
864 return gdk_display_open_default_libgtk_only () != NULL;
866 gettext_initialization ();
868 if (!check_setugid ())
871 gtk_group = gtk_get_option_group (TRUE);
873 context = g_option_context_new (parameter_string);
874 g_option_context_add_group (context, gtk_group);
877 g_option_context_add_main_entries (context, entries, translation_domain);
878 retval = g_option_context_parse (context, argc, argv, error);
880 g_option_context_free (context);
888 * @argc: (inout): a pointer to the number of command line arguments.
889 * @argv: (array) (inout): a pointer to the array of command line arguments.
891 * Parses command line arguments, and initializes global
892 * attributes of GTK+, but does not actually open a connection
893 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
895 * Any arguments used by GTK+ or GDK are removed from the array and
896 * @argc and @argv are updated accordingly.
898 * You shouldn't call this function explicitely if you are using
899 * gtk_init(), or gtk_init_check().
901 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
904 gtk_parse_args (int *argc,
907 GOptionContext *option_context;
908 GOptionGroup *gtk_group;
909 GError *error = NULL;
914 gettext_initialization ();
916 if (!check_setugid ())
919 option_context = g_option_context_new (NULL);
920 g_option_context_set_ignore_unknown_options (option_context, TRUE);
921 g_option_context_set_help_enabled (option_context, FALSE);
922 gtk_group = gtk_get_option_group (FALSE);
923 g_option_context_set_main_group (option_context, gtk_group);
924 if (!g_option_context_parse (option_context, argc, argv, &error))
926 g_warning ("%s", error->message);
927 g_error_free (error);
930 g_option_context_free (option_context);
935 #ifdef G_PLATFORM_WIN32
936 #undef gtk_init_check
941 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
942 * main() function. Changed if any arguments were handled.
943 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
944 * Any parameters understood by gtk_init() are stripped before return.
946 * This function does the same work as gtk_init() with only
947 * a single change: It does not terminate the program if the GUI can't be
948 * initialized. Instead it returns %FALSE on failure.
950 * This way the application can fall back to some other means of communication
951 * with the user - for example a curses or command line interface.
953 * Return value: %TRUE if the GUI has been successfully initialized,
957 gtk_init_check (int *argc,
960 if (!gtk_parse_args (argc, argv))
963 return gdk_display_open_default_libgtk_only () != NULL;
966 #ifdef G_PLATFORM_WIN32
972 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
973 * main() function. Changed if any arguments were handled.
974 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
975 * Any parameters understood by gtk_init() are stripped before return.
977 * Call this function before using any other GTK+ functions in your GUI
978 * applications. It will initialize everything needed to operate the
979 * toolkit and parses some standard command line options. @argc and
980 * @argv are adjusted accordingly so your own code will
981 * never see those standard arguments.
983 * Note that there are some alternative ways to initialize GTK+:
984 * if you are calling gtk_parse_args(), gtk_init_check(),
985 * gtk_init_with_args() or g_option_context_parse() with
986 * the option group returned by gtk_get_option_group(), you
987 * <emphasis>don't</emphasis> have to call gtk_init().
990 * This function will terminate your program if it was unable to initialize
991 * the GUI for some reason. If you want your program to fall back to a
992 * textual interface you want to call gtk_init_check() instead.
996 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
997 * during initialization, to ignore SIGPIPE signals, since these are
998 * almost never wanted in graphical applications. If you do need to
999 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1000 * but notice that other libraries (e.g. libdbus or gvfs) might do
1005 gtk_init (int *argc, char ***argv)
1007 if (!gtk_init_check (argc, argv))
1009 const char *display_name_arg = gdk_get_display_arg_name ();
1010 if (display_name_arg == NULL)
1011 display_name_arg = getenv("DISPLAY");
1012 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1017 #ifdef G_PLATFORM_WIN32
1020 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1022 if (sizeof_GtkWindow != sizeof (GtkWindow))
1023 g_error ("Incompatible build!\n"
1024 "The code using GTK+ thinks GtkWindow is of different\n"
1025 "size than it actually is in this build of GTK+.\n"
1026 "On Windows, this probably means that you have compiled\n"
1027 "your code with gcc without the -mms-bitfields switch,\n"
1028 "or that you are using an unsupported compiler.");
1031 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1032 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1033 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1034 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1035 * -fnative-struct still matters. GtkBox is one such.
1038 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1040 if (sizeof_GtkBox != sizeof (GtkBox))
1041 g_error ("Incompatible build!\n"
1042 "The code using GTK+ thinks GtkBox is of different\n"
1043 "size than it actually is in this build of GTK+.\n"
1044 "On Windows, this probably means that you have compiled\n"
1045 "your code with gcc without the -mms-bitfields switch,\n"
1046 "or that you are using an unsupported compiler.");
1049 /* These two functions might get more checks added later, thus pass
1050 * in the number of extra args.
1053 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1055 check_sizeof_GtkWindow (sizeof_GtkWindow);
1056 if (num_checks >= 2)
1057 check_sizeof_GtkBox (sizeof_GtkBox);
1058 gtk_init (argc, argv);
1062 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1064 check_sizeof_GtkWindow (sizeof_GtkWindow);
1065 if (num_checks >= 2)
1066 check_sizeof_GtkBox (sizeof_GtkBox);
1067 return gtk_init_check (argc, argv);
1073 gtk_exit (gint errorcode)
1082 * Initializes internationalization support for GTK+. gtk_init()
1083 * automatically does this, so there is typically no point
1084 * in calling this function.
1086 * If you are calling this function because you changed the locale
1087 * after GTK+ is was initialized, then calling this function
1088 * may help a bit. (Note, however, that changing the locale
1089 * after GTK+ is initialized may produce inconsistent results and
1090 * is not really supported.)
1092 * In detail - sets the current locale according to the
1093 * program environment. This is the same as calling the C library function
1094 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1095 * locale specific setup of the windowing system used by GDK.
1097 * Returns: a string corresponding to the locale set, typically in the
1098 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1099 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1100 * result of the setlocale(); it is also used on other machines, such as
1101 * Windows, where the C library returns a different result. The string is
1102 * owned by GTK+ and should not be modified or freed.
1105 gtk_set_locale (void)
1107 return gdk_set_locale ();
1111 * _gtk_get_lc_ctype:
1113 * Return the Unix-style locale string for the language currently in
1114 * effect. On Unix systems, this is the return value from
1115 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1116 * affect this through the environment variables LC_ALL, LC_CTYPE or
1117 * LANG (checked in that order). The locale strings typically is in
1118 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1119 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1120 * Swedish as written in Finland or pt_BR for Portuguese as written in
1123 * On Windows, the C library doesn't use any such environment
1124 * variables, and setting them won't affect the behaviour of functions
1125 * like ctime(). The user sets the locale through the Regional Options
1126 * in the Control Panel. The C library (in the setlocale() function)
1127 * does not use country and language codes, but country and language
1128 * names spelled out in English.
1129 * However, this function does check the above environment
1130 * variables, and does return a Unix-style locale string based on
1131 * either said environment variables or the thread's current locale.
1133 * Return value: a dynamically allocated string, free with g_free().
1137 _gtk_get_lc_ctype (void)
1140 /* Somebody might try to set the locale for this process using the
1141 * LANG or LC_ environment variables. The Microsoft C library
1142 * doesn't know anything about them. You set the locale in the
1143 * Control Panel. Setting these env vars won't have any affect on
1144 * locale-dependent C library functions like ctime(). But just for
1145 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1146 * it easier to test GTK and Pango in various default languages, you
1147 * don't have to clickety-click in the Control Panel, you can simply
1148 * start the program with LC_ALL=something on the command line.)
1152 p = getenv ("LC_ALL");
1154 return g_strdup (p);
1156 p = getenv ("LC_CTYPE");
1158 return g_strdup (p);
1160 p = getenv ("LANG");
1162 return g_strdup (p);
1164 return g_win32_getlocale ();
1166 return g_strdup (setlocale (LC_CTYPE, NULL));
1171 * gtk_get_default_language:
1173 * Returns the #PangoLanguage for the default language currently in
1174 * effect. (Note that this can change over the life of an
1175 * application.) The default language is derived from the current
1176 * locale. It determines, for example, whether GTK+ uses the
1177 * right-to-left or left-to-right text direction.
1179 * This function is equivalent to pango_language_get_default(). See
1180 * that function for details.
1182 * Return value: the default language as a #PangoLanguage, must not be
1186 gtk_get_default_language (void)
1188 return pango_language_get_default ();
1196 GtkInitFunction *init;
1199 gtk_main_loop_level++;
1201 loop = g_main_loop_new (NULL, TRUE);
1202 main_loops = g_slist_prepend (main_loops, loop);
1204 tmp_list = functions = init_functions;
1205 init_functions = NULL;
1209 init = tmp_list->data;
1210 tmp_list = tmp_list->next;
1212 (* init->function) (init->data);
1215 g_list_free (functions);
1217 if (g_main_loop_is_running (main_loops->data))
1219 GDK_THREADS_LEAVE ();
1220 g_main_loop_run (loop);
1221 GDK_THREADS_ENTER ();
1227 GList *reinvoke_list = NULL;
1228 GtkQuitFunction *quitf;
1230 while (quit_functions)
1232 quitf = quit_functions->data;
1234 tmp_list = quit_functions;
1235 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1236 g_list_free_1 (tmp_list);
1238 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1239 gtk_quit_invoke_function (quitf))
1241 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1245 gtk_quit_destroy (quitf);
1252 work = g_list_last (reinvoke_list);
1254 quit_functions->prev = work;
1255 work->next = quit_functions;
1256 quit_functions = work;
1262 main_loops = g_slist_remove (main_loops, loop);
1264 g_main_loop_unref (loop);
1266 gtk_main_loop_level--;
1268 if (gtk_main_loop_level == 0)
1270 /* Try storing all clipboard data we have */
1271 _gtk_clipboard_store_all ();
1273 /* Synchronize the recent manager singleton */
1274 _gtk_recent_manager_sync ();
1279 gtk_main_level (void)
1281 return gtk_main_loop_level;
1285 gtk_main_quit (void)
1287 g_return_if_fail (main_loops != NULL);
1289 g_main_loop_quit (main_loops->data);
1293 gtk_events_pending (void)
1297 GDK_THREADS_LEAVE ();
1298 result = g_main_context_pending (NULL);
1299 GDK_THREADS_ENTER ();
1305 gtk_main_iteration (void)
1307 GDK_THREADS_LEAVE ();
1308 g_main_context_iteration (NULL, TRUE);
1309 GDK_THREADS_ENTER ();
1312 return !g_main_loop_is_running (main_loops->data);
1318 gtk_main_iteration_do (gboolean blocking)
1320 GDK_THREADS_LEAVE ();
1321 g_main_context_iteration (NULL, blocking);
1322 GDK_THREADS_ENTER ();
1325 return !g_main_loop_is_running (main_loops->data);
1330 /* private libgtk to libgdk interfaces
1332 gboolean gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
1333 GdkWindow **grab_window,
1334 gboolean *owner_events);
1335 gboolean gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1336 GdkWindow **grab_window,
1337 gboolean *owner_events);
1340 rewrite_events_translate (GdkWindow *old_window,
1341 GdkWindow *new_window,
1345 gint old_origin_x, old_origin_y;
1346 gint new_origin_x, new_origin_y;
1348 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1349 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1351 *x += old_origin_x - new_origin_x;
1352 *y += old_origin_y - new_origin_y;
1356 rewrite_event_for_window (GdkEvent *event,
1357 GdkWindow *new_window)
1359 event = gdk_event_copy (event);
1361 switch (event->type)
1364 rewrite_events_translate (event->any.window,
1366 &event->scroll.x, &event->scroll.y);
1368 case GDK_BUTTON_PRESS:
1369 case GDK_2BUTTON_PRESS:
1370 case GDK_3BUTTON_PRESS:
1371 case GDK_BUTTON_RELEASE:
1372 rewrite_events_translate (event->any.window,
1374 &event->button.x, &event->button.y);
1376 case GDK_MOTION_NOTIFY:
1377 rewrite_events_translate (event->any.window,
1379 &event->motion.x, &event->motion.y);
1382 case GDK_KEY_RELEASE:
1383 case GDK_PROXIMITY_IN:
1384 case GDK_PROXIMITY_OUT:
1391 g_object_unref (event->any.window);
1392 event->any.window = g_object_ref (new_window);
1397 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1398 * then what X11 does is deliver the event normally if it was going to this
1399 * client, otherwise, delivers it in terms of the grab window. This function
1400 * rewrites events to the effect that events going to the same window group
1401 * are delivered normally, otherwise, the event is delivered in terms of the
1405 rewrite_event_for_grabs (GdkEvent *event)
1407 GdkWindow *grab_window;
1408 GtkWidget *event_widget, *grab_widget;
1409 gpointer grab_widget_ptr;
1410 gboolean owner_events;
1411 GdkDisplay *display;
1413 switch (event->type)
1416 case GDK_BUTTON_PRESS:
1417 case GDK_2BUTTON_PRESS:
1418 case GDK_3BUTTON_PRESS:
1419 case GDK_BUTTON_RELEASE:
1420 case GDK_MOTION_NOTIFY:
1421 case GDK_PROXIMITY_IN:
1422 case GDK_PROXIMITY_OUT:
1423 display = gdk_drawable_get_display (event->proximity.window);
1424 if (!gdk_pointer_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1430 case GDK_KEY_RELEASE:
1431 display = gdk_drawable_get_display (event->key.window);
1432 if (!gdk_keyboard_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1441 event_widget = gtk_get_event_widget (event);
1442 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1443 grab_widget = grab_widget_ptr;
1446 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1447 return rewrite_event_for_window (event, grab_window);
1453 gtk_main_do_event (GdkEvent *event)
1455 GtkWidget *event_widget;
1456 GtkWidget *grab_widget;
1457 GtkWindowGroup *window_group;
1458 GdkEvent *rewritten_event = NULL;
1461 if (event->type == GDK_SETTING)
1463 _gtk_settings_handle_event (&event->setting);
1467 if (event->type == GDK_OWNER_CHANGE)
1469 _gtk_clipboard_handle_event (&event->owner_change);
1473 /* Find the widget which got the event. We store the widget
1474 * in the user_data field of GdkWindow's.
1475 * Ignore the event if we don't have a widget for it, except
1476 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1477 * Though this happens rarely, bogus events can occour
1478 * for e.g. destroyed GdkWindows.
1480 event_widget = gtk_get_event_widget (event);
1483 /* To handle selection INCR transactions, we select
1484 * PropertyNotify events on the requestor window and create
1485 * a corresponding (fake) GdkWindow so that events get
1486 * here. There won't be a widget though, so we have to handle
1489 if (event->type == GDK_PROPERTY_NOTIFY)
1490 _gtk_selection_incr_event (event->any.window,
1496 /* If pointer or keyboard grabs are in effect, munge the events
1497 * so that each window group looks like a separate app.
1499 rewritten_event = rewrite_event_for_grabs (event);
1500 if (rewritten_event)
1502 event = rewritten_event;
1503 event_widget = gtk_get_event_widget (event);
1506 window_group = gtk_main_get_window_group (event_widget);
1508 /* Push the event onto a stack of current events for
1509 * gtk_current_event_get().
1511 current_events = g_list_prepend (current_events, event);
1513 /* If there is a grab in effect...
1515 if (window_group->grabs)
1517 grab_widget = window_group->grabs->data;
1519 /* If the grab widget is an ancestor of the event widget
1520 * then we send the event to the original event widget.
1521 * This is the key to implementing modality.
1523 if (gtk_widget_is_sensitive (event_widget) &&
1524 gtk_widget_is_ancestor (event_widget, grab_widget))
1525 grab_widget = event_widget;
1529 grab_widget = event_widget;
1532 /* Not all events get sent to the grabbing widget.
1533 * The delete, destroy, expose, focus change and resize
1534 * events still get sent to the event widget because
1535 * 1) these events have no meaning for the grabbing widget
1536 * and 2) redirecting these events to the grabbing widget
1537 * could cause the display to be messed up.
1539 * Drag events are also not redirected, since it isn't
1540 * clear what the semantics of that would be.
1542 switch (event->type)
1548 g_object_ref (event_widget);
1549 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1550 !gtk_widget_event (event_widget, event))
1551 gtk_widget_destroy (event_widget);
1552 g_object_unref (event_widget);
1556 /* Unexpected GDK_DESTROY from the outside, ignore for
1557 * child windows, handle like a GDK_DELETE for toplevels
1559 if (!event_widget->parent)
1561 g_object_ref (event_widget);
1562 if (!gtk_widget_event (event_widget, event) &&
1563 gtk_widget_get_realized (event_widget))
1564 gtk_widget_destroy (event_widget);
1565 g_object_unref (event_widget);
1570 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1572 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1573 gtk_widget_send_expose (event_widget, event);
1574 gdk_window_end_paint (event->any.window);
1578 /* The app may paint with a previously allocated cairo_t,
1579 which will draw directly to the window. We can't catch cairo
1580 drap operatoins to automatically flush the window, thus we
1581 need to explicitly flush any outstanding moves or double
1583 gdk_window_flush (event->any.window);
1584 gtk_widget_send_expose (event_widget, event);
1588 case GDK_PROPERTY_NOTIFY:
1590 case GDK_FOCUS_CHANGE:
1594 case GDK_SELECTION_CLEAR:
1595 case GDK_SELECTION_REQUEST:
1596 case GDK_SELECTION_NOTIFY:
1597 case GDK_CLIENT_EVENT:
1598 case GDK_VISIBILITY_NOTIFY:
1599 case GDK_WINDOW_STATE:
1600 case GDK_GRAB_BROKEN:
1602 gtk_widget_event (event_widget, event);
1606 case GDK_BUTTON_PRESS:
1607 case GDK_2BUTTON_PRESS:
1608 case GDK_3BUTTON_PRESS:
1609 gtk_propagate_event (grab_widget, event);
1613 case GDK_KEY_RELEASE:
1616 if (gtk_invoke_key_snoopers (grab_widget, event))
1619 /* Catch alt press to enable auto-mnemonics;
1620 * menus are handled elsewhere
1622 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1623 !GTK_IS_MENU_SHELL (grab_widget))
1625 gboolean auto_mnemonics;
1627 g_object_get (gtk_widget_get_settings (grab_widget),
1628 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1632 gboolean mnemonics_visible;
1635 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1637 window = gtk_widget_get_toplevel (grab_widget);
1639 if (GTK_IS_WINDOW (window))
1640 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1643 /* else fall through */
1644 case GDK_MOTION_NOTIFY:
1645 case GDK_BUTTON_RELEASE:
1646 case GDK_PROXIMITY_IN:
1647 case GDK_PROXIMITY_OUT:
1648 gtk_propagate_event (grab_widget, event);
1651 case GDK_ENTER_NOTIFY:
1652 GTK_PRIVATE_SET_FLAG (event_widget, GTK_HAS_POINTER);
1653 _gtk_widget_set_pointer_window (event_widget, event->any.window);
1654 if (gtk_widget_is_sensitive (grab_widget))
1655 gtk_widget_event (grab_widget, event);
1658 case GDK_LEAVE_NOTIFY:
1659 GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_HAS_POINTER);
1660 if (gtk_widget_is_sensitive (grab_widget))
1661 gtk_widget_event (grab_widget, event);
1664 case GDK_DRAG_STATUS:
1665 case GDK_DROP_FINISHED:
1666 _gtk_drag_source_handle_event (event_widget, event);
1668 case GDK_DRAG_ENTER:
1669 case GDK_DRAG_LEAVE:
1670 case GDK_DRAG_MOTION:
1671 case GDK_DROP_START:
1672 _gtk_drag_dest_handle_event (event_widget, event);
1675 g_assert_not_reached ();
1679 if (event->type == GDK_ENTER_NOTIFY
1680 || event->type == GDK_LEAVE_NOTIFY
1681 || event->type == GDK_BUTTON_PRESS
1682 || event->type == GDK_2BUTTON_PRESS
1683 || event->type == GDK_3BUTTON_PRESS
1684 || event->type == GDK_KEY_PRESS
1685 || event->type == GDK_DRAG_ENTER
1686 || event->type == GDK_GRAB_BROKEN
1687 || event->type == GDK_MOTION_NOTIFY
1688 || event->type == GDK_SCROLL)
1690 _gtk_tooltip_handle_event (event);
1693 tmp_list = current_events;
1694 current_events = g_list_remove_link (current_events, tmp_list);
1695 g_list_free_1 (tmp_list);
1697 if (rewritten_event)
1698 gdk_event_free (rewritten_event);
1713 static GtkWindowGroup *
1714 gtk_main_get_window_group (GtkWidget *widget)
1716 GtkWidget *toplevel = NULL;
1719 toplevel = gtk_widget_get_toplevel (widget);
1721 if (GTK_IS_WINDOW (toplevel))
1722 return gtk_window_get_group (GTK_WINDOW (toplevel));
1724 return gtk_window_get_group (NULL);
1729 GtkWidget *old_grab_widget;
1730 GtkWidget *new_grab_widget;
1731 gboolean was_grabbed;
1732 gboolean is_grabbed;
1737 gtk_grab_notify_foreach (GtkWidget *child,
1741 GrabNotifyInfo *info = data;
1743 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1745 was_grabbed = info->was_grabbed;
1746 is_grabbed = info->is_grabbed;
1748 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1749 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1751 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1752 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1754 g_object_ref (child);
1756 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1757 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1761 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1762 if (!was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1763 && gtk_widget_is_sensitive (child))
1764 _gtk_widget_synthesize_crossing (child, info->new_grab_widget,
1765 GDK_CROSSING_GTK_GRAB);
1769 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1770 if (was_shadowed && GTK_WIDGET_HAS_POINTER (child)
1771 && gtk_widget_is_sensitive (child))
1772 _gtk_widget_synthesize_crossing (info->old_grab_widget, child,
1773 info->from_grab ? GDK_CROSSING_GTK_GRAB
1774 : GDK_CROSSING_GTK_UNGRAB);
1777 if (was_shadowed != is_shadowed)
1778 _gtk_widget_grab_notify (child, was_shadowed);
1780 g_object_unref (child);
1782 info->was_grabbed = was_grabbed;
1783 info->is_grabbed = is_grabbed;
1787 gtk_grab_notify (GtkWindowGroup *group,
1788 GtkWidget *old_grab_widget,
1789 GtkWidget *new_grab_widget,
1793 GrabNotifyInfo info;
1795 if (old_grab_widget == new_grab_widget)
1798 info.old_grab_widget = old_grab_widget;
1799 info.new_grab_widget = new_grab_widget;
1800 info.from_grab = from_grab;
1802 g_object_ref (group);
1804 toplevels = gtk_window_list_toplevels ();
1805 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1809 GtkWindow *toplevel = toplevels->data;
1810 toplevels = g_list_delete_link (toplevels, toplevels);
1812 info.was_grabbed = FALSE;
1813 info.is_grabbed = FALSE;
1815 if (group == gtk_window_get_group (toplevel))
1816 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1817 g_object_unref (toplevel);
1820 g_object_unref (group);
1824 gtk_grab_add (GtkWidget *widget)
1826 GtkWindowGroup *group;
1827 GtkWidget *old_grab_widget;
1829 g_return_if_fail (widget != NULL);
1831 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1833 _gtk_widget_set_has_grab (widget, TRUE);
1835 group = gtk_main_get_window_group (widget);
1838 old_grab_widget = (GtkWidget *)group->grabs->data;
1840 old_grab_widget = NULL;
1842 g_object_ref (widget);
1843 group->grabs = g_slist_prepend (group->grabs, widget);
1845 gtk_grab_notify (group, old_grab_widget, widget, TRUE);
1850 gtk_grab_get_current (void)
1852 GtkWindowGroup *group;
1854 group = gtk_main_get_window_group (NULL);
1857 return GTK_WIDGET (group->grabs->data);
1862 gtk_grab_remove (GtkWidget *widget)
1864 GtkWindowGroup *group;
1865 GtkWidget *new_grab_widget;
1867 g_return_if_fail (widget != NULL);
1869 if (gtk_widget_has_grab (widget))
1871 _gtk_widget_set_has_grab (widget, FALSE);
1873 group = gtk_main_get_window_group (widget);
1874 group->grabs = g_slist_remove (group->grabs, widget);
1877 new_grab_widget = (GtkWidget *)group->grabs->data;
1879 new_grab_widget = NULL;
1881 gtk_grab_notify (group, widget, new_grab_widget, FALSE);
1883 g_object_unref (widget);
1888 gtk_init_add (GtkFunction function,
1891 GtkInitFunction *init;
1893 init = g_new (GtkInitFunction, 1);
1894 init->function = function;
1897 init_functions = g_list_prepend (init_functions, init);
1901 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
1904 GtkKeySnooperData *data;
1905 static guint snooper_id = 1;
1907 g_return_val_if_fail (snooper != NULL, 0);
1909 data = g_new (GtkKeySnooperData, 1);
1910 data->func = snooper;
1911 data->func_data = func_data;
1912 data->id = snooper_id++;
1913 key_snoopers = g_slist_prepend (key_snoopers, data);
1919 gtk_key_snooper_remove (guint snooper_id)
1921 GtkKeySnooperData *data = NULL;
1924 slist = key_snoopers;
1928 if (data->id == snooper_id)
1931 slist = slist->next;
1936 key_snoopers = g_slist_remove (key_snoopers, data);
1942 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
1946 gint return_val = FALSE;
1948 slist = key_snoopers;
1949 while (slist && !return_val)
1951 GtkKeySnooperData *data;
1954 slist = slist->next;
1955 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
1962 gtk_quit_add_full (guint main_level,
1963 GtkFunction function,
1964 GtkCallbackMarshal marshal,
1966 GDestroyNotify destroy)
1968 static guint quit_id = 1;
1969 GtkQuitFunction *quitf;
1971 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
1973 quitf = g_slice_new (GtkQuitFunction);
1975 quitf->id = quit_id++;
1976 quitf->main_level = main_level;
1977 quitf->function = function;
1978 quitf->marshal = marshal;
1980 quitf->destroy = destroy;
1982 quit_functions = g_list_prepend (quit_functions, quitf);
1988 gtk_quit_destroy (GtkQuitFunction *quitf)
1991 quitf->destroy (quitf->data);
1992 g_slice_free (GtkQuitFunction, quitf);
1996 gtk_quit_destructor (GtkObject **object_p)
1999 gtk_object_destroy (*object_p);
2006 gtk_quit_add_destroy (guint main_level,
2009 GtkObject **object_p;
2011 g_return_if_fail (main_level > 0);
2012 g_return_if_fail (GTK_IS_OBJECT (object));
2014 object_p = g_new (GtkObject*, 1);
2016 g_signal_connect (object,
2018 G_CALLBACK (gtk_widget_destroyed),
2020 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2024 gtk_quit_add (guint main_level,
2025 GtkFunction function,
2028 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2032 gtk_quit_remove (guint id)
2034 GtkQuitFunction *quitf;
2037 tmp_list = quit_functions;
2040 quitf = tmp_list->data;
2042 if (quitf->id == id)
2044 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2045 g_list_free (tmp_list);
2046 gtk_quit_destroy (quitf);
2051 tmp_list = tmp_list->next;
2056 gtk_quit_remove_by_data (gpointer data)
2058 GtkQuitFunction *quitf;
2061 tmp_list = quit_functions;
2064 quitf = tmp_list->data;
2066 if (quitf->data == data)
2068 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2069 g_list_free (tmp_list);
2070 gtk_quit_destroy (quitf);
2075 tmp_list = tmp_list->next;
2080 gtk_timeout_add_full (guint32 interval,
2081 GtkFunction function,
2082 GtkCallbackMarshal marshal,
2084 GDestroyNotify destroy)
2088 GtkClosure *closure;
2090 closure = g_new (GtkClosure, 1);
2091 closure->marshal = marshal;
2092 closure->data = data;
2093 closure->destroy = destroy;
2095 return g_timeout_add_full (0, interval,
2096 gtk_invoke_idle_timeout,
2098 gtk_destroy_closure);
2101 return g_timeout_add_full (0, interval, function, data, destroy);
2105 gtk_timeout_add (guint32 interval,
2106 GtkFunction function,
2109 return g_timeout_add_full (0, interval, function, data, NULL);
2113 gtk_timeout_remove (guint tag)
2115 g_source_remove (tag);
2119 gtk_idle_add_full (gint priority,
2120 GtkFunction function,
2121 GtkCallbackMarshal marshal,
2123 GDestroyNotify destroy)
2127 GtkClosure *closure;
2129 closure = g_new (GtkClosure, 1);
2130 closure->marshal = marshal;
2131 closure->data = data;
2132 closure->destroy = destroy;
2134 return g_idle_add_full (priority,
2135 gtk_invoke_idle_timeout,
2137 gtk_destroy_closure);
2140 return g_idle_add_full (priority, function, data, destroy);
2144 gtk_idle_add (GtkFunction function,
2147 return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
2151 gtk_idle_add_priority (gint priority,
2152 GtkFunction function,
2155 return g_idle_add_full (priority, function, data, NULL);
2159 gtk_idle_remove (guint tag)
2161 g_source_remove (tag);
2165 gtk_idle_remove_by_data (gpointer data)
2167 if (!g_idle_remove_by_data (data))
2168 g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
2172 gtk_input_add_full (gint source,
2173 GdkInputCondition condition,
2174 GdkInputFunction function,
2175 GtkCallbackMarshal marshal,
2177 GDestroyNotify destroy)
2181 GtkClosure *closure;
2183 closure = g_new (GtkClosure, 1);
2184 closure->marshal = marshal;
2185 closure->data = data;
2186 closure->destroy = destroy;
2188 return gdk_input_add_full (source,
2190 (GdkInputFunction) gtk_invoke_input,
2192 (GDestroyNotify) gtk_destroy_closure);
2195 return gdk_input_add_full (source, condition, function, data, destroy);
2199 gtk_input_remove (guint tag)
2201 g_source_remove (tag);
2205 gtk_destroy_closure (gpointer data)
2207 GtkClosure *closure = data;
2209 if (closure->destroy)
2210 (closure->destroy) (closure->data);
2215 gtk_invoke_idle_timeout (gpointer data)
2217 GtkClosure *closure = data;
2220 gint ret_val = FALSE;
2221 args[0].name = NULL;
2222 args[0].type = G_TYPE_BOOLEAN;
2223 args[0].d.pointer_data = &ret_val;
2224 closure->marshal (NULL, closure->data, 0, args);
2229 gtk_invoke_input (gpointer data,
2231 GdkInputCondition condition)
2233 GtkClosure *closure = data;
2236 args[0].type = G_TYPE_INT;
2237 args[0].name = NULL;
2238 GTK_VALUE_INT (args[0]) = source;
2239 args[1].type = GDK_TYPE_INPUT_CONDITION;
2240 args[1].name = NULL;
2241 GTK_VALUE_FLAGS (args[1]) = condition;
2242 args[2].type = G_TYPE_NONE;
2243 args[2].name = NULL;
2245 closure->marshal (NULL, closure->data, 2, args);
2249 * gtk_get_current_event:
2251 * Obtains a copy of the event currently being processed by GTK+. For
2252 * example, if you get a "clicked" signal from #GtkButton, the current
2253 * event will be the #GdkEventButton that triggered the "clicked"
2254 * signal. The returned event must be freed with gdk_event_free().
2255 * If there is no current event, the function returns %NULL.
2257 * Return value: a copy of the current event, or %NULL if no current event.
2260 gtk_get_current_event (void)
2263 return gdk_event_copy (current_events->data);
2269 * gtk_get_current_event_time:
2271 * If there is a current event and it has a timestamp, return that
2272 * timestamp, otherwise return %GDK_CURRENT_TIME.
2274 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2277 gtk_get_current_event_time (void)
2280 return gdk_event_get_time (current_events->data);
2282 return GDK_CURRENT_TIME;
2286 * gtk_get_current_event_state:
2287 * @state: a location to store the state of the current event
2289 * If there is a current event and it has a state field, place
2290 * that state field in @state and return %TRUE, otherwise return
2293 * Return value: %TRUE if there was a current event and it had a state field
2296 gtk_get_current_event_state (GdkModifierType *state)
2298 g_return_val_if_fail (state != NULL, FALSE);
2301 return gdk_event_get_state (current_events->data, state);
2310 * gtk_get_event_widget:
2311 * @event: a #GdkEvent
2313 * If @event is %NULL or the event was not associated with any widget,
2314 * returns %NULL, otherwise returns the widget that received the event
2317 * Return value: the widget that originally received @event, or %NULL
2320 gtk_get_event_widget (GdkEvent *event)
2323 gpointer widget_ptr;
2326 if (event && event->any.window &&
2327 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2329 gdk_window_get_user_data (event->any.window, &widget_ptr);
2330 widget = widget_ptr;
2337 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2339 if (!quitf->marshal)
2340 return quitf->function (quitf->data);
2344 gint ret_val = FALSE;
2346 args[0].name = NULL;
2347 args[0].type = G_TYPE_BOOLEAN;
2348 args[0].d.pointer_data = &ret_val;
2349 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2357 * gtk_propagate_event:
2358 * @widget: a #GtkWidget
2361 * Sends an event to a widget, propagating the event to parent widgets
2362 * if the event remains unhandled. Events received by GTK+ from GDK
2363 * normally begin in gtk_main_do_event(). Depending on the type of
2364 * event, existence of modal dialogs, grabs, etc., the event may be
2365 * propagated; if so, this function is used. gtk_propagate_event()
2366 * calls gtk_widget_event() on each widget it decides to send the
2367 * event to. So gtk_widget_event() is the lowest-level function; it
2368 * simply emits the "event" and possibly an event-specific signal on a
2369 * widget. gtk_propagate_event() is a bit higher-level, and
2370 * gtk_main_do_event() is the highest level.
2372 * All that said, you most likely don't want to use any of these
2373 * functions; synthesizing events is rarely needed. Consider asking on
2374 * the mailing list for better ways to achieve your goals. For
2375 * example, use gdk_window_invalidate_rect() or
2376 * gtk_widget_queue_draw() instead of making up expose events.
2380 gtk_propagate_event (GtkWidget *widget,
2385 g_return_if_fail (GTK_IS_WIDGET (widget));
2386 g_return_if_fail (event != NULL);
2388 handled_event = FALSE;
2390 g_object_ref (widget);
2392 if ((event->type == GDK_KEY_PRESS) ||
2393 (event->type == GDK_KEY_RELEASE))
2395 /* Only send key events within Window widgets to the Window
2396 * The Window widget will in turn pass the
2397 * key event on to the currently focused widget
2402 window = gtk_widget_get_toplevel (widget);
2403 if (GTK_IS_WINDOW (window))
2405 /* If there is a grab within the window, give the grab widget
2406 * a first crack at the key event
2408 if (widget != window && gtk_widget_has_grab (widget))
2409 handled_event = gtk_widget_event (widget, event);
2413 window = gtk_widget_get_toplevel (widget);
2414 if (GTK_IS_WINDOW (window))
2416 if (gtk_widget_is_sensitive (window))
2417 gtk_widget_event (window, event);
2421 handled_event = TRUE; /* don't send to widget */
2425 /* Other events get propagated up the widget tree
2426 * so that parents can see the button and motion
2427 * events of the children.
2435 /* Scroll events are special cased here because it
2436 * feels wrong when scrolling a GtkViewport, say,
2437 * to have children of the viewport eat the scroll
2440 if (!gtk_widget_is_sensitive (widget))
2441 handled_event = event->type != GDK_SCROLL;
2443 handled_event = gtk_widget_event (widget, event);
2445 tmp = widget->parent;
2446 g_object_unref (widget);
2450 if (!handled_event && widget)
2451 g_object_ref (widget);
2457 g_object_unref (widget);
2462 gtk_error (gchar *str)
2468 gtk_warning (gchar *str)
2474 gtk_message (gchar *str)
2480 gtk_print (gchar *str)
2482 static GtkWidget *window = NULL;
2483 static GtkWidget *text;
2484 static int level = 0;
2488 GtkWidget *hscrollbar;
2489 GtkWidget *vscrollbar;
2490 GtkWidget *separator;
2495 fputs (str, stdout);
2502 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2504 gtk_signal_connect (GTK_OBJECT (window), "destroy",
2505 G_CALLBACK (gtk_widget_destroyed),
2508 gtk_window_set_title (GTK_WINDOW (window), "Messages");
2510 box1 = gtk_vbox_new (FALSE, 0);
2511 gtk_container_add (GTK_CONTAINER (window), box1);
2512 gtk_widget_show (box1);
2515 box2 = gtk_vbox_new (FALSE, 10);
2516 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2517 gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2518 gtk_widget_show (box2);
2521 table = gtk_table_new (2, 2, FALSE);
2522 gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2523 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2524 gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2525 gtk_widget_show (table);
2527 text = gtk_text_new (NULL, NULL);
2528 gtk_text_set_editable (GTK_TEXT (text), FALSE);
2529 gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2530 gtk_widget_show (text);
2531 gtk_widget_realize (text);
2533 hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2534 gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2535 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2536 gtk_widget_show (hscrollbar);
2538 vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2539 gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2540 GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2541 gtk_widget_show (vscrollbar);
2543 separator = gtk_hseparator_new ();
2544 gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2545 gtk_widget_show (separator);
2548 box2 = gtk_vbox_new (FALSE, 10);
2549 gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2550 gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2551 gtk_widget_show (box2);
2554 button = gtk_button_new_with_label ("close");
2555 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2556 G_CALLBACK (gtk_widget_hide),
2557 GTK_OBJECT (window));
2558 gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2559 gtk_widget_set_can_default (button, TRUE);
2560 gtk_widget_grab_default (button);
2561 gtk_widget_show (button);
2565 gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2568 if (!gtk_widget_get_visible (window))
2569 gtk_widget_show (window);
2574 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2575 GValue *return_accu,
2576 const GValue *handler_return,
2579 gboolean continue_emission;
2580 gboolean signal_handled;
2582 signal_handled = g_value_get_boolean (handler_return);
2583 g_value_set_boolean (return_accu, signal_handled);
2584 continue_emission = !signal_handled;
2586 return continue_emission;
2589 #define __GTK_MAIN_C__
2590 #include "gtkaliasdef.c"