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 {"size-request", GTK_DEBUG_SIZE_REQUEST},
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 check_mixed_deps (void)
616 module = g_module_open (NULL, 0);
618 if (g_module_symbol (module, "gtk_progress_get_type", &func))
620 g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
623 g_module_close (module);
627 do_pre_parse_initialization (int *argc,
630 const gchar *env_string;
635 pre_initialized = TRUE;
639 gdk_pre_parse_libgtk_only ();
640 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
642 #ifdef G_ENABLE_DEBUG
643 env_string = g_getenv ("GTK_DEBUG");
644 if (env_string != NULL)
646 gtk_debug_flags = g_parse_debug_string (env_string,
648 G_N_ELEMENTS (gtk_debug_keys));
651 #endif /* G_ENABLE_DEBUG */
653 env_string = g_getenv ("GTK_MODULES");
655 gtk_modules_string = g_string_new (env_string);
659 gettext_initialization (void)
661 setlocale_initialization ();
664 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
665 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
666 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
667 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
668 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
674 do_post_parse_initialization (int *argc,
680 gettext_initialization ();
683 signal (SIGPIPE, SIG_IGN);
686 if (g_fatal_warnings)
688 GLogLevelFlags fatal_mask;
690 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
691 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
692 g_log_set_always_fatal (fatal_mask);
695 if (gtk_debug_flags & GTK_DEBUG_UPDATES)
696 gdk_window_set_debug_updates (TRUE);
699 /* Translate to default:RTL if you want your widgets
700 * to be RTL, otherwise translate to default:LTR.
701 * Do *not* translate it to "predefinito:LTR", if it
702 * it isn't default:LTR or default:RTL it will not work
704 char *e = _("default:LTR");
705 if (strcmp (e, "default:RTL")==0)
706 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
707 else if (strcmp (e, "default:LTR"))
708 g_warning ("Whoever translated default:LTR did so wrongly.\n");
711 /* do what the call to gtk_type_init() used to do */
714 _gtk_accel_map_init ();
717 /* Set the 'initialized' flag.
719 gtk_initialized = TRUE;
721 /* load gtk modules */
722 if (gtk_modules_string)
724 _gtk_modules_init (argc, argv, gtk_modules_string->str);
725 g_string_free (gtk_modules_string, TRUE);
729 _gtk_modules_init (argc, argv, NULL);
736 gboolean open_default_display;
740 pre_parse_hook (GOptionContext *context,
745 do_pre_parse_initialization (NULL, NULL);
751 post_parse_hook (GOptionContext *context,
756 OptionGroupInfo *info = data;
759 do_post_parse_initialization (NULL, NULL);
761 if (info->open_default_display)
763 if (gdk_display_open_default_libgtk_only () == NULL)
765 const char *display_name = gdk_get_display_arg_name ();
768 G_OPTION_ERROR_FAILED,
769 _("Cannot open display: %s"),
770 display_name ? display_name : "" );
781 * gtk_get_option_group:
782 * @open_default_display: whether to open the default display
783 * when parsing the commandline arguments
785 * Returns a #GOptionGroup for the commandline arguments recognized
786 * by GTK+ and GDK. You should add this group to your #GOptionContext
787 * with g_option_context_add_group(), if you are using
788 * g_option_context_parse() to parse your commandline arguments.
790 * Returns: a #GOptionGroup for the commandline arguments recognized
796 gtk_get_option_group (gboolean open_default_display)
799 OptionGroupInfo *info;
801 gettext_initialization ();
803 info = g_new0 (OptionGroupInfo, 1);
804 info->open_default_display = open_default_display;
806 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
807 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
809 gdk_add_option_entries_libgtk_only (group);
810 g_option_group_add_entries (group, gtk_args);
811 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
817 * gtk_init_with_args:
818 * @argc: a pointer to the number of command line arguments.
819 * @argv: a pointer to the array of command line arguments.
820 * @parameter_string: a string which is displayed in
821 * the first line of <option>--help</option> output, after
822 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
823 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
824 * describing the options of your program
825 * @translation_domain: a translation domain to use for translating
826 * the <option>--help</option> output for the options in @entries
827 * with gettext(), or %NULL
828 * @error: a return location for errors
830 * This function does the same work as gtk_init_check().
831 * Additionally, it allows you to add your own commandline options,
832 * and it automatically generates nicely formatted
833 * <option>--help</option> output. Note that your program will
834 * be terminated after writing out the help output.
836 * Returns: %TRUE if the GUI has been successfully initialized,
842 gtk_init_with_args (gint *argc,
844 const gchar *parameter_string,
845 const GOptionEntry *entries,
846 const gchar *translation_domain,
849 GOptionContext *context;
850 GOptionGroup *gtk_group;
854 return gdk_display_open_default_libgtk_only () != NULL;
856 gettext_initialization ();
858 if (!check_setugid ())
861 gtk_group = gtk_get_option_group (TRUE);
863 context = g_option_context_new (parameter_string);
864 g_option_context_add_group (context, gtk_group);
867 g_option_context_add_main_entries (context, entries, translation_domain);
868 retval = g_option_context_parse (context, argc, argv, error);
870 g_option_context_free (context);
878 * @argc: (inout): a pointer to the number of command line arguments.
879 * @argv: (array) (inout): a pointer to the array of command line arguments.
881 * Parses command line arguments, and initializes global
882 * attributes of GTK+, but does not actually open a connection
883 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
885 * Any arguments used by GTK+ or GDK are removed from the array and
886 * @argc and @argv are updated accordingly.
888 * You shouldn't call this function explicitely if you are using
889 * gtk_init(), or gtk_init_check().
891 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
894 gtk_parse_args (int *argc,
897 GOptionContext *option_context;
898 GOptionGroup *gtk_group;
899 GError *error = NULL;
904 gettext_initialization ();
906 if (!check_setugid ())
909 option_context = g_option_context_new (NULL);
910 g_option_context_set_ignore_unknown_options (option_context, TRUE);
911 g_option_context_set_help_enabled (option_context, FALSE);
912 gtk_group = gtk_get_option_group (FALSE);
913 g_option_context_set_main_group (option_context, gtk_group);
914 if (!g_option_context_parse (option_context, argc, argv, &error))
916 g_warning ("%s", error->message);
917 g_error_free (error);
920 g_option_context_free (option_context);
925 #ifdef G_PLATFORM_WIN32
926 #undef gtk_init_check
931 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
932 * main() function. Changed if any arguments were handled.
933 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
934 * Any parameters understood by gtk_init() are stripped before return.
936 * This function does the same work as gtk_init() with only
937 * a single change: It does not terminate the program if the GUI can't be
938 * initialized. Instead it returns %FALSE on failure.
940 * This way the application can fall back to some other means of communication
941 * with the user - for example a curses or command line interface.
943 * Return value: %TRUE if the GUI has been successfully initialized,
947 gtk_init_check (int *argc,
950 if (!gtk_parse_args (argc, argv))
953 return gdk_display_open_default_libgtk_only () != NULL;
956 #ifdef G_PLATFORM_WIN32
962 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
963 * main() function. Changed if any arguments were handled.
964 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
965 * Any parameters understood by gtk_init() are stripped before return.
967 * Call this function before using any other GTK+ functions in your GUI
968 * applications. It will initialize everything needed to operate the
969 * toolkit and parses some standard command line options. @argc and
970 * @argv are adjusted accordingly so your own code will
971 * never see those standard arguments.
973 * Note that there are some alternative ways to initialize GTK+:
974 * if you are calling gtk_parse_args(), gtk_init_check(),
975 * gtk_init_with_args() or g_option_context_parse() with
976 * the option group returned by gtk_get_option_group(), you
977 * <emphasis>don't</emphasis> have to call gtk_init().
980 * This function will terminate your program if it was unable to initialize
981 * the GUI for some reason. If you want your program to fall back to a
982 * textual interface you want to call gtk_init_check() instead.
986 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
987 * during initialization, to ignore SIGPIPE signals, since these are
988 * almost never wanted in graphical applications. If you do need to
989 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
990 * but notice that other libraries (e.g. libdbus or gvfs) might do
995 gtk_init (int *argc, char ***argv)
997 if (!gtk_init_check (argc, argv))
999 const char *display_name_arg = gdk_get_display_arg_name ();
1000 if (display_name_arg == NULL)
1001 display_name_arg = getenv("DISPLAY");
1002 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1007 #ifdef G_PLATFORM_WIN32
1010 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1012 if (sizeof_GtkWindow != sizeof (GtkWindow))
1013 g_error ("Incompatible build!\n"
1014 "The code using GTK+ thinks GtkWindow 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 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1022 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1023 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1024 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1025 * -fnative-struct still matters. GtkBox is one such.
1028 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1030 if (sizeof_GtkBox != sizeof (GtkBox))
1031 g_error ("Incompatible build!\n"
1032 "The code using GTK+ thinks GtkBox is of different\n"
1033 "size than it actually is in this build of GTK+.\n"
1034 "On Windows, this probably means that you have compiled\n"
1035 "your code with gcc without the -mms-bitfields switch,\n"
1036 "or that you are using an unsupported compiler.");
1039 /* These two functions might get more checks added later, thus pass
1040 * in the number of extra args.
1043 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1045 check_sizeof_GtkWindow (sizeof_GtkWindow);
1046 if (num_checks >= 2)
1047 check_sizeof_GtkBox (sizeof_GtkBox);
1048 gtk_init (argc, argv);
1052 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1054 check_sizeof_GtkWindow (sizeof_GtkWindow);
1055 if (num_checks >= 2)
1056 check_sizeof_GtkBox (sizeof_GtkBox);
1057 return gtk_init_check (argc, argv);
1065 * Initializes internationalization support for GTK+. gtk_init()
1066 * automatically does this, so there is typically no point
1067 * in calling this function.
1069 * If you are calling this function because you changed the locale
1070 * after GTK+ is was initialized, then calling this function
1071 * may help a bit. (Note, however, that changing the locale
1072 * after GTK+ is initialized may produce inconsistent results and
1073 * is not really supported.)
1075 * In detail - sets the current locale according to the
1076 * program environment. This is the same as calling the C library function
1077 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1078 * locale specific setup of the windowing system used by GDK.
1080 * Returns: a string corresponding to the locale set, typically in the
1081 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1082 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1083 * result of the setlocale(); it is also used on other machines, such as
1084 * Windows, where the C library returns a different result. The string is
1085 * owned by GTK+ and should not be modified or freed.
1088 gtk_set_locale (void)
1090 return gdk_set_locale ();
1094 * _gtk_get_lc_ctype:
1096 * Return the Unix-style locale string for the language currently in
1097 * effect. On Unix systems, this is the return value from
1098 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1099 * affect this through the environment variables LC_ALL, LC_CTYPE or
1100 * LANG (checked in that order). The locale strings typically is in
1101 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1102 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1103 * Swedish as written in Finland or pt_BR for Portuguese as written in
1106 * On Windows, the C library doesn't use any such environment
1107 * variables, and setting them won't affect the behaviour of functions
1108 * like ctime(). The user sets the locale through the Regional Options
1109 * in the Control Panel. The C library (in the setlocale() function)
1110 * does not use country and language codes, but country and language
1111 * names spelled out in English.
1112 * However, this function does check the above environment
1113 * variables, and does return a Unix-style locale string based on
1114 * either said environment variables or the thread's current locale.
1116 * Return value: a dynamically allocated string, free with g_free().
1120 _gtk_get_lc_ctype (void)
1123 /* Somebody might try to set the locale for this process using the
1124 * LANG or LC_ environment variables. The Microsoft C library
1125 * doesn't know anything about them. You set the locale in the
1126 * Control Panel. Setting these env vars won't have any affect on
1127 * locale-dependent C library functions like ctime(). But just for
1128 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1129 * it easier to test GTK and Pango in various default languages, you
1130 * don't have to clickety-click in the Control Panel, you can simply
1131 * start the program with LC_ALL=something on the command line.)
1135 p = getenv ("LC_ALL");
1137 return g_strdup (p);
1139 p = getenv ("LC_CTYPE");
1141 return g_strdup (p);
1143 p = getenv ("LANG");
1145 return g_strdup (p);
1147 return g_win32_getlocale ();
1149 return g_strdup (setlocale (LC_CTYPE, NULL));
1154 * gtk_get_default_language:
1156 * Returns the #PangoLanguage for the default language currently in
1157 * effect. (Note that this can change over the life of an
1158 * application.) The default language is derived from the current
1159 * locale. It determines, for example, whether GTK+ uses the
1160 * right-to-left or left-to-right text direction.
1162 * This function is equivalent to pango_language_get_default(). See
1163 * that function for details.
1165 * Return value: the default language as a #PangoLanguage, must not be
1169 gtk_get_default_language (void)
1171 return pango_language_get_default ();
1179 GtkInitFunction *init;
1182 gtk_main_loop_level++;
1184 loop = g_main_loop_new (NULL, TRUE);
1185 main_loops = g_slist_prepend (main_loops, loop);
1187 tmp_list = functions = init_functions;
1188 init_functions = NULL;
1192 init = tmp_list->data;
1193 tmp_list = tmp_list->next;
1195 (* init->function) (init->data);
1198 g_list_free (functions);
1200 if (g_main_loop_is_running (main_loops->data))
1202 GDK_THREADS_LEAVE ();
1203 g_main_loop_run (loop);
1204 GDK_THREADS_ENTER ();
1210 GList *reinvoke_list = NULL;
1211 GtkQuitFunction *quitf;
1213 while (quit_functions)
1215 quitf = quit_functions->data;
1217 tmp_list = quit_functions;
1218 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1219 g_list_free_1 (tmp_list);
1221 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1222 gtk_quit_invoke_function (quitf))
1224 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1228 gtk_quit_destroy (quitf);
1235 work = g_list_last (reinvoke_list);
1237 quit_functions->prev = work;
1238 work->next = quit_functions;
1239 quit_functions = work;
1245 main_loops = g_slist_remove (main_loops, loop);
1247 g_main_loop_unref (loop);
1249 gtk_main_loop_level--;
1251 if (gtk_main_loop_level == 0)
1253 /* Try storing all clipboard data we have */
1254 _gtk_clipboard_store_all ();
1256 /* Synchronize the recent manager singleton */
1257 _gtk_recent_manager_sync ();
1262 gtk_main_level (void)
1264 return gtk_main_loop_level;
1268 gtk_main_quit (void)
1270 g_return_if_fail (main_loops != NULL);
1272 g_main_loop_quit (main_loops->data);
1276 gtk_events_pending (void)
1280 GDK_THREADS_LEAVE ();
1281 result = g_main_context_pending (NULL);
1282 GDK_THREADS_ENTER ();
1288 gtk_main_iteration (void)
1290 GDK_THREADS_LEAVE ();
1291 g_main_context_iteration (NULL, TRUE);
1292 GDK_THREADS_ENTER ();
1295 return !g_main_loop_is_running (main_loops->data);
1301 gtk_main_iteration_do (gboolean blocking)
1303 GDK_THREADS_LEAVE ();
1304 g_main_context_iteration (NULL, blocking);
1305 GDK_THREADS_ENTER ();
1308 return !g_main_loop_is_running (main_loops->data);
1313 /* private libgtk to libgdk interfaces
1315 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1317 GdkWindow **grab_window,
1318 gboolean *owner_events);
1321 rewrite_events_translate (GdkWindow *old_window,
1322 GdkWindow *new_window,
1326 gint old_origin_x, old_origin_y;
1327 gint new_origin_x, new_origin_y;
1329 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1330 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1332 *x += old_origin_x - new_origin_x;
1333 *y += old_origin_y - new_origin_y;
1337 rewrite_event_for_window (GdkEvent *event,
1338 GdkWindow *new_window)
1340 event = gdk_event_copy (event);
1342 switch (event->type)
1345 rewrite_events_translate (event->any.window,
1347 &event->scroll.x, &event->scroll.y);
1349 case GDK_BUTTON_PRESS:
1350 case GDK_2BUTTON_PRESS:
1351 case GDK_3BUTTON_PRESS:
1352 case GDK_BUTTON_RELEASE:
1353 rewrite_events_translate (event->any.window,
1355 &event->button.x, &event->button.y);
1357 case GDK_MOTION_NOTIFY:
1358 rewrite_events_translate (event->any.window,
1360 &event->motion.x, &event->motion.y);
1363 case GDK_KEY_RELEASE:
1364 case GDK_PROXIMITY_IN:
1365 case GDK_PROXIMITY_OUT:
1372 g_object_unref (event->any.window);
1373 event->any.window = g_object_ref (new_window);
1378 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1379 * then what X11 does is deliver the event normally if it was going to this
1380 * client, otherwise, delivers it in terms of the grab window. This function
1381 * rewrites events to the effect that events going to the same window group
1382 * are delivered normally, otherwise, the event is delivered in terms of the
1386 rewrite_event_for_grabs (GdkEvent *event)
1388 GdkWindow *grab_window;
1389 GtkWidget *event_widget, *grab_widget;
1390 gpointer grab_widget_ptr;
1391 gboolean owner_events;
1392 GdkDisplay *display;
1395 switch (event->type)
1398 case GDK_BUTTON_PRESS:
1399 case GDK_2BUTTON_PRESS:
1400 case GDK_3BUTTON_PRESS:
1401 case GDK_BUTTON_RELEASE:
1402 case GDK_MOTION_NOTIFY:
1403 case GDK_PROXIMITY_IN:
1404 case GDK_PROXIMITY_OUT:
1406 case GDK_KEY_RELEASE:
1407 display = gdk_drawable_get_display (event->any.window);
1408 device = gdk_event_get_device (event);
1410 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1418 event_widget = gtk_get_event_widget (event);
1419 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1420 grab_widget = grab_widget_ptr;
1423 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1424 return rewrite_event_for_window (event, grab_window);
1430 gtk_main_do_event (GdkEvent *event)
1432 GtkWidget *event_widget;
1433 GtkWidget *grab_widget = NULL;
1434 GtkWindowGroup *window_group;
1435 GdkEvent *rewritten_event = NULL;
1439 if (event->type == GDK_SETTING)
1441 _gtk_settings_handle_event (&event->setting);
1445 if (event->type == GDK_OWNER_CHANGE)
1447 _gtk_clipboard_handle_event (&event->owner_change);
1451 /* Find the widget which got the event. We store the widget
1452 * in the user_data field of GdkWindow's.
1453 * Ignore the event if we don't have a widget for it, except
1454 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1455 * Though this happens rarely, bogus events can occour
1456 * for e.g. destroyed GdkWindows.
1458 event_widget = gtk_get_event_widget (event);
1461 /* To handle selection INCR transactions, we select
1462 * PropertyNotify events on the requestor window and create
1463 * a corresponding (fake) GdkWindow so that events get
1464 * here. There won't be a widget though, so we have to handle
1467 if (event->type == GDK_PROPERTY_NOTIFY)
1468 _gtk_selection_incr_event (event->any.window,
1474 /* If pointer or keyboard grabs are in effect, munge the events
1475 * so that each window group looks like a separate app.
1477 rewritten_event = rewrite_event_for_grabs (event);
1478 if (rewritten_event)
1480 event = rewritten_event;
1481 event_widget = gtk_get_event_widget (event);
1484 window_group = gtk_main_get_window_group (event_widget);
1485 device = gdk_event_get_device (event);
1487 /* check whether there is a (device) grab in effect...
1490 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1492 if (!grab_widget && window_group->grabs)
1493 grab_widget = window_group->grabs->data;
1495 /* If the grab widget is an ancestor of the event widget
1496 * then we send the event to the original event widget.
1497 * This is the key to implementing modality.
1500 (gtk_widget_is_sensitive (event_widget) &&
1501 gtk_widget_is_ancestor (event_widget, grab_widget)))
1502 grab_widget = event_widget;
1504 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1506 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1508 if (rewritten_event)
1509 gdk_event_free (rewritten_event);
1514 /* Push the event onto a stack of current events for
1515 * gtk_current_event_get().
1517 current_events = g_list_prepend (current_events, event);
1519 /* Not all events get sent to the grabbing widget.
1520 * The delete, destroy, expose, focus change and resize
1521 * events still get sent to the event widget because
1522 * 1) these events have no meaning for the grabbing widget
1523 * and 2) redirecting these events to the grabbing widget
1524 * could cause the display to be messed up.
1526 * Drag events are also not redirected, since it isn't
1527 * clear what the semantics of that would be.
1529 switch (event->type)
1535 g_object_ref (event_widget);
1536 if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1537 !gtk_widget_event (event_widget, event))
1538 gtk_widget_destroy (event_widget);
1539 g_object_unref (event_widget);
1543 /* Unexpected GDK_DESTROY from the outside, ignore for
1544 * child windows, handle like a GDK_DELETE for toplevels
1546 if (!event_widget->parent)
1548 g_object_ref (event_widget);
1549 if (!gtk_widget_event (event_widget, event) &&
1550 gtk_widget_get_realized (event_widget))
1551 gtk_widget_destroy (event_widget);
1552 g_object_unref (event_widget);
1557 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1559 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1560 gtk_widget_send_expose (event_widget, event);
1561 gdk_window_end_paint (event->any.window);
1565 /* The app may paint with a previously allocated cairo_t,
1566 which will draw directly to the window. We can't catch cairo
1567 drap operatoins to automatically flush the window, thus we
1568 need to explicitly flush any outstanding moves or double
1570 gdk_window_flush (event->any.window);
1571 gtk_widget_send_expose (event_widget, event);
1575 case GDK_PROPERTY_NOTIFY:
1577 case GDK_FOCUS_CHANGE:
1581 case GDK_SELECTION_CLEAR:
1582 case GDK_SELECTION_REQUEST:
1583 case GDK_SELECTION_NOTIFY:
1584 case GDK_CLIENT_EVENT:
1585 case GDK_VISIBILITY_NOTIFY:
1586 case GDK_WINDOW_STATE:
1587 case GDK_GRAB_BROKEN:
1589 gtk_widget_event (event_widget, event);
1593 case GDK_BUTTON_PRESS:
1594 case GDK_2BUTTON_PRESS:
1595 case GDK_3BUTTON_PRESS:
1596 gtk_propagate_event (grab_widget, event);
1600 case GDK_KEY_RELEASE:
1603 if (gtk_invoke_key_snoopers (grab_widget, event))
1606 /* Catch alt press to enable auto-mnemonics;
1607 * menus are handled elsewhere
1609 if ((event->key.keyval == GDK_Alt_L || event->key.keyval == GDK_Alt_R) &&
1610 !GTK_IS_MENU_SHELL (grab_widget))
1612 gboolean auto_mnemonics;
1614 g_object_get (gtk_widget_get_settings (grab_widget),
1615 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1619 gboolean mnemonics_visible;
1622 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1624 window = gtk_widget_get_toplevel (grab_widget);
1626 if (GTK_IS_WINDOW (window))
1627 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1630 /* else fall through */
1631 case GDK_MOTION_NOTIFY:
1632 case GDK_BUTTON_RELEASE:
1633 case GDK_PROXIMITY_IN:
1634 case GDK_PROXIMITY_OUT:
1635 gtk_propagate_event (grab_widget, event);
1638 case GDK_ENTER_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_LEAVE_NOTIFY:
1647 _gtk_widget_set_device_window (event_widget,
1648 gdk_event_get_device (event),
1650 if (gtk_widget_is_sensitive (grab_widget))
1651 gtk_widget_event (grab_widget, event);
1654 case GDK_DRAG_STATUS:
1655 case GDK_DROP_FINISHED:
1656 _gtk_drag_source_handle_event (event_widget, event);
1658 case GDK_DRAG_ENTER:
1659 case GDK_DRAG_LEAVE:
1660 case GDK_DRAG_MOTION:
1661 case GDK_DROP_START:
1662 _gtk_drag_dest_handle_event (event_widget, event);
1665 g_assert_not_reached ();
1669 if (event->type == GDK_ENTER_NOTIFY
1670 || event->type == GDK_LEAVE_NOTIFY
1671 || event->type == GDK_BUTTON_PRESS
1672 || event->type == GDK_2BUTTON_PRESS
1673 || event->type == GDK_3BUTTON_PRESS
1674 || event->type == GDK_KEY_PRESS
1675 || event->type == GDK_DRAG_ENTER
1676 || event->type == GDK_GRAB_BROKEN
1677 || event->type == GDK_MOTION_NOTIFY
1678 || event->type == GDK_SCROLL)
1680 _gtk_tooltip_handle_event (event);
1683 tmp_list = current_events;
1684 current_events = g_list_remove_link (current_events, tmp_list);
1685 g_list_free_1 (tmp_list);
1687 if (rewritten_event)
1688 gdk_event_free (rewritten_event);
1703 static GtkWindowGroup *
1704 gtk_main_get_window_group (GtkWidget *widget)
1706 GtkWidget *toplevel = NULL;
1709 toplevel = gtk_widget_get_toplevel (widget);
1711 if (GTK_IS_WINDOW (toplevel))
1712 return gtk_window_get_group (GTK_WINDOW (toplevel));
1714 return gtk_window_get_group (NULL);
1719 GtkWidget *old_grab_widget;
1720 GtkWidget *new_grab_widget;
1721 gboolean was_grabbed;
1722 gboolean is_grabbed;
1724 GList *notified_windows;
1729 synth_crossing_for_grab_notify (GtkWidget *from,
1731 GrabNotifyInfo *info,
1733 GdkCrossingMode mode)
1737 GdkDevice *device = devices->data;
1738 GdkWindow *from_window, *to_window;
1740 /* Do not propagate events more than once to
1741 * the same windows if non-multidevice aware.
1747 from_window = _gtk_widget_get_device_window (from, device);
1750 !gdk_window_get_support_multidevice (from_window) &&
1751 g_list_find (info->notified_windows, from_window))
1759 to_window = _gtk_widget_get_device_window (to, device);
1762 !gdk_window_get_support_multidevice (to_window) &&
1763 g_list_find (info->notified_windows, to_window))
1767 if (from_window || to_window)
1769 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1770 (to_window) ? to : NULL,
1774 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1777 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1780 devices = devices->next;
1785 gtk_grab_notify_foreach (GtkWidget *child,
1788 GrabNotifyInfo *info = data;
1789 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1792 was_grabbed = info->was_grabbed;
1793 is_grabbed = info->is_grabbed;
1795 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1796 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1798 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1799 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1801 g_object_ref (child);
1803 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1804 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1807 _gtk_widget_get_device_window (child, info->device))
1809 /* Device specified and is on widget */
1810 devices = g_list_prepend (NULL, info->device);
1813 devices = _gtk_widget_list_devices (child);
1817 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1818 if (!was_shadowed && devices &&
1819 gtk_widget_is_sensitive (child))
1820 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1822 GDK_CROSSING_GTK_GRAB);
1826 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1827 if (was_shadowed && devices &&
1828 gtk_widget_is_sensitive (child))
1829 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1831 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1832 GDK_CROSSING_GTK_UNGRAB);
1835 if (was_shadowed != is_shadowed)
1836 _gtk_widget_grab_notify (child, was_shadowed);
1838 g_object_unref (child);
1839 g_list_free (devices);
1841 info->was_grabbed = was_grabbed;
1842 info->is_grabbed = is_grabbed;
1846 gtk_grab_notify (GtkWindowGroup *group,
1848 GtkWidget *old_grab_widget,
1849 GtkWidget *new_grab_widget,
1853 GrabNotifyInfo info = { 0 };
1855 if (old_grab_widget == new_grab_widget)
1858 info.old_grab_widget = old_grab_widget;
1859 info.new_grab_widget = new_grab_widget;
1860 info.from_grab = from_grab;
1861 info.device = device;
1863 g_object_ref (group);
1865 toplevels = gtk_window_list_toplevels ();
1866 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1870 GtkWindow *toplevel = toplevels->data;
1871 toplevels = g_list_delete_link (toplevels, toplevels);
1873 info.was_grabbed = FALSE;
1874 info.is_grabbed = FALSE;
1876 if (group == gtk_window_get_group (toplevel))
1877 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1878 g_object_unref (toplevel);
1881 g_list_free (info.notified_windows);
1882 g_object_unref (group);
1886 gtk_grab_add (GtkWidget *widget)
1888 GtkWindowGroup *group;
1889 GtkWidget *old_grab_widget;
1891 g_return_if_fail (widget != NULL);
1893 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
1895 _gtk_widget_set_has_grab (widget, TRUE);
1897 group = gtk_main_get_window_group (widget);
1900 old_grab_widget = (GtkWidget *)group->grabs->data;
1902 old_grab_widget = NULL;
1904 g_object_ref (widget);
1905 group->grabs = g_slist_prepend (group->grabs, widget);
1907 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
1912 gtk_grab_get_current (void)
1914 GtkWindowGroup *group;
1916 group = gtk_main_get_window_group (NULL);
1919 return GTK_WIDGET (group->grabs->data);
1924 gtk_grab_remove (GtkWidget *widget)
1926 GtkWindowGroup *group;
1927 GtkWidget *new_grab_widget;
1929 g_return_if_fail (widget != NULL);
1931 if (gtk_widget_has_grab (widget))
1933 _gtk_widget_set_has_grab (widget, FALSE);
1935 group = gtk_main_get_window_group (widget);
1936 group->grabs = g_slist_remove (group->grabs, widget);
1939 new_grab_widget = (GtkWidget *)group->grabs->data;
1941 new_grab_widget = NULL;
1943 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
1945 g_object_unref (widget);
1950 * gtk_device_grab_add:
1951 * @widget: a #GtkWidget
1952 * @device: a #GtkDevice to grab on.
1953 * @block_others: %TRUE to prevent other devices to interact with @widget.
1955 * Adds a GTK+ grab on @device, so all the events on @device and its
1956 * associated pointer or keyboard (if any) are delivered to @widget.
1957 * If the @block_others parameter is %TRUE, any other devices will be
1958 * unable to interact with @widget during the grab.
1963 gtk_device_grab_add (GtkWidget *widget,
1965 gboolean block_others)
1967 GtkWindowGroup *group;
1968 GtkWidget *old_grab_widget;
1970 g_return_if_fail (GTK_IS_WIDGET (widget));
1971 g_return_if_fail (GDK_IS_DEVICE (device));
1973 group = gtk_main_get_window_group (widget);
1974 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
1976 if (old_grab_widget != widget)
1977 _gtk_window_group_add_device_grab (group, widget, device, block_others);
1979 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
1983 * gtk_device_grab_remove:
1984 * @widget: a #GtkWidget
1985 * @device: a #GdkDevice
1987 * Removes a device grab from the given widget. You have to pair calls
1988 * to gtk_device_grab_add() and gtk_device_grab_remove().
1993 gtk_device_grab_remove (GtkWidget *widget,
1996 GtkWindowGroup *group;
1997 GtkWidget *new_grab_widget;
1999 g_return_if_fail (GTK_IS_WIDGET (widget));
2000 g_return_if_fail (GDK_IS_DEVICE (device));
2002 group = gtk_main_get_window_group (widget);
2003 _gtk_window_group_remove_device_grab (group, widget, device);
2004 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2006 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2010 gtk_init_add (GtkFunction function,
2013 GtkInitFunction *init;
2015 init = g_new (GtkInitFunction, 1);
2016 init->function = function;
2019 init_functions = g_list_prepend (init_functions, init);
2023 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2026 GtkKeySnooperData *data;
2027 static guint snooper_id = 1;
2029 g_return_val_if_fail (snooper != NULL, 0);
2031 data = g_new (GtkKeySnooperData, 1);
2032 data->func = snooper;
2033 data->func_data = func_data;
2034 data->id = snooper_id++;
2035 key_snoopers = g_slist_prepend (key_snoopers, data);
2041 gtk_key_snooper_remove (guint snooper_id)
2043 GtkKeySnooperData *data = NULL;
2046 slist = key_snoopers;
2050 if (data->id == snooper_id)
2053 slist = slist->next;
2058 key_snoopers = g_slist_remove (key_snoopers, data);
2064 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2068 gint return_val = FALSE;
2070 slist = key_snoopers;
2071 while (slist && !return_val)
2073 GtkKeySnooperData *data;
2076 slist = slist->next;
2077 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2084 gtk_quit_add_full (guint main_level,
2085 GtkFunction function,
2086 GtkCallbackMarshal marshal,
2088 GDestroyNotify destroy)
2090 static guint quit_id = 1;
2091 GtkQuitFunction *quitf;
2093 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2095 quitf = g_slice_new (GtkQuitFunction);
2097 quitf->id = quit_id++;
2098 quitf->main_level = main_level;
2099 quitf->function = function;
2100 quitf->marshal = marshal;
2102 quitf->destroy = destroy;
2104 quit_functions = g_list_prepend (quit_functions, quitf);
2110 gtk_quit_destroy (GtkQuitFunction *quitf)
2113 quitf->destroy (quitf->data);
2114 g_slice_free (GtkQuitFunction, quitf);
2118 gtk_quit_destructor (GtkObject **object_p)
2121 gtk_object_destroy (*object_p);
2128 gtk_quit_add_destroy (guint main_level,
2131 GtkObject **object_p;
2133 g_return_if_fail (main_level > 0);
2134 g_return_if_fail (GTK_IS_OBJECT (object));
2136 object_p = g_new (GtkObject*, 1);
2138 g_signal_connect (object,
2140 G_CALLBACK (gtk_widget_destroyed),
2142 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2146 gtk_quit_add (guint main_level,
2147 GtkFunction function,
2150 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2154 gtk_quit_remove (guint id)
2156 GtkQuitFunction *quitf;
2159 tmp_list = quit_functions;
2162 quitf = tmp_list->data;
2164 if (quitf->id == id)
2166 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2167 g_list_free (tmp_list);
2168 gtk_quit_destroy (quitf);
2173 tmp_list = tmp_list->next;
2178 gtk_quit_remove_by_data (gpointer data)
2180 GtkQuitFunction *quitf;
2183 tmp_list = quit_functions;
2186 quitf = tmp_list->data;
2188 if (quitf->data == data)
2190 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2191 g_list_free (tmp_list);
2192 gtk_quit_destroy (quitf);
2197 tmp_list = tmp_list->next;
2202 * gtk_get_current_event:
2204 * Obtains a copy of the event currently being processed by GTK+. For
2205 * example, if you get a "clicked" signal from #GtkButton, the current
2206 * event will be the #GdkEventButton that triggered the "clicked"
2207 * signal. The returned event must be freed with gdk_event_free().
2208 * If there is no current event, the function returns %NULL.
2210 * Return value: a copy of the current event, or %NULL if no current event.
2213 gtk_get_current_event (void)
2216 return gdk_event_copy (current_events->data);
2222 * gtk_get_current_event_time:
2224 * If there is a current event and it has a timestamp, return that
2225 * timestamp, otherwise return %GDK_CURRENT_TIME.
2227 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2230 gtk_get_current_event_time (void)
2233 return gdk_event_get_time (current_events->data);
2235 return GDK_CURRENT_TIME;
2239 * gtk_get_current_event_state:
2240 * @state: a location to store the state of the current event
2242 * If there is a current event and it has a state field, place
2243 * that state field in @state and return %TRUE, otherwise return
2246 * Return value: %TRUE if there was a current event and it had a state field
2249 gtk_get_current_event_state (GdkModifierType *state)
2251 g_return_val_if_fail (state != NULL, FALSE);
2254 return gdk_event_get_state (current_events->data, state);
2263 * gtk_get_current_event_device:
2265 * If there is a current event and it has a device, return that
2266 * device, otherwise return %NULL.
2268 * Returns: a #GdkDevice, or %NULL
2271 gtk_get_current_event_device (void)
2274 return gdk_event_get_device (current_events->data);
2280 * gtk_get_event_widget:
2281 * @event: a #GdkEvent
2283 * If @event is %NULL or the event was not associated with any widget,
2284 * returns %NULL, otherwise returns the widget that received the event
2287 * Return value: the widget that originally received @event, or %NULL
2290 gtk_get_event_widget (GdkEvent *event)
2293 gpointer widget_ptr;
2296 if (event && event->any.window &&
2297 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2299 gdk_window_get_user_data (event->any.window, &widget_ptr);
2300 widget = widget_ptr;
2307 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2309 if (!quitf->marshal)
2310 return quitf->function (quitf->data);
2314 gint ret_val = FALSE;
2316 args[0].name = NULL;
2317 args[0].type = G_TYPE_BOOLEAN;
2318 args[0].d.pointer_data = &ret_val;
2319 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2327 * gtk_propagate_event:
2328 * @widget: a #GtkWidget
2331 * Sends an event to a widget, propagating the event to parent widgets
2332 * if the event remains unhandled. Events received by GTK+ from GDK
2333 * normally begin in gtk_main_do_event(). Depending on the type of
2334 * event, existence of modal dialogs, grabs, etc., the event may be
2335 * propagated; if so, this function is used. gtk_propagate_event()
2336 * calls gtk_widget_event() on each widget it decides to send the
2337 * event to. So gtk_widget_event() is the lowest-level function; it
2338 * simply emits the "event" and possibly an event-specific signal on a
2339 * widget. gtk_propagate_event() is a bit higher-level, and
2340 * gtk_main_do_event() is the highest level.
2342 * All that said, you most likely don't want to use any of these
2343 * functions; synthesizing events is rarely needed. Consider asking on
2344 * the mailing list for better ways to achieve your goals. For
2345 * example, use gdk_window_invalidate_rect() or
2346 * gtk_widget_queue_draw() instead of making up expose events.
2350 gtk_propagate_event (GtkWidget *widget,
2355 g_return_if_fail (GTK_IS_WIDGET (widget));
2356 g_return_if_fail (event != NULL);
2358 handled_event = FALSE;
2360 g_object_ref (widget);
2362 if ((event->type == GDK_KEY_PRESS) ||
2363 (event->type == GDK_KEY_RELEASE))
2365 /* Only send key events within Window widgets to the Window
2366 * The Window widget will in turn pass the
2367 * key event on to the currently focused widget
2372 window = gtk_widget_get_toplevel (widget);
2373 if (GTK_IS_WINDOW (window))
2375 /* If there is a grab within the window, give the grab widget
2376 * a first crack at the key event
2378 if (widget != window && gtk_widget_has_grab (widget))
2379 handled_event = gtk_widget_event (widget, event);
2383 window = gtk_widget_get_toplevel (widget);
2384 if (GTK_IS_WINDOW (window))
2386 if (gtk_widget_is_sensitive (window))
2387 gtk_widget_event (window, event);
2391 handled_event = TRUE; /* don't send to widget */
2395 /* Other events get propagated up the widget tree
2396 * so that parents can see the button and motion
2397 * events of the children.
2405 /* Scroll events are special cased here because it
2406 * feels wrong when scrolling a GtkViewport, say,
2407 * to have children of the viewport eat the scroll
2410 if (!gtk_widget_is_sensitive (widget))
2411 handled_event = event->type != GDK_SCROLL;
2413 handled_event = gtk_widget_event (widget, event);
2415 tmp = widget->parent;
2416 g_object_unref (widget);
2420 if (!handled_event && widget)
2421 g_object_ref (widget);
2427 g_object_unref (widget);
2431 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2432 GValue *return_accu,
2433 const GValue *handler_return,
2436 gboolean continue_emission;
2437 gboolean signal_handled;
2439 signal_handled = g_value_get_boolean (handler_return);
2440 g_value_set_boolean (return_accu, signal_handled);
2441 continue_emission = !signal_handled;
2443 return continue_emission;
2446 #define __GTK_MAIN_C__
2447 #include "gtkaliasdef.c"