1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdkconfig.h"
40 #include <sys/types.h> /* For uid_t, gid_t */
50 #include "gtkaccelmap.h"
52 #include "gtkclipboard.h"
54 #include "gtkversion.h"
56 #include "gtkmodules.h"
58 #include "gtkrecentmanager.h"
59 #include "gtkselection.h"
60 #include "gtksettings.h"
61 #include "gtkwidget.h"
62 #include "gtkwindow.h"
63 #include "gtktooltip.h"
67 #include "gdk/gdkkeysyms.h"
69 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
73 static HMODULE gtk_dll;
76 DllMain (HINSTANCE hinstDLL,
82 case DLL_PROCESS_ATTACH:
83 gtk_dll = (HMODULE) hinstDLL;
90 /* These here before inclusion of gtkprivate.h so that the original
91 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
95 _gtk_get_libdir (void)
97 static char *gtk_libdir = NULL;
98 if (gtk_libdir == NULL)
100 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
101 gchar *slash = strrchr (root, '\\');
102 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
103 gtk_libdir = GTK_LIBDIR;
105 gtk_libdir = g_build_filename (root, "lib", NULL);
113 _gtk_get_localedir (void)
115 static char *gtk_localedir = NULL;
116 if (gtk_localedir == NULL)
121 /* GTK_LOCALEDIR ends in either /lib/locale or
122 * /share/locale. Scan for that slash.
124 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
130 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
131 temp = g_build_filename (root, p, NULL);
134 /* gtk_localedir is passed to bindtextdomain() which isn't
137 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
140 return gtk_localedir;
145 #include "gtkprivate.h"
147 /* Private type definitions
149 typedef struct _GtkInitFunction GtkInitFunction;
150 typedef struct _GtkQuitFunction GtkQuitFunction;
151 typedef struct _GtkKeySnooperData GtkKeySnooperData;
153 struct _GtkInitFunction
155 GtkFunction function;
159 struct _GtkQuitFunction
163 GtkCallbackMarshal marshal;
164 GtkFunction function;
166 GDestroyNotify destroy;
169 struct _GtkKeySnooperData
171 GtkKeySnoopFunc func;
176 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
177 static void gtk_quit_destroy (GtkQuitFunction *quitf);
178 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
181 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
183 const guint gtk_major_version = GTK_MAJOR_VERSION;
184 const guint gtk_minor_version = GTK_MINOR_VERSION;
185 const guint gtk_micro_version = GTK_MICRO_VERSION;
186 const guint gtk_binary_age = GTK_BINARY_AGE;
187 const guint gtk_interface_age = GTK_INTERFACE_AGE;
189 static guint gtk_main_loop_level = 0;
190 static gint pre_initialized = FALSE;
191 static gint gtk_initialized = FALSE;
192 static GList *current_events = NULL;
194 static GSList *main_loops = NULL; /* stack of currently executing main loops */
196 static GList *init_functions = NULL; /* A list of init functions.
198 static GList *quit_functions = NULL; /* A list of quit functions.
200 static GSList *key_snoopers = NULL;
202 guint gtk_debug_flags = 0; /* Global GTK debug flag */
204 #ifdef G_ENABLE_DEBUG
205 static const GDebugKey gtk_debug_keys[] = {
206 {"misc", GTK_DEBUG_MISC},
207 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
208 {"text", GTK_DEBUG_TEXT},
209 {"tree", GTK_DEBUG_TREE},
210 {"updates", GTK_DEBUG_UPDATES},
211 {"keybindings", GTK_DEBUG_KEYBINDINGS},
212 {"multihead", GTK_DEBUG_MULTIHEAD},
213 {"modules", GTK_DEBUG_MODULES},
214 {"geometry", GTK_DEBUG_GEOMETRY},
215 {"icontheme", GTK_DEBUG_ICONTHEME},
216 {"printing", GTK_DEBUG_PRINTING},
217 {"builder", GTK_DEBUG_BUILDER},
218 {"extended-layout", GTK_DEBUG_EXTENDED_LAYOUT},
220 #endif /* G_ENABLE_DEBUG */
224 * @required_major: the required major version.
225 * @required_minor: the required minor version.
226 * @required_micro: the required micro version.
228 * Checks that the GTK+ library in use is compatible with the
229 * given version. Generally you would pass in the constants
230 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
231 * as the three arguments to this function; that produces
232 * a check that the library in use is compatible with
233 * the version of GTK+ the application or module was compiled
236 * Compatibility is defined by two things: first the version
237 * of the running library is newer than the version
238 * @required_major.required_minor.@required_micro. Second
239 * the running library must be binary compatible with the
240 * version @required_major.required_minor.@required_micro
241 * (same major version.)
243 * This function is primarily for GTK+ modules; the module
244 * can call this function to check that it wasn't loaded
245 * into an incompatible version of GTK+. However, such a
246 * a check isn't completely reliable, since the module may be
247 * linked against an old version of GTK+ and calling the
248 * old version of gtk_check_version(), but still get loaded
249 * into an application using a newer version of GTK+.
251 * Return value: %NULL if the GTK+ library is compatible with the
252 * given version, or a string describing the version mismatch.
253 * The returned string is owned by GTK+ and should not be modified
257 gtk_check_version (guint required_major,
258 guint required_minor,
259 guint required_micro)
261 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
262 gint required_effective_micro = 100 * required_minor + required_micro;
264 if (required_major > GTK_MAJOR_VERSION)
265 return "Gtk+ version too old (major mismatch)";
266 if (required_major < GTK_MAJOR_VERSION)
267 return "Gtk+ version too new (major mismatch)";
268 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
269 return "Gtk+ version too new (micro mismatch)";
270 if (required_effective_micro > gtk_effective_micro)
271 return "Gtk+ version too old (micro mismatch)";
275 /* This checks to see if the process is running suid or sgid
276 * at the current time. If so, we don't allow GTK+ to be initialized.
277 * This is meant to be a mild check - we only error out if we
278 * can prove the programmer is doing something wrong, not if
279 * they could be doing something wrong. For this reason, we
280 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
285 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
287 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
288 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
290 #ifdef HAVE_GETRESUID
291 /* These aren't in the header files, so we prototype them here.
293 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
294 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
296 if (getresuid (&ruid, &euid, &suid) != 0 ||
297 getresgid (&rgid, &egid, &sgid) != 0)
298 #endif /* HAVE_GETRESUID */
300 suid = ruid = getuid ();
301 sgid = rgid = getgid ();
306 if (ruid != euid || ruid != suid ||
307 rgid != egid || rgid != sgid)
309 g_warning ("This process is currently running setuid or setgid.\n"
310 "This is not a supported use of GTK+. You must create a helper\n"
311 "program instead. For further details, see:\n\n"
312 " http://www.gtk.org/setuid.html\n\n"
313 "Refusing to initialize GTK+.");
323 _gtk_get_datadir (void)
325 static char *gtk_datadir = NULL;
326 if (gtk_datadir == NULL)
328 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
329 gtk_datadir = g_build_filename (root, "share", NULL);
337 _gtk_get_sysconfdir (void)
339 static char *gtk_sysconfdir = NULL;
340 if (gtk_sysconfdir == NULL)
342 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
343 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
347 return gtk_sysconfdir;
351 _gtk_get_data_prefix (void)
353 static char *gtk_data_prefix = NULL;
354 if (gtk_data_prefix == NULL)
355 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
357 return gtk_data_prefix;
360 #endif /* G_OS_WIN32 */
362 static gboolean do_setlocale = TRUE;
365 * gtk_disable_setlocale:
367 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
368 * gtk_parse_args() from automatically
369 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
370 * want to use this function if you wanted to set the locale for
371 * your program to something other than the user's locale, or if
372 * you wanted to set different values for different locale categories.
374 * Most programs should not need to call this function.
377 gtk_disable_setlocale (void)
380 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
382 do_setlocale = FALSE;
385 #ifdef G_PLATFORM_WIN32
386 #undef gtk_init_check
389 static GString *gtk_modules_string = NULL;
390 static gboolean g_fatal_warnings = FALSE;
392 #ifdef G_ENABLE_DEBUG
394 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
396 gtk_debug_flags |= g_parse_debug_string (value,
398 G_N_ELEMENTS (gtk_debug_keys));
404 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
406 gtk_debug_flags &= ~g_parse_debug_string (value,
408 G_N_ELEMENTS (gtk_debug_keys));
412 #endif /* G_ENABLE_DEBUG */
415 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
419 if (gtk_modules_string)
420 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
422 gtk_modules_string = g_string_new (NULL);
424 g_string_append (gtk_modules_string, value);
430 static const GOptionEntry gtk_args[] = {
431 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
432 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
433 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
434 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
435 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
436 #ifdef G_ENABLE_DEBUG
437 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
438 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
439 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
440 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
441 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
442 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
449 static char *iso639_to_check = NULL;
450 static char *iso3166_to_check = NULL;
451 static char *script_to_check = NULL;
452 static gboolean setlocale_called = FALSE;
455 enum_locale_proc (LPTSTR locale)
463 lcid = strtoul (locale, &endptr, 16);
464 if (*endptr == '\0' &&
465 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
466 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
468 if (strcmp (iso639, iso639_to_check) == 0 &&
469 ((iso3166_to_check != NULL &&
470 strcmp (iso3166, iso3166_to_check) == 0) ||
471 (iso3166_to_check == NULL &&
472 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
474 char language[100], country[100];
477 if (script_to_check != NULL)
479 /* If lcid is the "other" script for this language,
480 * return TRUE, i.e. continue looking.
482 if (strcmp (script_to_check, "Latn") == 0)
484 switch (LANGIDFROMLCID (lcid))
486 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
488 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
490 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
492 case MAKELANGID (LANG_SERBIAN, 0x07):
493 /* Serbian in Bosnia and Herzegovina, Cyrillic */
497 else if (strcmp (script_to_check, "Cyrl") == 0)
499 switch (LANGIDFROMLCID (lcid))
501 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
503 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
505 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
507 case MAKELANGID (LANG_SERBIAN, 0x06):
508 /* Serbian in Bosnia and Herzegovina, Latin */
514 SetThreadLocale (lcid);
516 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
517 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
519 strcpy (locale, language);
520 strcat (locale, "_");
521 strcat (locale, country);
523 if (setlocale (LC_ALL, locale) != NULL)
524 setlocale_called = TRUE;
537 setlocale_initialization (void)
539 static gboolean initialized = FALSE;
548 /* If some of the POSIXish environment variables are set, set
549 * the Win32 thread locale correspondingly.
551 char *p = getenv ("LC_ALL");
558 if (strcmp (p, "C") == 0)
559 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
562 /* Check if one of the supported locales match the
563 * environment variable. If so, use that locale.
566 iso3166_to_check = strchr (iso639_to_check, '_');
567 if (iso3166_to_check != NULL)
569 *iso3166_to_check++ = '\0';
571 script_to_check = strchr (iso3166_to_check, '@');
572 if (script_to_check != NULL)
573 *script_to_check++ = '\0';
575 /* Handle special cases. */
577 /* The standard code for Serbia and Montenegro was
578 * "CS", but MSFT uses for some reason "SP". By now
579 * (October 2006), SP has split into two, "RS" and
580 * "ME", but don't bother trying to handle those
581 * yet. Do handle the even older "YU", though.
583 if (strcmp (iso3166_to_check, "CS") == 0 ||
584 strcmp (iso3166_to_check, "YU") == 0)
585 iso3166_to_check = "SP";
589 script_to_check = strchr (iso639_to_check, '@');
590 if (script_to_check != NULL)
591 *script_to_check++ = '\0';
592 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
593 if (strcmp (iso639_to_check, "sr") == 0)
594 iso3166_to_check = "SP";
597 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
601 if (!setlocale_called)
602 setlocale (LC_ALL, "");
604 if (!setlocale (LC_ALL, ""))
605 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
611 do_pre_parse_initialization (int *argc,
614 const gchar *env_string;
619 pre_initialized = TRUE;
621 gdk_pre_parse_libgtk_only ();
622 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
624 #ifdef G_ENABLE_DEBUG
625 env_string = g_getenv ("GTK_DEBUG");
626 if (env_string != NULL)
628 gtk_debug_flags = g_parse_debug_string (env_string,
630 G_N_ELEMENTS (gtk_debug_keys));
633 #endif /* G_ENABLE_DEBUG */
635 env_string = g_getenv ("GTK_MODULES");
637 gtk_modules_string = g_string_new (env_string);
641 gettext_initialization (void)
643 setlocale_initialization ();
646 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
647 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
648 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
649 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
650 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
656 do_post_parse_initialization (int *argc,
662 gettext_initialization ();
665 signal (SIGPIPE, SIG_IGN);
668 if (g_fatal_warnings)
670 GLogLevelFlags fatal_mask;
672 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
673 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
674 g_log_set_always_fatal (fatal_mask);
677 if (gtk_debug_flags & GTK_DEBUG_UPDATES)
678 gdk_window_set_debug_updates (TRUE);
681 /* Translate to default:RTL if you want your widgets
682 * to be RTL, otherwise translate to default:LTR.
683 * Do *not* translate it to "predefinito:LTR", if it
684 * it isn't default:LTR or default:RTL it will not work
686 char *e = _("default:LTR");
687 if (strcmp (e, "default:RTL")==0)
688 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
689 else if (strcmp (e, "default:LTR"))
690 g_warning ("Whoever translated default:LTR did so wrongly.\n");
693 /* do what the call to gtk_type_init() used to do */
696 _gtk_accel_map_init ();
699 /* Set the 'initialized' flag.
701 gtk_initialized = TRUE;
703 /* load gtk modules */
704 if (gtk_modules_string)
706 _gtk_modules_init (argc, argv, gtk_modules_string->str);
707 g_string_free (gtk_modules_string, TRUE);
711 _gtk_modules_init (argc, argv, NULL);
718 gboolean open_default_display;
722 pre_parse_hook (GOptionContext *context,
727 do_pre_parse_initialization (NULL, NULL);
733 post_parse_hook (GOptionContext *context,
738 OptionGroupInfo *info = data;
741 do_post_parse_initialization (NULL, NULL);
743 if (info->open_default_display)
745 if (gdk_display_open_default_libgtk_only () == NULL)
747 const char *display_name = gdk_get_display_arg_name ();
750 G_OPTION_ERROR_FAILED,
751 _("Cannot open display: %s"),
752 display_name ? display_name : "" );
763 * gtk_get_option_group:
764 * @open_default_display: whether to open the default display
765 * when parsing the commandline arguments
767 * Returns a #GOptionGroup for the commandline arguments recognized
768 * by GTK+ and GDK. You should add this group to your #GOptionContext
769 * with g_option_context_add_group(), if you are using
770 * g_option_context_parse() to parse your commandline arguments.
772 * Returns: a #GOptionGroup for the commandline arguments recognized
778 gtk_get_option_group (gboolean open_default_display)
781 OptionGroupInfo *info;
783 gettext_initialization ();
785 info = g_new0 (OptionGroupInfo, 1);
786 info->open_default_display = open_default_display;
788 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
789 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
791 gdk_add_option_entries_libgtk_only (group);
792 g_option_group_add_entries (group, gtk_args);
793 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
799 * gtk_init_with_args:
800 * @argc: a pointer to the number of command line arguments.
801 * @argv: a pointer to the array of command line arguments.
802 * @parameter_string: a string which is displayed in
803 * the first line of <option>--help</option> output, after
804 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
805 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
806 * describing the options of your program
807 * @translation_domain: a translation domain to use for translating
808 * the <option>--help</option> output for the options in @entries
809 * with gettext(), or %NULL
810 * @error: a return location for errors
812 * This function does the same work as gtk_init_check().
813 * Additionally, it allows you to add your own commandline options,
814 * and it automatically generates nicely formatted
815 * <option>--help</option> output. Note that your program will
816 * be terminated after writing out the help output.
818 * Returns: %TRUE if the GUI has been successfully initialized,
824 gtk_init_with_args (int *argc,
826 const char *parameter_string,
827 GOptionEntry *entries,
828 const char *translation_domain,
831 GOptionContext *context;
832 GOptionGroup *gtk_group;
836 return gdk_display_open_default_libgtk_only () != NULL;
838 gettext_initialization ();
840 if (!check_setugid ())
843 gtk_group = gtk_get_option_group (TRUE);
845 context = g_option_context_new (parameter_string);
846 g_option_context_add_group (context, gtk_group);
849 g_option_context_add_main_entries (context, entries, translation_domain);
850 retval = g_option_context_parse (context, argc, argv, error);
852 g_option_context_free (context);
860 * @argc: (inout): a pointer to the number of command line arguments.
861 * @argv: (array) (inout): a pointer to the array of command line arguments.
863 * Parses command line arguments, and initializes global
864 * attributes of GTK+, but does not actually open a connection
865 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
867 * Any arguments used by GTK+ or GDK are removed from the array and
868 * @argc and @argv are updated accordingly.
870 * You shouldn't call this function explicitely if you are using
871 * gtk_init(), or gtk_init_check().
873 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
876 gtk_parse_args (int *argc,
879 GOptionContext *option_context;
880 GOptionGroup *gtk_group;
881 GError *error = NULL;
886 gettext_initialization ();
888 if (!check_setugid ())
891 option_context = g_option_context_new (NULL);
892 g_option_context_set_ignore_unknown_options (option_context, TRUE);
893 g_option_context_set_help_enabled (option_context, FALSE);
894 gtk_group = gtk_get_option_group (FALSE);
895 g_option_context_set_main_group (option_context, gtk_group);
896 if (!g_option_context_parse (option_context, argc, argv, &error))
898 g_warning ("%s", error->message);
899 g_error_free (error);
902 g_option_context_free (option_context);
907 #ifdef G_PLATFORM_WIN32
908 #undef gtk_init_check
913 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
914 * main() function. Changed if any arguments were handled.
915 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
916 * Any parameters understood by gtk_init() are stripped before return.
918 * This function does the same work as gtk_init() with only
919 * a single change: It does not terminate the program if the GUI can't be
920 * initialized. Instead it returns %FALSE on failure.
922 * This way the application can fall back to some other means of communication
923 * with the user - for example a curses or command line interface.
925 * Return value: %TRUE if the GUI has been successfully initialized,
929 gtk_init_check (int *argc,
932 if (!gtk_parse_args (argc, argv))
935 return gdk_display_open_default_libgtk_only () != NULL;
938 #ifdef G_PLATFORM_WIN32
944 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
945 * main() function. Changed if any arguments were handled.
946 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
947 * Any parameters understood by gtk_init() are stripped before return.
949 * Call this function before using any other GTK+ functions in your GUI
950 * applications. It will initialize everything needed to operate the
951 * toolkit and parses some standard command line options. @argc and
952 * @argv are adjusted accordingly so your own code will
953 * never see those standard arguments.
955 * Note that there are some alternative ways to initialize GTK+:
956 * if you are calling gtk_parse_args(), gtk_init_check(),
957 * gtk_init_with_args() or g_option_context_parse() with
958 * the option group returned by gtk_get_option_group(), you
959 * <emphasis>don't</emphasis> have to call gtk_init().
962 * This function will terminate your program if it was unable to initialize
963 * the GUI for some reason. If you want your program to fall back to a
964 * textual interface you want to call gtk_init_check() instead.
968 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
969 * during initialization, to ignore SIGPIPE signals, since these are
970 * almost never wanted in graphical applications. If you do need to
971 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
972 * but notice that other libraries (e.g. libdbus or gvfs) might do
977 gtk_init (int *argc, char ***argv)
979 if (!gtk_init_check (argc, argv))
981 const char *display_name_arg = gdk_get_display_arg_name ();
982 if (display_name_arg == NULL)
983 display_name_arg = getenv("DISPLAY");
984 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
989 #ifdef G_PLATFORM_WIN32
992 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
994 if (sizeof_GtkWindow != sizeof (GtkWindow))
995 g_error ("Incompatible build!\n"
996 "The code using GTK+ thinks GtkWindow is of different\n"
997 "size than it actually is in this build of GTK+.\n"
998 "On Windows, this probably means that you have compiled\n"
999 "your code with gcc without the -mms-bitfields switch,\n"
1000 "or that you are using an unsupported compiler.");
1003 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1004 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1005 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1006 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1007 * -fnative-struct still matters. GtkBox is one such.
1010 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1012 if (sizeof_GtkBox != sizeof (GtkBox))
1013 g_error ("Incompatible build!\n"
1014 "The code using GTK+ thinks GtkBox is of different\n"
1015 "size than it actually is in this build of GTK+.\n"
1016 "On Windows, this probably means that you have compiled\n"
1017 "your code with gcc without the -mms-bitfields switch,\n"
1018 "or that you are using an unsupported compiler.");
1021 /* These two functions might get more checks added later, thus pass
1022 * in the number of extra args.
1025 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1027 check_sizeof_GtkWindow (sizeof_GtkWindow);
1028 if (num_checks >= 2)
1029 check_sizeof_GtkBox (sizeof_GtkBox);
1030 gtk_init (argc, argv);
1034 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1036 check_sizeof_GtkWindow (sizeof_GtkWindow);
1037 if (num_checks >= 2)
1038 check_sizeof_GtkBox (sizeof_GtkBox);
1039 return gtk_init_check (argc, argv);
1047 * Initializes internationalization support for GTK+. gtk_init()
1048 * automatically does this, so there is typically no point
1049 * in calling this function.
1051 * If you are calling this function because you changed the locale
1052 * after GTK+ is was initialized, then calling this function
1053 * may help a bit. (Note, however, that changing the locale
1054 * after GTK+ is initialized may produce inconsistent results and
1055 * is not really supported.)
1057 * In detail - sets the current locale according to the
1058 * program environment. This is the same as calling the C library function
1059 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1060 * locale specific setup of the windowing system used by GDK.
1062 * Returns: a string corresponding to the locale set, typically in the
1063 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1064 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1065 * result of the setlocale(); it is also used on other machines, such as
1066 * Windows, where the C library returns a different result. The string is
1067 * owned by GTK+ and should not be modified or freed.
1070 gtk_set_locale (void)
1072 return gdk_set_locale ();
1076 * _gtk_get_lc_ctype:
1078 * Return the Unix-style locale string for the language currently in
1079 * effect. On Unix systems, this is the return value from
1080 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1081 * affect this through the environment variables LC_ALL, LC_CTYPE or
1082 * LANG (checked in that order). The locale strings typically is in
1083 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1084 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1085 * Swedish as written in Finland or pt_BR for Portuguese as written in
1088 * On Windows, the C library doesn't use any such environment
1089 * variables, and setting them won't affect the behaviour of functions
1090 * like ctime(). The user sets the locale through the Regional Options
1091 * in the Control Panel. The C library (in the setlocale() function)
1092 * does not use country and language codes, but country and language
1093 * names spelled out in English.
1094 * However, this function does check the above environment
1095 * variables, and does return a Unix-style locale string based on
1096 * either said environment variables or the thread's current locale.
1098 * Return value: a dynamically allocated string, free with g_free().
1102 _gtk_get_lc_ctype (void)
1105 /* Somebody might try to set the locale for this process using the
1106 * LANG or LC_ environment variables. The Microsoft C library
1107 * doesn't know anything about them. You set the locale in the
1108 * Control Panel. Setting these env vars won't have any affect on
1109 * locale-dependent C library functions like ctime(). But just for
1110 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1111 * it easier to test GTK and Pango in various default languages, you
1112 * don't have to clickety-click in the Control Panel, you can simply
1113 * start the program with LC_ALL=something on the command line.)
1117 p = getenv ("LC_ALL");
1119 return g_strdup (p);
1121 p = getenv ("LC_CTYPE");
1123 return g_strdup (p);
1125 p = getenv ("LANG");
1127 return g_strdup (p);
1129 return g_win32_getlocale ();
1131 return g_strdup (setlocale (LC_CTYPE, NULL));
1136 * gtk_get_default_language:
1138 * Returns the #PangoLanguage for the default language currently in
1139 * effect. (Note that this can change over the life of an
1140 * application.) The default language is derived from the current
1141 * locale. It determines, for example, whether GTK+ uses the
1142 * right-to-left or left-to-right text direction.
1144 * This function is equivalent to pango_language_get_default(). See
1145 * that function for details.
1147 * Return value: the default language as a #PangoLanguage, must not be
1151 gtk_get_default_language (void)
1153 return pango_language_get_default ();
1161 GtkInitFunction *init;
1164 gtk_main_loop_level++;
1166 loop = g_main_loop_new (NULL, TRUE);
1167 main_loops = g_slist_prepend (main_loops, loop);
1169 tmp_list = functions = init_functions;
1170 init_functions = NULL;
1174 init = tmp_list->data;
1175 tmp_list = tmp_list->next;
1177 (* init->function) (init->data);
1180 g_list_free (functions);
1182 if (g_main_loop_is_running (main_loops->data))
1184 GDK_THREADS_LEAVE ();
1185 g_main_loop_run (loop);
1186 GDK_THREADS_ENTER ();
1192 GList *reinvoke_list = NULL;
1193 GtkQuitFunction *quitf;
1195 while (quit_functions)
1197 quitf = quit_functions->data;
1199 tmp_list = quit_functions;
1200 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1201 g_list_free_1 (tmp_list);
1203 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1204 gtk_quit_invoke_function (quitf))
1206 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1210 gtk_quit_destroy (quitf);
1217 work = g_list_last (reinvoke_list);
1219 quit_functions->prev = work;
1220 work->next = quit_functions;
1221 quit_functions = work;
1227 main_loops = g_slist_remove (main_loops, loop);
1229 g_main_loop_unref (loop);
1231 gtk_main_loop_level--;
1233 if (gtk_main_loop_level == 0)
1235 /* Try storing all clipboard data we have */
1236 _gtk_clipboard_store_all ();
1238 /* Synchronize the recent manager singleton */
1239 _gtk_recent_manager_sync ();
1244 gtk_main_level (void)
1246 return gtk_main_loop_level;
1250 gtk_main_quit (void)
1252 g_return_if_fail (main_loops != NULL);
1254 g_main_loop_quit (main_loops->data);
1258 gtk_events_pending (void)
1262 GDK_THREADS_LEAVE ();
1263 result = g_main_context_pending (NULL);
1264 GDK_THREADS_ENTER ();
1270 gtk_main_iteration (void)
1272 GDK_THREADS_LEAVE ();
1273 g_main_context_iteration (NULL, TRUE);
1274 GDK_THREADS_ENTER ();
1277 return !g_main_loop_is_running (main_loops->data);
1283 gtk_main_iteration_do (gboolean blocking)
1285 GDK_THREADS_LEAVE ();
1286 g_main_context_iteration (NULL, blocking);
1287 GDK_THREADS_ENTER ();
1290 return !g_main_loop_is_running (main_loops->data);
1295 /* private libgtk to libgdk interfaces
1297 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1299 GdkWindow **grab_window,
1300 gboolean *owner_events);
1303 rewrite_events_translate (GdkWindow *old_window,
1304 GdkWindow *new_window,
1308 gint old_origin_x, old_origin_y;
1309 gint new_origin_x, new_origin_y;
1311 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1312 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1314 *x += old_origin_x - new_origin_x;
1315 *y += old_origin_y - new_origin_y;
1319 rewrite_event_for_window (GdkEvent *event,
1320 GdkWindow *new_window)
1322 event = gdk_event_copy (event);
1324 switch (event->type)
1327 rewrite_events_translate (event->any.window,
1329 &event->scroll.x, &event->scroll.y);
1331 case GDK_BUTTON_PRESS:
1332 case GDK_2BUTTON_PRESS:
1333 case GDK_3BUTTON_PRESS:
1334 case GDK_BUTTON_RELEASE:
1335 rewrite_events_translate (event->any.window,
1337 &event->button.x, &event->button.y);
1339 case GDK_MOTION_NOTIFY:
1340 rewrite_events_translate (event->any.window,
1342 &event->motion.x, &event->motion.y);
1345 case GDK_KEY_RELEASE:
1346 case GDK_PROXIMITY_IN:
1347 case GDK_PROXIMITY_OUT:
1354 g_object_unref (event->any.window);
1355 event->any.window = g_object_ref (new_window);
1360 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1361 * then what X11 does is deliver the event normally if it was going to this
1362 * client, otherwise, delivers it in terms of the grab window. This function
1363 * rewrites events to the effect that events going to the same window group
1364 * are delivered normally, otherwise, the event is delivered in terms of the
1368 rewrite_event_for_grabs (GdkEvent *event)
1370 GdkWindow *grab_window;
1371 GtkWidget *event_widget, *grab_widget;
1372 gpointer grab_widget_ptr;
1373 gboolean owner_events;
1374 GdkDisplay *display;
1377 switch (event->type)
1380 case GDK_BUTTON_PRESS:
1381 case GDK_2BUTTON_PRESS:
1382 case GDK_3BUTTON_PRESS:
1383 case GDK_BUTTON_RELEASE:
1384 case GDK_MOTION_NOTIFY:
1385 case GDK_PROXIMITY_IN:
1386 case GDK_PROXIMITY_OUT:
1388 case GDK_KEY_RELEASE:
1389 display = gdk_drawable_get_display (event->any.window);
1390 device = gdk_event_get_device (event);
1392 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1400 event_widget = gtk_get_event_widget (event);
1401 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1402 grab_widget = grab_widget_ptr;
1405 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1406 return rewrite_event_for_window (event, grab_window);
1412 gtk_main_do_event (GdkEvent *event)
1414 GtkWidget *event_widget;
1415 GtkWidget *grab_widget = NULL;
1416 GtkWindowGroup *window_group;
1417 GdkEvent *rewritten_event = NULL;
1421 if (event->type == GDK_SETTING)
1423 _gtk_settings_handle_event (&event->setting);
1427 if (event->type == GDK_OWNER_CHANGE)
1429 _gtk_clipboard_handle_event (&event->owner_change);
1433 /* Find the widget which got the event. We store the widget
1434 * in the user_data field of GdkWindow's.
1435 * Ignore the event if we don't have a widget for it, except
1436 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1437 * Though this happens rarely, bogus events can occour
1438 * for e.g. destroyed GdkWindows.
1440 event_widget = gtk_get_event_widget (event);
1443 /* To handle selection INCR transactions, we select
1444 * PropertyNotify events on the requestor window and create
1445 * a corresponding (fake) GdkWindow so that events get
1446 * here. There won't be a widget though, so we have to handle
1449 if (event->type == GDK_PROPERTY_NOTIFY)
1450 _gtk_selection_incr_event (event->any.window,
1456 /* If pointer or keyboard grabs are in effect, munge the events
1457 * so that each window group looks like a separate app.
1459 rewritten_event = rewrite_event_for_grabs (event);
1460 if (rewritten_event)
1462 event = rewritten_event;
1463 event_widget = gtk_get_event_widget (event);
1466 window_group = gtk_main_get_window_group (event_widget);
1467 device = gdk_event_get_device (event);
1469 /* If there is a grab in effect...
1471 if (window_group->grabs)
1473 grab_widget = window_group->grabs->data;
1475 /* If the grab widget is an ancestor of the event widget
1476 * then we send the event to the original event widget.
1477 * This is the key to implementing modality.
1479 if (gtk_widget_is_sensitive (event_widget) &&
1480 gtk_widget_is_ancestor (event_widget, grab_widget))
1481 grab_widget = event_widget;
1485 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1488 gtk_widget_get_sensitive (event_widget) &&
1489 gtk_widget_is_ancestor (event_widget, grab_widget))
1490 grab_widget = event_widget;
1494 grab_widget = event_widget;
1496 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1498 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1500 if (rewritten_event)
1501 gdk_event_free (rewritten_event);
1506 /* Push the event onto a stack of current events for
1507 * gtk_current_event_get().
1509 current_events = g_list_prepend (current_events, event);
1511 /* Not all events get sent to the grabbing widget.
1512 * The delete, destroy, expose, focus change and resize
1513 * events still get sent to the event widget because
1514 * 1) these events have no meaning for the grabbing widget
1515 * and 2) redirecting these events to the grabbing widget
1516 * could cause the display to be messed up.
1518 * Drag events are also not redirected, since it isn't
1519 * clear what the semantics of that would be.
1521 switch (event->type)
1527 g_object_ref (event_widget);
1528 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1529 !gtk_widget_event (event_widget, event))
1530 gtk_widget_destroy (event_widget);
1531 g_object_unref (event_widget);
1535 /* Unexpected GDK_DESTROY from the outside, ignore for
1536 * child windows, handle like a GDK_DELETE for toplevels
1538 if (!event_widget->parent)
1540 g_object_ref (event_widget);
1541 if (!gtk_widget_event (event_widget, event) &&
1542 gtk_widget_get_realized (event_widget))
1543 gtk_widget_destroy (event_widget);
1544 g_object_unref (event_widget);
1549 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1551 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1552 gtk_widget_send_expose (event_widget, event);
1553 gdk_window_end_paint (event->any.window);
1557 /* The app may paint with a previously allocated cairo_t,
1558 which will draw directly to the window. We can't catch cairo
1559 drap operatoins to automatically flush the window, thus we
1560 need to explicitly flush any outstanding moves or double
1562 gdk_window_flush (event->any.window);
1563 gtk_widget_send_expose (event_widget, event);
1567 case GDK_PROPERTY_NOTIFY:
1569 case GDK_FOCUS_CHANGE:
1573 case GDK_SELECTION_CLEAR:
1574 case GDK_SELECTION_REQUEST:
1575 case GDK_SELECTION_NOTIFY:
1576 case GDK_CLIENT_EVENT:
1577 case GDK_VISIBILITY_NOTIFY:
1578 case GDK_WINDOW_STATE:
1579 case GDK_GRAB_BROKEN:
1581 gtk_widget_event (event_widget, event);
1585 case GDK_BUTTON_PRESS:
1586 case GDK_2BUTTON_PRESS:
1587 case GDK_3BUTTON_PRESS:
1588 gtk_propagate_event (grab_widget, event);
1592 case GDK_KEY_RELEASE:
1595 if (gtk_invoke_key_snoopers (grab_widget, event))
1598 /* Catch alt press to enable auto-mnemonics;
1599 * menus are handled elsewhere
1601 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1602 !GTK_IS_MENU_SHELL (grab_widget))
1604 gboolean auto_mnemonics;
1606 g_object_get (gtk_widget_get_settings (grab_widget),
1607 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1611 gboolean mnemonics_visible;
1614 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1616 window = gtk_widget_get_toplevel (grab_widget);
1618 if (GTK_IS_WINDOW (window))
1619 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1622 /* else fall through */
1623 case GDK_MOTION_NOTIFY:
1624 case GDK_BUTTON_RELEASE:
1625 case GDK_PROXIMITY_IN:
1626 case GDK_PROXIMITY_OUT:
1627 gtk_propagate_event (grab_widget, event);
1630 case GDK_ENTER_NOTIFY:
1631 _gtk_widget_set_device_window (event_widget,
1632 gdk_event_get_device (event),
1634 if (gtk_widget_is_sensitive (grab_widget))
1635 gtk_widget_event (grab_widget, event);
1638 case GDK_LEAVE_NOTIFY:
1639 _gtk_widget_set_device_window (event_widget,
1640 gdk_event_get_device (event),
1642 if (gtk_widget_is_sensitive (grab_widget))
1643 gtk_widget_event (grab_widget, event);
1646 case GDK_DRAG_STATUS:
1647 case GDK_DROP_FINISHED:
1648 _gtk_drag_source_handle_event (event_widget, event);
1650 case GDK_DRAG_ENTER:
1651 case GDK_DRAG_LEAVE:
1652 case GDK_DRAG_MOTION:
1653 case GDK_DROP_START:
1654 _gtk_drag_dest_handle_event (event_widget, event);
1657 g_assert_not_reached ();
1661 if (event->type == GDK_ENTER_NOTIFY
1662 || event->type == GDK_LEAVE_NOTIFY
1663 || event->type == GDK_BUTTON_PRESS
1664 || event->type == GDK_2BUTTON_PRESS
1665 || event->type == GDK_3BUTTON_PRESS
1666 || event->type == GDK_KEY_PRESS
1667 || event->type == GDK_DRAG_ENTER
1668 || event->type == GDK_GRAB_BROKEN
1669 || event->type == GDK_MOTION_NOTIFY
1670 || event->type == GDK_SCROLL)
1672 _gtk_tooltip_handle_event (event);
1675 tmp_list = current_events;
1676 current_events = g_list_remove_link (current_events, tmp_list);
1677 g_list_free_1 (tmp_list);
1679 if (rewritten_event)
1680 gdk_event_free (rewritten_event);
1695 static GtkWindowGroup *
1696 gtk_main_get_window_group (GtkWidget *widget)
1698 GtkWidget *toplevel = NULL;
1701 toplevel = gtk_widget_get_toplevel (widget);
1703 if (GTK_IS_WINDOW (toplevel))
1704 return gtk_window_get_group (GTK_WINDOW (toplevel));
1706 return gtk_window_get_group (NULL);
1711 GtkWidget *old_grab_widget;
1712 GtkWidget *new_grab_widget;
1713 gboolean was_grabbed;
1714 gboolean is_grabbed;
1716 GList *notified_windows;
1721 synth_crossing_for_grab_notify (GtkWidget *from,
1723 GrabNotifyInfo *info,
1725 GdkCrossingMode mode)
1729 GdkDevice *device = devices->data;
1730 GdkWindow *from_window, *to_window;
1732 /* Do not propagate events more than once to
1733 * the same windows if non-multidevice aware.
1739 from_window = _gtk_widget_get_device_window (from, device);
1742 !gdk_window_get_support_multidevice (from_window) &&
1743 g_list_find (info->notified_windows, from_window))
1751 to_window = _gtk_widget_get_device_window (to, device);
1754 !gdk_window_get_support_multidevice (to_window) &&
1755 g_list_find (info->notified_windows, to_window))
1759 if (from_window || to_window)
1761 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1762 (to_window) ? to : NULL,
1766 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1769 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1772 devices = devices->next;
1777 gtk_grab_notify_foreach (GtkWidget *child,
1780 GrabNotifyInfo *info = data;
1781 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1784 was_grabbed = info->was_grabbed;
1785 is_grabbed = info->is_grabbed;
1787 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1788 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1790 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1791 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1793 g_object_ref (child);
1795 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1796 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1799 _gtk_widget_get_device_window (child, info->device))
1801 /* Device specified and is on widget */
1802 devices = g_list_prepend (NULL, info->device);
1805 devices = _gtk_widget_list_devices (child);
1809 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1810 if (!was_shadowed && devices &&
1811 gtk_widget_is_sensitive (child))
1812 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1814 GDK_CROSSING_GTK_GRAB);
1818 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1819 if (was_shadowed && devices &&
1820 gtk_widget_is_sensitive (child))
1821 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1823 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1824 GDK_CROSSING_GTK_UNGRAB);
1827 if (was_shadowed != is_shadowed)
1828 _gtk_widget_grab_notify (child, was_shadowed);
1830 g_object_unref (child);
1831 g_list_free (devices);
1833 info->was_grabbed = was_grabbed;
1834 info->is_grabbed = is_grabbed;
1838 gtk_grab_notify (GtkWindowGroup *group,
1840 GtkWidget *old_grab_widget,
1841 GtkWidget *new_grab_widget,
1845 GrabNotifyInfo info = { 0 };
1847 if (old_grab_widget == new_grab_widget)
1850 info.old_grab_widget = old_grab_widget;
1851 info.new_grab_widget = new_grab_widget;
1852 info.from_grab = from_grab;
1853 info.device = device;
1855 g_object_ref (group);
1857 toplevels = gtk_window_list_toplevels ();
1858 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1862 GtkWindow *toplevel = toplevels->data;
1863 toplevels = g_list_delete_link (toplevels, toplevels);
1865 info.was_grabbed = FALSE;
1866 info.is_grabbed = FALSE;
1868 if (group == gtk_window_get_group (toplevel))
1869 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1870 g_object_unref (toplevel);
1873 g_list_free (info.notified_windows);
1874 g_object_unref (group);
1878 gtk_grab_add (GtkWidget *widget)
1880 GtkWindowGroup *group;
1881 GtkWidget *old_grab_widget;
1883 g_return_if_fail (widget != NULL);
1885 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1887 _gtk_widget_set_has_grab (widget, TRUE);
1889 group = gtk_main_get_window_group (widget);
1892 old_grab_widget = (GtkWidget *)group->grabs->data;
1894 old_grab_widget = NULL;
1896 g_object_ref (widget);
1897 group->grabs = g_slist_prepend (group->grabs, widget);
1899 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1904 gtk_grab_get_current (void)
1906 GtkWindowGroup *group;
1908 group = gtk_main_get_window_group (NULL);
1911 return GTK_WIDGET (group->grabs->data);
1916 gtk_grab_remove (GtkWidget *widget)
1918 GtkWindowGroup *group;
1919 GtkWidget *new_grab_widget;
1921 g_return_if_fail (widget != NULL);
1923 if (gtk_widget_has_grab (widget))
1925 _gtk_widget_set_has_grab (widget, FALSE);
1927 group = gtk_main_get_window_group (widget);
1928 group->grabs = g_slist_remove (group->grabs, widget);
1931 new_grab_widget = (GtkWidget *)group->grabs->data;
1933 new_grab_widget = NULL;
1935 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
1937 g_object_unref (widget);
1942 * gtk_device_grab_add:
1943 * @widget: a #GtkWidget
1944 * @device: a #GtkDevice to grab on.
1945 * @block_others: %TRUE to prevent other devices to interact with @widget.
1947 * Adds a GTK+ grab on @device, so all the events on @device and its
1948 * associated pointer or keyboard (if any) are delivered to @widget.
1949 * If the @block_others parameter is %TRUE, any other devices will be
1950 * unable to interact with @widget during the grab.
1955 gtk_device_grab_add (GtkWidget *widget,
1957 gboolean block_others)
1959 GtkWindowGroup *group;
1960 GtkWidget *old_grab_widget;
1962 g_return_if_fail (GTK_IS_WIDGET (widget));
1963 g_return_if_fail (GDK_IS_DEVICE (device));
1965 group = gtk_main_get_window_group (widget);
1966 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
1968 if (old_grab_widget != widget)
1969 _gtk_window_group_add_device_grab (group, widget, device, block_others);
1971 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
1975 * gtk_device_grab_remove:
1976 * @widget: a #GtkWidget
1977 * @device: a #GdkDevice
1979 * Removes a device grab from the given widget. You have to pair calls
1980 * to gtk_device_grab_add() and gtk_device_grab_remove().
1985 gtk_device_grab_remove (GtkWidget *widget,
1988 GtkWindowGroup *group;
1989 GtkWidget *new_grab_widget;
1991 g_return_if_fail (GTK_IS_WIDGET (widget));
1992 g_return_if_fail (GDK_IS_DEVICE (device));
1994 group = gtk_main_get_window_group (widget);
1995 _gtk_window_group_remove_device_grab (group, widget, device);
1996 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
1998 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2002 gtk_init_add (GtkFunction function,
2005 GtkInitFunction *init;
2007 init = g_new (GtkInitFunction, 1);
2008 init->function = function;
2011 init_functions = g_list_prepend (init_functions, init);
2015 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2018 GtkKeySnooperData *data;
2019 static guint snooper_id = 1;
2021 g_return_val_if_fail (snooper != NULL, 0);
2023 data = g_new (GtkKeySnooperData, 1);
2024 data->func = snooper;
2025 data->func_data = func_data;
2026 data->id = snooper_id++;
2027 key_snoopers = g_slist_prepend (key_snoopers, data);
2033 gtk_key_snooper_remove (guint snooper_id)
2035 GtkKeySnooperData *data = NULL;
2038 slist = key_snoopers;
2042 if (data->id == snooper_id)
2045 slist = slist->next;
2050 key_snoopers = g_slist_remove (key_snoopers, data);
2056 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2060 gint return_val = FALSE;
2062 slist = key_snoopers;
2063 while (slist && !return_val)
2065 GtkKeySnooperData *data;
2068 slist = slist->next;
2069 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2076 gtk_quit_add_full (guint main_level,
2077 GtkFunction function,
2078 GtkCallbackMarshal marshal,
2080 GDestroyNotify destroy)
2082 static guint quit_id = 1;
2083 GtkQuitFunction *quitf;
2085 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2087 quitf = g_slice_new (GtkQuitFunction);
2089 quitf->id = quit_id++;
2090 quitf->main_level = main_level;
2091 quitf->function = function;
2092 quitf->marshal = marshal;
2094 quitf->destroy = destroy;
2096 quit_functions = g_list_prepend (quit_functions, quitf);
2102 gtk_quit_destroy (GtkQuitFunction *quitf)
2105 quitf->destroy (quitf->data);
2106 g_slice_free (GtkQuitFunction, quitf);
2110 gtk_quit_destructor (GtkObject **object_p)
2113 gtk_object_destroy (*object_p);
2120 gtk_quit_add_destroy (guint main_level,
2123 GtkObject **object_p;
2125 g_return_if_fail (main_level > 0);
2126 g_return_if_fail (GTK_IS_OBJECT (object));
2128 object_p = g_new (GtkObject*, 1);
2130 g_signal_connect (object,
2132 G_CALLBACK (gtk_widget_destroyed),
2134 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2138 gtk_quit_add (guint main_level,
2139 GtkFunction function,
2142 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2146 gtk_quit_remove (guint id)
2148 GtkQuitFunction *quitf;
2151 tmp_list = quit_functions;
2154 quitf = tmp_list->data;
2156 if (quitf->id == id)
2158 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2159 g_list_free (tmp_list);
2160 gtk_quit_destroy (quitf);
2165 tmp_list = tmp_list->next;
2170 gtk_quit_remove_by_data (gpointer data)
2172 GtkQuitFunction *quitf;
2175 tmp_list = quit_functions;
2178 quitf = tmp_list->data;
2180 if (quitf->data == data)
2182 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2183 g_list_free (tmp_list);
2184 gtk_quit_destroy (quitf);
2189 tmp_list = tmp_list->next;
2194 * gtk_get_current_event:
2196 * Obtains a copy of the event currently being processed by GTK+. For
2197 * example, if you get a "clicked" signal from #GtkButton, the current
2198 * event will be the #GdkEventButton that triggered the "clicked"
2199 * signal. The returned event must be freed with gdk_event_free().
2200 * If there is no current event, the function returns %NULL.
2202 * Return value: a copy of the current event, or %NULL if no current event.
2205 gtk_get_current_event (void)
2208 return gdk_event_copy (current_events->data);
2214 * gtk_get_current_event_time:
2216 * If there is a current event and it has a timestamp, return that
2217 * timestamp, otherwise return %GDK_CURRENT_TIME.
2219 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2222 gtk_get_current_event_time (void)
2225 return gdk_event_get_time (current_events->data);
2227 return GDK_CURRENT_TIME;
2231 * gtk_get_current_event_state:
2232 * @state: a location to store the state of the current event
2234 * If there is a current event and it has a state field, place
2235 * that state field in @state and return %TRUE, otherwise return
2238 * Return value: %TRUE if there was a current event and it had a state field
2241 gtk_get_current_event_state (GdkModifierType *state)
2243 g_return_val_if_fail (state != NULL, FALSE);
2246 return gdk_event_get_state (current_events->data, state);
2255 * gtk_get_current_event_device:
2257 * If there is a current event and it has a device, return that
2258 * device, otherwise return %NULL.
2260 * Returns: a #GdkDevice, or %NULL
2263 gtk_get_current_event_device (void)
2266 return gdk_event_get_device (current_events->data);
2272 * gtk_get_event_widget:
2273 * @event: a #GdkEvent
2275 * If @event is %NULL or the event was not associated with any widget,
2276 * returns %NULL, otherwise returns the widget that received the event
2279 * Return value: the widget that originally received @event, or %NULL
2282 gtk_get_event_widget (GdkEvent *event)
2285 gpointer widget_ptr;
2288 if (event && event->any.window &&
2289 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2291 gdk_window_get_user_data (event->any.window, &widget_ptr);
2292 widget = widget_ptr;
2299 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2301 if (!quitf->marshal)
2302 return quitf->function (quitf->data);
2306 gint ret_val = FALSE;
2308 args[0].name = NULL;
2309 args[0].type = G_TYPE_BOOLEAN;
2310 args[0].d.pointer_data = &ret_val;
2311 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2319 * gtk_propagate_event:
2320 * @widget: a #GtkWidget
2323 * Sends an event to a widget, propagating the event to parent widgets
2324 * if the event remains unhandled. Events received by GTK+ from GDK
2325 * normally begin in gtk_main_do_event(). Depending on the type of
2326 * event, existence of modal dialogs, grabs, etc., the event may be
2327 * propagated; if so, this function is used. gtk_propagate_event()
2328 * calls gtk_widget_event() on each widget it decides to send the
2329 * event to. So gtk_widget_event() is the lowest-level function; it
2330 * simply emits the "event" and possibly an event-specific signal on a
2331 * widget. gtk_propagate_event() is a bit higher-level, and
2332 * gtk_main_do_event() is the highest level.
2334 * All that said, you most likely don't want to use any of these
2335 * functions; synthesizing events is rarely needed. Consider asking on
2336 * the mailing list for better ways to achieve your goals. For
2337 * example, use gdk_window_invalidate_rect() or
2338 * gtk_widget_queue_draw() instead of making up expose events.
2342 gtk_propagate_event (GtkWidget *widget,
2347 g_return_if_fail (GTK_IS_WIDGET (widget));
2348 g_return_if_fail (event != NULL);
2350 handled_event = FALSE;
2352 g_object_ref (widget);
2354 if ((event->type == GDK_KEY_PRESS) ||
2355 (event->type == GDK_KEY_RELEASE))
2357 /* Only send key events within Window widgets to the Window
2358 * The Window widget will in turn pass the
2359 * key event on to the currently focused widget
2364 window = gtk_widget_get_toplevel (widget);
2365 if (GTK_IS_WINDOW (window))
2367 /* If there is a grab within the window, give the grab widget
2368 * a first crack at the key event
2370 if (widget != window && gtk_widget_has_grab (widget))
2371 handled_event = gtk_widget_event (widget, event);
2375 window = gtk_widget_get_toplevel (widget);
2376 if (GTK_IS_WINDOW (window))
2378 if (gtk_widget_is_sensitive (window))
2379 gtk_widget_event (window, event);
2383 handled_event = TRUE; /* don't send to widget */
2387 /* Other events get propagated up the widget tree
2388 * so that parents can see the button and motion
2389 * events of the children.
2397 /* Scroll events are special cased here because it
2398 * feels wrong when scrolling a GtkViewport, say,
2399 * to have children of the viewport eat the scroll
2402 if (!gtk_widget_is_sensitive (widget))
2403 handled_event = event->type != GDK_SCROLL;
2405 handled_event = gtk_widget_event (widget, event);
2407 tmp = widget->parent;
2408 g_object_unref (widget);
2412 if (!handled_event && widget)
2413 g_object_ref (widget);
2419 g_object_unref (widget);
2423 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2424 GValue *return_accu,
2425 const GValue *handler_return,
2428 gboolean continue_emission;
2429 gboolean signal_handled;
2431 signal_handled = g_value_get_boolean (handler_return);
2432 g_value_set_boolean (return_accu, signal_handled);
2433 continue_emission = !signal_handled;
2435 return continue_emission;
2438 #define __GTK_MAIN_C__
2439 #include "gtkaliasdef.c"