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 (gint *argc,
826 const gchar *parameter_string,
827 const GOptionEntry *entries,
828 const gchar *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 /* check whether there is a (device) grab in effect...
1472 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1474 if (!grab_widget && window_group->grabs)
1475 grab_widget = window_group->grabs->data;
1477 /* If the grab widget is an ancestor of the event widget
1478 * then we send the event to the original event widget.
1479 * This is the key to implementing modality.
1482 (gtk_widget_is_sensitive (event_widget) &&
1483 gtk_widget_is_ancestor (event_widget, grab_widget)))
1484 grab_widget = event_widget;
1486 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1488 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1490 if (rewritten_event)
1491 gdk_event_free (rewritten_event);
1496 /* Push the event onto a stack of current events for
1497 * gtk_current_event_get().
1499 current_events = g_list_prepend (current_events, event);
1501 /* Not all events get sent to the grabbing widget.
1502 * The delete, destroy, expose, focus change and resize
1503 * events still get sent to the event widget because
1504 * 1) these events have no meaning for the grabbing widget
1505 * and 2) redirecting these events to the grabbing widget
1506 * could cause the display to be messed up.
1508 * Drag events are also not redirected, since it isn't
1509 * clear what the semantics of that would be.
1511 switch (event->type)
1517 g_object_ref (event_widget);
1518 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1519 !gtk_widget_event (event_widget, event))
1520 gtk_widget_destroy (event_widget);
1521 g_object_unref (event_widget);
1525 /* Unexpected GDK_DESTROY from the outside, ignore for
1526 * child windows, handle like a GDK_DELETE for toplevels
1528 if (!event_widget->parent)
1530 g_object_ref (event_widget);
1531 if (!gtk_widget_event (event_widget, event) &&
1532 gtk_widget_get_realized (event_widget))
1533 gtk_widget_destroy (event_widget);
1534 g_object_unref (event_widget);
1539 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1541 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1542 gtk_widget_send_expose (event_widget, event);
1543 gdk_window_end_paint (event->any.window);
1547 /* The app may paint with a previously allocated cairo_t,
1548 which will draw directly to the window. We can't catch cairo
1549 drap operatoins to automatically flush the window, thus we
1550 need to explicitly flush any outstanding moves or double
1552 gdk_window_flush (event->any.window);
1553 gtk_widget_send_expose (event_widget, event);
1557 case GDK_PROPERTY_NOTIFY:
1559 case GDK_FOCUS_CHANGE:
1563 case GDK_SELECTION_CLEAR:
1564 case GDK_SELECTION_REQUEST:
1565 case GDK_SELECTION_NOTIFY:
1566 case GDK_CLIENT_EVENT:
1567 case GDK_VISIBILITY_NOTIFY:
1568 case GDK_WINDOW_STATE:
1569 case GDK_GRAB_BROKEN:
1571 gtk_widget_event (event_widget, event);
1575 case GDK_BUTTON_PRESS:
1576 case GDK_2BUTTON_PRESS:
1577 case GDK_3BUTTON_PRESS:
1578 gtk_propagate_event (grab_widget, event);
1582 case GDK_KEY_RELEASE:
1585 if (gtk_invoke_key_snoopers (grab_widget, event))
1588 /* Catch alt press to enable auto-mnemonics;
1589 * menus are handled elsewhere
1591 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1592 !GTK_IS_MENU_SHELL (grab_widget))
1594 gboolean auto_mnemonics;
1596 g_object_get (gtk_widget_get_settings (grab_widget),
1597 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1601 gboolean mnemonics_visible;
1604 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1606 window = gtk_widget_get_toplevel (grab_widget);
1608 if (GTK_IS_WINDOW (window))
1609 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1612 /* else fall through */
1613 case GDK_MOTION_NOTIFY:
1614 case GDK_BUTTON_RELEASE:
1615 case GDK_PROXIMITY_IN:
1616 case GDK_PROXIMITY_OUT:
1617 gtk_propagate_event (grab_widget, event);
1620 case GDK_ENTER_NOTIFY:
1621 _gtk_widget_set_device_window (event_widget,
1622 gdk_event_get_device (event),
1624 if (gtk_widget_is_sensitive (grab_widget))
1625 gtk_widget_event (grab_widget, event);
1628 case GDK_LEAVE_NOTIFY:
1629 _gtk_widget_set_device_window (event_widget,
1630 gdk_event_get_device (event),
1632 if (gtk_widget_is_sensitive (grab_widget))
1633 gtk_widget_event (grab_widget, event);
1636 case GDK_DRAG_STATUS:
1637 case GDK_DROP_FINISHED:
1638 _gtk_drag_source_handle_event (event_widget, event);
1640 case GDK_DRAG_ENTER:
1641 case GDK_DRAG_LEAVE:
1642 case GDK_DRAG_MOTION:
1643 case GDK_DROP_START:
1644 _gtk_drag_dest_handle_event (event_widget, event);
1647 g_assert_not_reached ();
1651 if (event->type == GDK_ENTER_NOTIFY
1652 || event->type == GDK_LEAVE_NOTIFY
1653 || event->type == GDK_BUTTON_PRESS
1654 || event->type == GDK_2BUTTON_PRESS
1655 || event->type == GDK_3BUTTON_PRESS
1656 || event->type == GDK_KEY_PRESS
1657 || event->type == GDK_DRAG_ENTER
1658 || event->type == GDK_GRAB_BROKEN
1659 || event->type == GDK_MOTION_NOTIFY
1660 || event->type == GDK_SCROLL)
1662 _gtk_tooltip_handle_event (event);
1665 tmp_list = current_events;
1666 current_events = g_list_remove_link (current_events, tmp_list);
1667 g_list_free_1 (tmp_list);
1669 if (rewritten_event)
1670 gdk_event_free (rewritten_event);
1685 static GtkWindowGroup *
1686 gtk_main_get_window_group (GtkWidget *widget)
1688 GtkWidget *toplevel = NULL;
1691 toplevel = gtk_widget_get_toplevel (widget);
1693 if (GTK_IS_WINDOW (toplevel))
1694 return gtk_window_get_group (GTK_WINDOW (toplevel));
1696 return gtk_window_get_group (NULL);
1701 GtkWidget *old_grab_widget;
1702 GtkWidget *new_grab_widget;
1703 gboolean was_grabbed;
1704 gboolean is_grabbed;
1706 GList *notified_windows;
1711 synth_crossing_for_grab_notify (GtkWidget *from,
1713 GrabNotifyInfo *info,
1715 GdkCrossingMode mode)
1719 GdkDevice *device = devices->data;
1720 GdkWindow *from_window, *to_window;
1722 /* Do not propagate events more than once to
1723 * the same windows if non-multidevice aware.
1729 from_window = _gtk_widget_get_device_window (from, device);
1732 !gdk_window_get_support_multidevice (from_window) &&
1733 g_list_find (info->notified_windows, from_window))
1741 to_window = _gtk_widget_get_device_window (to, device);
1744 !gdk_window_get_support_multidevice (to_window) &&
1745 g_list_find (info->notified_windows, to_window))
1749 if (from_window || to_window)
1751 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1752 (to_window) ? to : NULL,
1756 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1759 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1762 devices = devices->next;
1767 gtk_grab_notify_foreach (GtkWidget *child,
1770 GrabNotifyInfo *info = data;
1771 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1774 was_grabbed = info->was_grabbed;
1775 is_grabbed = info->is_grabbed;
1777 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1778 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1780 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1781 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1783 g_object_ref (child);
1785 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1786 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1789 _gtk_widget_get_device_window (child, info->device))
1791 /* Device specified and is on widget */
1792 devices = g_list_prepend (NULL, info->device);
1795 devices = _gtk_widget_list_devices (child);
1799 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1800 if (!was_shadowed && devices &&
1801 gtk_widget_is_sensitive (child))
1802 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1804 GDK_CROSSING_GTK_GRAB);
1808 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1809 if (was_shadowed && devices &&
1810 gtk_widget_is_sensitive (child))
1811 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1813 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1814 GDK_CROSSING_GTK_UNGRAB);
1817 if (was_shadowed != is_shadowed)
1818 _gtk_widget_grab_notify (child, was_shadowed);
1820 g_object_unref (child);
1821 g_list_free (devices);
1823 info->was_grabbed = was_grabbed;
1824 info->is_grabbed = is_grabbed;
1828 gtk_grab_notify (GtkWindowGroup *group,
1830 GtkWidget *old_grab_widget,
1831 GtkWidget *new_grab_widget,
1835 GrabNotifyInfo info = { 0 };
1837 if (old_grab_widget == new_grab_widget)
1840 info.old_grab_widget = old_grab_widget;
1841 info.new_grab_widget = new_grab_widget;
1842 info.from_grab = from_grab;
1843 info.device = device;
1845 g_object_ref (group);
1847 toplevels = gtk_window_list_toplevels ();
1848 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1852 GtkWindow *toplevel = toplevels->data;
1853 toplevels = g_list_delete_link (toplevels, toplevels);
1855 info.was_grabbed = FALSE;
1856 info.is_grabbed = FALSE;
1858 if (group == gtk_window_get_group (toplevel))
1859 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1860 g_object_unref (toplevel);
1863 g_list_free (info.notified_windows);
1864 g_object_unref (group);
1868 gtk_grab_add (GtkWidget *widget)
1870 GtkWindowGroup *group;
1871 GtkWidget *old_grab_widget;
1873 g_return_if_fail (widget != NULL);
1875 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1877 _gtk_widget_set_has_grab (widget, TRUE);
1879 group = gtk_main_get_window_group (widget);
1882 old_grab_widget = (GtkWidget *)group->grabs->data;
1884 old_grab_widget = NULL;
1886 g_object_ref (widget);
1887 group->grabs = g_slist_prepend (group->grabs, widget);
1889 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1894 gtk_grab_get_current (void)
1896 GtkWindowGroup *group;
1898 group = gtk_main_get_window_group (NULL);
1901 return GTK_WIDGET (group->grabs->data);
1906 gtk_grab_remove (GtkWidget *widget)
1908 GtkWindowGroup *group;
1909 GtkWidget *new_grab_widget;
1911 g_return_if_fail (widget != NULL);
1913 if (gtk_widget_has_grab (widget))
1915 _gtk_widget_set_has_grab (widget, FALSE);
1917 group = gtk_main_get_window_group (widget);
1918 group->grabs = g_slist_remove (group->grabs, widget);
1921 new_grab_widget = (GtkWidget *)group->grabs->data;
1923 new_grab_widget = NULL;
1925 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
1927 g_object_unref (widget);
1932 * gtk_device_grab_add:
1933 * @widget: a #GtkWidget
1934 * @device: a #GtkDevice to grab on.
1935 * @block_others: %TRUE to prevent other devices to interact with @widget.
1937 * Adds a GTK+ grab on @device, so all the events on @device and its
1938 * associated pointer or keyboard (if any) are delivered to @widget.
1939 * If the @block_others parameter is %TRUE, any other devices will be
1940 * unable to interact with @widget during the grab.
1945 gtk_device_grab_add (GtkWidget *widget,
1947 gboolean block_others)
1949 GtkWindowGroup *group;
1950 GtkWidget *old_grab_widget;
1952 g_return_if_fail (GTK_IS_WIDGET (widget));
1953 g_return_if_fail (GDK_IS_DEVICE (device));
1955 group = gtk_main_get_window_group (widget);
1956 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
1958 if (old_grab_widget != widget)
1959 _gtk_window_group_add_device_grab (group, widget, device, block_others);
1961 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
1965 * gtk_device_grab_remove:
1966 * @widget: a #GtkWidget
1967 * @device: a #GdkDevice
1969 * Removes a device grab from the given widget. You have to pair calls
1970 * to gtk_device_grab_add() and gtk_device_grab_remove().
1975 gtk_device_grab_remove (GtkWidget *widget,
1978 GtkWindowGroup *group;
1979 GtkWidget *new_grab_widget;
1981 g_return_if_fail (GTK_IS_WIDGET (widget));
1982 g_return_if_fail (GDK_IS_DEVICE (device));
1984 group = gtk_main_get_window_group (widget);
1985 _gtk_window_group_remove_device_grab (group, widget, device);
1986 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
1988 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
1992 gtk_init_add (GtkFunction function,
1995 GtkInitFunction *init;
1997 init = g_new (GtkInitFunction, 1);
1998 init->function = function;
2001 init_functions = g_list_prepend (init_functions, init);
2005 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2008 GtkKeySnooperData *data;
2009 static guint snooper_id = 1;
2011 g_return_val_if_fail (snooper != NULL, 0);
2013 data = g_new (GtkKeySnooperData, 1);
2014 data->func = snooper;
2015 data->func_data = func_data;
2016 data->id = snooper_id++;
2017 key_snoopers = g_slist_prepend (key_snoopers, data);
2023 gtk_key_snooper_remove (guint snooper_id)
2025 GtkKeySnooperData *data = NULL;
2028 slist = key_snoopers;
2032 if (data->id == snooper_id)
2035 slist = slist->next;
2040 key_snoopers = g_slist_remove (key_snoopers, data);
2046 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2050 gint return_val = FALSE;
2052 slist = key_snoopers;
2053 while (slist && !return_val)
2055 GtkKeySnooperData *data;
2058 slist = slist->next;
2059 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2066 gtk_quit_add_full (guint main_level,
2067 GtkFunction function,
2068 GtkCallbackMarshal marshal,
2070 GDestroyNotify destroy)
2072 static guint quit_id = 1;
2073 GtkQuitFunction *quitf;
2075 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2077 quitf = g_slice_new (GtkQuitFunction);
2079 quitf->id = quit_id++;
2080 quitf->main_level = main_level;
2081 quitf->function = function;
2082 quitf->marshal = marshal;
2084 quitf->destroy = destroy;
2086 quit_functions = g_list_prepend (quit_functions, quitf);
2092 gtk_quit_destroy (GtkQuitFunction *quitf)
2095 quitf->destroy (quitf->data);
2096 g_slice_free (GtkQuitFunction, quitf);
2100 gtk_quit_destructor (GtkObject **object_p)
2103 gtk_object_destroy (*object_p);
2110 gtk_quit_add_destroy (guint main_level,
2113 GtkObject **object_p;
2115 g_return_if_fail (main_level > 0);
2116 g_return_if_fail (GTK_IS_OBJECT (object));
2118 object_p = g_new (GtkObject*, 1);
2120 g_signal_connect (object,
2122 G_CALLBACK (gtk_widget_destroyed),
2124 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2128 gtk_quit_add (guint main_level,
2129 GtkFunction function,
2132 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2136 gtk_quit_remove (guint id)
2138 GtkQuitFunction *quitf;
2141 tmp_list = quit_functions;
2144 quitf = tmp_list->data;
2146 if (quitf->id == id)
2148 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2149 g_list_free (tmp_list);
2150 gtk_quit_destroy (quitf);
2155 tmp_list = tmp_list->next;
2160 gtk_quit_remove_by_data (gpointer data)
2162 GtkQuitFunction *quitf;
2165 tmp_list = quit_functions;
2168 quitf = tmp_list->data;
2170 if (quitf->data == data)
2172 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2173 g_list_free (tmp_list);
2174 gtk_quit_destroy (quitf);
2179 tmp_list = tmp_list->next;
2184 * gtk_get_current_event:
2186 * Obtains a copy of the event currently being processed by GTK+. For
2187 * example, if you get a "clicked" signal from #GtkButton, the current
2188 * event will be the #GdkEventButton that triggered the "clicked"
2189 * signal. The returned event must be freed with gdk_event_free().
2190 * If there is no current event, the function returns %NULL.
2192 * Return value: a copy of the current event, or %NULL if no current event.
2195 gtk_get_current_event (void)
2198 return gdk_event_copy (current_events->data);
2204 * gtk_get_current_event_time:
2206 * If there is a current event and it has a timestamp, return that
2207 * timestamp, otherwise return %GDK_CURRENT_TIME.
2209 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2212 gtk_get_current_event_time (void)
2215 return gdk_event_get_time (current_events->data);
2217 return GDK_CURRENT_TIME;
2221 * gtk_get_current_event_state:
2222 * @state: a location to store the state of the current event
2224 * If there is a current event and it has a state field, place
2225 * that state field in @state and return %TRUE, otherwise return
2228 * Return value: %TRUE if there was a current event and it had a state field
2231 gtk_get_current_event_state (GdkModifierType *state)
2233 g_return_val_if_fail (state != NULL, FALSE);
2236 return gdk_event_get_state (current_events->data, state);
2245 * gtk_get_current_event_device:
2247 * If there is a current event and it has a device, return that
2248 * device, otherwise return %NULL.
2250 * Returns: a #GdkDevice, or %NULL
2253 gtk_get_current_event_device (void)
2256 return gdk_event_get_device (current_events->data);
2262 * gtk_get_event_widget:
2263 * @event: a #GdkEvent
2265 * If @event is %NULL or the event was not associated with any widget,
2266 * returns %NULL, otherwise returns the widget that received the event
2269 * Return value: the widget that originally received @event, or %NULL
2272 gtk_get_event_widget (GdkEvent *event)
2275 gpointer widget_ptr;
2278 if (event && event->any.window &&
2279 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2281 gdk_window_get_user_data (event->any.window, &widget_ptr);
2282 widget = widget_ptr;
2289 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2291 if (!quitf->marshal)
2292 return quitf->function (quitf->data);
2296 gint ret_val = FALSE;
2298 args[0].name = NULL;
2299 args[0].type = G_TYPE_BOOLEAN;
2300 args[0].d.pointer_data = &ret_val;
2301 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2309 * gtk_propagate_event:
2310 * @widget: a #GtkWidget
2313 * Sends an event to a widget, propagating the event to parent widgets
2314 * if the event remains unhandled. Events received by GTK+ from GDK
2315 * normally begin in gtk_main_do_event(). Depending on the type of
2316 * event, existence of modal dialogs, grabs, etc., the event may be
2317 * propagated; if so, this function is used. gtk_propagate_event()
2318 * calls gtk_widget_event() on each widget it decides to send the
2319 * event to. So gtk_widget_event() is the lowest-level function; it
2320 * simply emits the "event" and possibly an event-specific signal on a
2321 * widget. gtk_propagate_event() is a bit higher-level, and
2322 * gtk_main_do_event() is the highest level.
2324 * All that said, you most likely don't want to use any of these
2325 * functions; synthesizing events is rarely needed. Consider asking on
2326 * the mailing list for better ways to achieve your goals. For
2327 * example, use gdk_window_invalidate_rect() or
2328 * gtk_widget_queue_draw() instead of making up expose events.
2332 gtk_propagate_event (GtkWidget *widget,
2337 g_return_if_fail (GTK_IS_WIDGET (widget));
2338 g_return_if_fail (event != NULL);
2340 handled_event = FALSE;
2342 g_object_ref (widget);
2344 if ((event->type == GDK_KEY_PRESS) ||
2345 (event->type == GDK_KEY_RELEASE))
2347 /* Only send key events within Window widgets to the Window
2348 * The Window widget will in turn pass the
2349 * key event on to the currently focused widget
2354 window = gtk_widget_get_toplevel (widget);
2355 if (GTK_IS_WINDOW (window))
2357 /* If there is a grab within the window, give the grab widget
2358 * a first crack at the key event
2360 if (widget != window && gtk_widget_has_grab (widget))
2361 handled_event = gtk_widget_event (widget, event);
2365 window = gtk_widget_get_toplevel (widget);
2366 if (GTK_IS_WINDOW (window))
2368 if (gtk_widget_is_sensitive (window))
2369 gtk_widget_event (window, event);
2373 handled_event = TRUE; /* don't send to widget */
2377 /* Other events get propagated up the widget tree
2378 * so that parents can see the button and motion
2379 * events of the children.
2387 /* Scroll events are special cased here because it
2388 * feels wrong when scrolling a GtkViewport, say,
2389 * to have children of the viewport eat the scroll
2392 if (!gtk_widget_is_sensitive (widget))
2393 handled_event = event->type != GDK_SCROLL;
2395 handled_event = gtk_widget_event (widget, event);
2397 tmp = widget->parent;
2398 g_object_unref (widget);
2402 if (!handled_event && widget)
2403 g_object_ref (widget);
2409 g_object_unref (widget);
2413 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2414 GValue *return_accu,
2415 const GValue *handler_return,
2418 gboolean continue_emission;
2419 gboolean signal_handled;
2421 signal_handled = g_value_get_boolean (handler_return);
2422 g_value_set_boolean (return_accu, signal_handled);
2423 continue_emission = !signal_handled;
2425 return continue_emission;
2428 #define __GTK_MAIN_C__
2429 #include "gtkaliasdef.c"