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"
66 #include "gdk/gdkkeysyms.h"
68 #include "gdk/gdkprivate.h" /* for GDK_WINDOW_DESTROYED */
72 static HMODULE gtk_dll;
75 DllMain (HINSTANCE hinstDLL,
81 case DLL_PROCESS_ATTACH:
82 gtk_dll = (HMODULE) hinstDLL;
89 /* These here before inclusion of gtkprivate.h so that the original
90 * GTK_LIBDIR and GTK_LOCALEDIR definitions are seen. Yeah, this is a
94 _gtk_get_libdir (void)
96 static char *gtk_libdir = NULL;
97 if (gtk_libdir == NULL)
99 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
100 gchar *slash = strrchr (root, '\\');
101 if (g_ascii_strcasecmp (slash + 1, ".libs") == 0)
102 gtk_libdir = GTK_LIBDIR;
104 gtk_libdir = g_build_filename (root, "lib", NULL);
112 _gtk_get_localedir (void)
114 static char *gtk_localedir = NULL;
115 if (gtk_localedir == NULL)
120 /* GTK_LOCALEDIR ends in either /lib/locale or
121 * /share/locale. Scan for that slash.
123 p = GTK_LOCALEDIR + strlen (GTK_LOCALEDIR);
129 root = g_win32_get_package_installation_directory_of_module (gtk_dll);
130 temp = g_build_filename (root, p, NULL);
133 /* gtk_localedir is passed to bindtextdomain() which isn't
136 gtk_localedir = g_win32_locale_filename_from_utf8 (temp);
139 return gtk_localedir;
144 #include "gtkprivate.h"
146 /* Private type definitions
148 typedef struct _GtkInitFunction GtkInitFunction;
149 typedef struct _GtkQuitFunction GtkQuitFunction;
150 typedef struct _GtkKeySnooperData GtkKeySnooperData;
152 struct _GtkInitFunction
154 GtkFunction function;
158 struct _GtkQuitFunction
162 GtkCallbackMarshal marshal;
163 GtkFunction function;
165 GDestroyNotify destroy;
168 struct _GtkKeySnooperData
170 GtkKeySnoopFunc func;
175 static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
176 static void gtk_quit_destroy (GtkQuitFunction *quitf);
177 static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
180 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
182 static guint gtk_main_loop_level = 0;
183 static gint pre_initialized = FALSE;
184 static gint gtk_initialized = FALSE;
185 static GList *current_events = NULL;
187 static GSList *main_loops = NULL; /* stack of currently executing main loops */
189 static GList *init_functions = NULL; /* A list of init functions.
191 static GList *quit_functions = NULL; /* A list of quit functions.
193 static GSList *key_snoopers = NULL;
195 static guint debug_flags = 0; /* Global GTK debug flag */
197 #ifdef G_ENABLE_DEBUG
198 static const GDebugKey gtk_debug_keys[] = {
199 {"misc", GTK_DEBUG_MISC},
200 {"plugsocket", GTK_DEBUG_PLUGSOCKET},
201 {"text", GTK_DEBUG_TEXT},
202 {"tree", GTK_DEBUG_TREE},
203 {"updates", GTK_DEBUG_UPDATES},
204 {"keybindings", GTK_DEBUG_KEYBINDINGS},
205 {"multihead", GTK_DEBUG_MULTIHEAD},
206 {"modules", GTK_DEBUG_MODULES},
207 {"geometry", GTK_DEBUG_GEOMETRY},
208 {"icontheme", GTK_DEBUG_ICONTHEME},
209 {"printing", GTK_DEBUG_PRINTING},
210 {"builder", GTK_DEBUG_BUILDER},
211 {"size-request", GTK_DEBUG_SIZE_REQUEST},
213 #endif /* G_ENABLE_DEBUG */
216 * gtk_get_major_version:
218 * Returns the major version number of the GTK+ library. (e.g. in GTK+ version
221 * This function is in the library, so it represents the GTK+ library
222 * your code is running against. Contrast with the #GTK_MAJOR_VERSION
223 * macro, which represents the major version of the GTK+ headers you
224 * have included when compiling your code.
226 * Returns: the major version number of the GTK+ library.
231 gtk_get_major_version (void)
233 return GTK_MAJOR_VERSION;
237 * gtk_get_minor_version:
239 * Returns the minor version number of the GTK+ library. (e.g. in GTK+ version
242 * This function is in the library, so it represents the GTK+ library
243 * your code is are running against. Contrast with the
244 * #GTK_MINOR_VERSION macro, which represents the minor version of the
245 * GTK+ headers you have included when compiling your code.
247 * Returns: the minor version number of the GTK+ library.
252 gtk_get_minor_version (void)
254 return GTK_MINOR_VERSION;
258 * gtk_get_micro_version:
260 * Returns the micro version number of the GTK+ library. (e.g. in GTK+ version
263 * This function is in the library, so it represents the GTK+ library
264 * your code is are running against. Contrast with the
265 * #GTK_MICRO_VERSION macro, which represents the micro version of the
266 * GTK+ headers you have included when compiling your code.
268 * Returns: the micro version number of the GTK+ library.
273 gtk_get_micro_version (void)
275 return GTK_MICRO_VERSION;
279 * gtk_get_binary_age:
281 * Returns the binary age as passed to
282 * <application>libtool</application> when building the GTK+ library
283 * the process is running against. If
284 * <application>libtool</application> means nothing to you, don't
287 * Returns: the binary age of the GTK+ library.
292 gtk_get_binary_age (void)
294 return GTK_BINARY_AGE;
298 * gtk_get_interface_age:
300 * Returns the interface age as passed to
301 * <application>libtool</application> when building the GTK+ library
302 * the process is running against. If
303 * <application>libtool</application> means nothing to you, don't
306 * Returns: the interface age of the GTK+ library.
311 gtk_get_interface_age (void)
313 return GTK_INTERFACE_AGE;
318 * @required_major: the required major version.
319 * @required_minor: the required minor version.
320 * @required_micro: the required micro version.
322 * Checks that the GTK+ library in use is compatible with the
323 * given version. Generally you would pass in the constants
324 * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
325 * as the three arguments to this function; that produces
326 * a check that the library in use is compatible with
327 * the version of GTK+ the application or module was compiled
330 * Compatibility is defined by two things: first the version
331 * of the running library is newer than the version
332 * @required_major.required_minor.@required_micro. Second
333 * the running library must be binary compatible with the
334 * version @required_major.required_minor.@required_micro
335 * (same major version.)
337 * This function is primarily for GTK+ modules; the module
338 * can call this function to check that it wasn't loaded
339 * into an incompatible version of GTK+. However, such a
340 * a check isn't completely reliable, since the module may be
341 * linked against an old version of GTK+ and calling the
342 * old version of gtk_check_version(), but still get loaded
343 * into an application using a newer version of GTK+.
345 * Return value: %NULL if the GTK+ library is compatible with the
346 * given version, or a string describing the version mismatch.
347 * The returned string is owned by GTK+ and should not be modified
351 gtk_check_version (guint required_major,
352 guint required_minor,
353 guint required_micro)
355 gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
356 gint required_effective_micro = 100 * required_minor + required_micro;
358 if (required_major > GTK_MAJOR_VERSION)
359 return "Gtk+ version too old (major mismatch)";
360 if (required_major < GTK_MAJOR_VERSION)
361 return "Gtk+ version too new (major mismatch)";
362 if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
363 return "Gtk+ version too new (micro mismatch)";
364 if (required_effective_micro > gtk_effective_micro)
365 return "Gtk+ version too old (micro mismatch)";
369 /* This checks to see if the process is running suid or sgid
370 * at the current time. If so, we don't allow GTK+ to be initialized.
371 * This is meant to be a mild check - we only error out if we
372 * can prove the programmer is doing something wrong, not if
373 * they could be doing something wrong. For this reason, we
374 * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
379 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
381 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
382 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
384 #ifdef HAVE_GETRESUID
385 /* These aren't in the header files, so we prototype them here.
387 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
388 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
390 if (getresuid (&ruid, &euid, &suid) != 0 ||
391 getresgid (&rgid, &egid, &sgid) != 0)
392 #endif /* HAVE_GETRESUID */
394 suid = ruid = getuid ();
395 sgid = rgid = getgid ();
400 if (ruid != euid || ruid != suid ||
401 rgid != egid || rgid != sgid)
403 g_warning ("This process is currently running setuid or setgid.\n"
404 "This is not a supported use of GTK+. You must create a helper\n"
405 "program instead. For further details, see:\n\n"
406 " http://www.gtk.org/setuid.html\n\n"
407 "Refusing to initialize GTK+.");
417 _gtk_get_datadir (void)
419 static char *gtk_datadir = NULL;
420 if (gtk_datadir == NULL)
422 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
423 gtk_datadir = g_build_filename (root, "share", NULL);
431 _gtk_get_sysconfdir (void)
433 static char *gtk_sysconfdir = NULL;
434 if (gtk_sysconfdir == NULL)
436 gchar *root = g_win32_get_package_installation_directory_of_module (gtk_dll);
437 gtk_sysconfdir = g_build_filename (root, "etc", NULL);
441 return gtk_sysconfdir;
445 _gtk_get_data_prefix (void)
447 static char *gtk_data_prefix = NULL;
448 if (gtk_data_prefix == NULL)
449 gtk_data_prefix = g_win32_get_package_installation_directory_of_module (gtk_dll);
451 return gtk_data_prefix;
454 #endif /* G_OS_WIN32 */
456 static gboolean do_setlocale = TRUE;
459 * gtk_disable_setlocale:
461 * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
462 * gtk_parse_args() from automatically
463 * calling <literal>setlocale (LC_ALL, "")</literal>. You would
464 * want to use this function if you wanted to set the locale for
465 * your program to something other than the user's locale, or if
466 * you wanted to set different values for different locale categories.
468 * Most programs should not need to call this function.
471 gtk_disable_setlocale (void)
474 g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
476 do_setlocale = FALSE;
479 #ifdef G_PLATFORM_WIN32
480 #undef gtk_init_check
483 static GString *gtk_modules_string = NULL;
484 static gboolean g_fatal_warnings = FALSE;
486 #ifdef G_ENABLE_DEBUG
488 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
490 debug_flags |= g_parse_debug_string (value,
492 G_N_ELEMENTS (gtk_debug_keys));
498 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
500 debug_flags &= ~g_parse_debug_string (value,
502 G_N_ELEMENTS (gtk_debug_keys));
506 #endif /* G_ENABLE_DEBUG */
509 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
513 if (gtk_modules_string)
514 g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
516 gtk_modules_string = g_string_new (NULL);
518 g_string_append (gtk_modules_string, value);
524 static const GOptionEntry gtk_args[] = {
525 { "gtk-module", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,
526 /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"),
527 /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
528 { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings,
529 /* Description of --g-fatal-warnings in --help output */ N_("Make all warnings fatal"), NULL },
530 #ifdef G_ENABLE_DEBUG
531 { "gtk-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,
532 /* Description of --gtk-debug=FLAGS in --help output */ N_("GTK+ debugging flags to set"),
533 /* Placeholder in --gtk-debug=FLAGS in --help output */ N_("FLAGS") },
534 { "gtk-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb,
535 /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"),
536 /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
543 static char *iso639_to_check = NULL;
544 static char *iso3166_to_check = NULL;
545 static char *script_to_check = NULL;
546 static gboolean setlocale_called = FALSE;
549 enum_locale_proc (LPTSTR locale)
557 lcid = strtoul (locale, &endptr, 16);
558 if (*endptr == '\0' &&
559 GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) &&
560 GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
562 if (strcmp (iso639, iso639_to_check) == 0 &&
563 ((iso3166_to_check != NULL &&
564 strcmp (iso3166, iso3166_to_check) == 0) ||
565 (iso3166_to_check == NULL &&
566 SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT)))
568 char language[100], country[100];
571 if (script_to_check != NULL)
573 /* If lcid is the "other" script for this language,
574 * return TRUE, i.e. continue looking.
576 if (strcmp (script_to_check, "Latn") == 0)
578 switch (LANGIDFROMLCID (lcid))
580 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC):
582 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC):
584 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC):
586 case MAKELANGID (LANG_SERBIAN, 0x07):
587 /* Serbian in Bosnia and Herzegovina, Cyrillic */
591 else if (strcmp (script_to_check, "Cyrl") == 0)
593 switch (LANGIDFROMLCID (lcid))
595 case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN):
597 case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN):
599 case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN):
601 case MAKELANGID (LANG_SERBIAN, 0x06):
602 /* Serbian in Bosnia and Herzegovina, Latin */
608 SetThreadLocale (lcid);
610 if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) &&
611 GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country)))
613 strcpy (locale, language);
614 strcat (locale, "_");
615 strcat (locale, country);
617 if (setlocale (LC_ALL, locale) != NULL)
618 setlocale_called = TRUE;
631 setlocale_initialization (void)
633 static gboolean initialized = FALSE;
642 /* If some of the POSIXish environment variables are set, set
643 * the Win32 thread locale correspondingly.
645 char *p = getenv ("LC_ALL");
652 if (strcmp (p, "C") == 0)
653 SetThreadLocale (LOCALE_SYSTEM_DEFAULT);
656 /* Check if one of the supported locales match the
657 * environment variable. If so, use that locale.
660 iso3166_to_check = strchr (iso639_to_check, '_');
661 if (iso3166_to_check != NULL)
663 *iso3166_to_check++ = '\0';
665 script_to_check = strchr (iso3166_to_check, '@');
666 if (script_to_check != NULL)
667 *script_to_check++ = '\0';
669 /* Handle special cases. */
671 /* The standard code for Serbia and Montenegro was
672 * "CS", but MSFT uses for some reason "SP". By now
673 * (October 2006), SP has split into two, "RS" and
674 * "ME", but don't bother trying to handle those
675 * yet. Do handle the even older "YU", though.
677 if (strcmp (iso3166_to_check, "CS") == 0 ||
678 strcmp (iso3166_to_check, "YU") == 0)
679 iso3166_to_check = "SP";
683 script_to_check = strchr (iso639_to_check, '@');
684 if (script_to_check != NULL)
685 *script_to_check++ = '\0';
686 /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */
687 if (strcmp (iso639_to_check, "sr") == 0)
688 iso3166_to_check = "SP";
691 EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED);
695 if (!setlocale_called)
696 setlocale (LC_ALL, "");
698 if (!setlocale (LC_ALL, ""))
699 g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
705 check_mixed_deps (void)
710 module = g_module_open (NULL, 0);
712 if (g_module_symbol (module, "gtk_progress_get_type", &func))
714 g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
717 g_module_close (module);
721 do_pre_parse_initialization (int *argc,
724 const gchar *env_string;
729 pre_initialized = TRUE;
733 gdk_pre_parse_libgtk_only ();
734 gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
736 #ifdef G_ENABLE_DEBUG
737 env_string = g_getenv ("GTK_DEBUG");
738 if (env_string != NULL)
740 debug_flags = g_parse_debug_string (env_string,
742 G_N_ELEMENTS (gtk_debug_keys));
745 #endif /* G_ENABLE_DEBUG */
747 env_string = g_getenv ("GTK_MODULES");
749 gtk_modules_string = g_string_new (env_string);
753 gettext_initialization (void)
755 setlocale_initialization ();
758 bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
759 bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
760 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
761 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
762 bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
768 do_post_parse_initialization (int *argc,
774 gettext_initialization ();
777 signal (SIGPIPE, SIG_IGN);
780 if (g_fatal_warnings)
782 GLogLevelFlags fatal_mask;
784 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
785 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
786 g_log_set_always_fatal (fatal_mask);
789 if (debug_flags & GTK_DEBUG_UPDATES)
790 gdk_window_set_debug_updates (TRUE);
793 /* Translate to default:RTL if you want your widgets
794 * to be RTL, otherwise translate to default:LTR.
795 * Do *not* translate it to "predefinito:LTR", if it
796 * it isn't default:LTR or default:RTL it will not work
798 char *e = _("default:LTR");
799 if (strcmp (e, "default:RTL")==0)
800 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
801 else if (strcmp (e, "default:LTR"))
802 g_warning ("Whoever translated default:LTR did so wrongly.\n");
805 /* do what the call to gtk_type_init() used to do */
808 _gtk_accel_map_init ();
811 /* Set the 'initialized' flag.
813 gtk_initialized = TRUE;
815 /* load gtk modules */
816 if (gtk_modules_string)
818 _gtk_modules_init (argc, argv, gtk_modules_string->str);
819 g_string_free (gtk_modules_string, TRUE);
823 _gtk_modules_init (argc, argv, NULL);
830 gboolean open_default_display;
834 pre_parse_hook (GOptionContext *context,
839 do_pre_parse_initialization (NULL, NULL);
845 post_parse_hook (GOptionContext *context,
850 OptionGroupInfo *info = data;
853 do_post_parse_initialization (NULL, NULL);
855 if (info->open_default_display)
857 if (gdk_display_open_default_libgtk_only () == NULL)
859 const char *display_name = gdk_get_display_arg_name ();
862 G_OPTION_ERROR_FAILED,
863 _("Cannot open display: %s"),
864 display_name ? display_name : "" );
875 * gtk_get_debug_flags:
877 * Returns the GTK+ debug flags setting.
880 gtk_get_debug_flags (void)
886 * gtk_set_debug_flags:
888 * Sets the GTK+ debug flags.
891 gtk_set_debug_flags (guint flags)
897 * gtk_get_option_group:
898 * @open_default_display: whether to open the default display
899 * when parsing the commandline arguments
901 * Returns a #GOptionGroup for the commandline arguments recognized
902 * by GTK+ and GDK. You should add this group to your #GOptionContext
903 * with g_option_context_add_group(), if you are using
904 * g_option_context_parse() to parse your commandline arguments.
906 * Returns: a #GOptionGroup for the commandline arguments recognized
912 gtk_get_option_group (gboolean open_default_display)
915 OptionGroupInfo *info;
917 gettext_initialization ();
919 info = g_new0 (OptionGroupInfo, 1);
920 info->open_default_display = open_default_display;
922 group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
923 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
925 gdk_add_option_entries_libgtk_only (group);
926 g_option_group_add_entries (group, gtk_args);
927 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
933 * gtk_init_with_args:
934 * @argc: a pointer to the number of command line arguments.
935 * @argv: a pointer to the array of command line arguments.
936 * @parameter_string: a string which is displayed in
937 * the first line of <option>--help</option> output, after
938 * <literal><replaceable>programname</replaceable> [OPTION...]</literal>
939 * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
940 * describing the options of your program
941 * @translation_domain: a translation domain to use for translating
942 * the <option>--help</option> output for the options in @entries
943 * and the @parameter_string with gettext(), or %NULL
944 * @error: a return location for errors
946 * This function does the same work as gtk_init_check().
947 * Additionally, it allows you to add your own commandline options,
948 * and it automatically generates nicely formatted
949 * <option>--help</option> output. Note that your program will
950 * be terminated after writing out the help output.
952 * Returns: %TRUE if the GUI has been successfully initialized,
958 gtk_init_with_args (gint *argc,
960 const gchar *parameter_string,
961 const GOptionEntry *entries,
962 const gchar *translation_domain,
965 GOptionContext *context;
966 GOptionGroup *gtk_group;
970 return gdk_display_open_default_libgtk_only () != NULL;
972 gettext_initialization ();
974 if (!check_setugid ())
977 gtk_group = gtk_get_option_group (TRUE);
979 context = g_option_context_new (parameter_string);
980 g_option_context_add_group (context, gtk_group);
981 g_option_context_set_translation_domain (context, translation_domain);
984 g_option_context_add_main_entries (context, entries, translation_domain);
985 retval = g_option_context_parse (context, argc, argv, error);
987 g_option_context_free (context);
995 * @argc: (inout): a pointer to the number of command line arguments.
996 * @argv: (array) (inout): a pointer to the array of command line arguments.
998 * Parses command line arguments, and initializes global
999 * attributes of GTK+, but does not actually open a connection
1000 * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
1002 * Any arguments used by GTK+ or GDK are removed from the array and
1003 * @argc and @argv are updated accordingly.
1005 * You shouldn't call this function explicitely if you are using
1006 * gtk_init(), or gtk_init_check().
1008 * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
1011 gtk_parse_args (int *argc,
1014 GOptionContext *option_context;
1015 GOptionGroup *gtk_group;
1016 GError *error = NULL;
1018 if (gtk_initialized)
1021 gettext_initialization ();
1023 if (!check_setugid ())
1026 option_context = g_option_context_new (NULL);
1027 g_option_context_set_ignore_unknown_options (option_context, TRUE);
1028 g_option_context_set_help_enabled (option_context, FALSE);
1029 gtk_group = gtk_get_option_group (FALSE);
1030 g_option_context_set_main_group (option_context, gtk_group);
1031 if (!g_option_context_parse (option_context, argc, argv, &error))
1033 g_warning ("%s", error->message);
1034 g_error_free (error);
1037 g_option_context_free (option_context);
1042 #ifdef G_PLATFORM_WIN32
1043 #undef gtk_init_check
1048 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1049 * main() function. Changed if any arguments were handled.
1050 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1051 * Any parameters understood by gtk_init() are stripped before return.
1053 * This function does the same work as gtk_init() with only
1054 * a single change: It does not terminate the program if the GUI can't be
1055 * initialized. Instead it returns %FALSE on failure.
1057 * This way the application can fall back to some other means of communication
1058 * with the user - for example a curses or command line interface.
1060 * Return value: %TRUE if the GUI has been successfully initialized,
1064 gtk_init_check (int *argc,
1067 if (!gtk_parse_args (argc, argv))
1070 return gdk_display_open_default_libgtk_only () != NULL;
1073 #ifdef G_PLATFORM_WIN32
1079 * @argc: (inout): Address of the <parameter>argc</parameter> parameter of your
1080 * main() function. Changed if any arguments were handled.
1081 * @argv: (array length=argc) (inout) (allow-none): Address of the <parameter>argv</parameter> parameter of main().
1082 * Any parameters understood by gtk_init() are stripped before return.
1084 * Call this function before using any other GTK+ functions in your GUI
1085 * applications. It will initialize everything needed to operate the
1086 * toolkit and parses some standard command line options. @argc and
1087 * @argv are adjusted accordingly so your own code will
1088 * never see those standard arguments.
1090 * Note that there are some alternative ways to initialize GTK+:
1091 * if you are calling gtk_parse_args(), gtk_init_check(),
1092 * gtk_init_with_args() or g_option_context_parse() with
1093 * the option group returned by gtk_get_option_group(), you
1094 * <emphasis>don't</emphasis> have to call gtk_init().
1097 * This function will terminate your program if it was unable to initialize
1098 * the GUI for some reason. If you want your program to fall back to a
1099 * textual interface you want to call gtk_init_check() instead.
1103 * Since 2.18, GTK+ calls <literal>signal (SIGPIPE, SIG_IGN)</literal>
1104 * during initialization, to ignore SIGPIPE signals, since these are
1105 * almost never wanted in graphical applications. If you do need to
1106 * handle SIGPIPE for some reason, reset the handler after gtk_init(),
1107 * but notice that other libraries (e.g. libdbus or gvfs) might do
1112 gtk_init (int *argc, char ***argv)
1114 if (!gtk_init_check (argc, argv))
1116 const char *display_name_arg = gdk_get_display_arg_name ();
1117 if (display_name_arg == NULL)
1118 display_name_arg = getenv("DISPLAY");
1119 g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : "");
1124 #ifdef G_PLATFORM_WIN32
1127 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
1129 if (sizeof_GtkWindow != sizeof (GtkWindow))
1130 g_error ("Incompatible build!\n"
1131 "The code using GTK+ thinks GtkWindow is of different\n"
1132 "size than it actually is in this build of GTK+.\n"
1133 "On Windows, this probably means that you have compiled\n"
1134 "your code with gcc without the -mms-bitfields switch,\n"
1135 "or that you are using an unsupported compiler.");
1138 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
1139 * gcc-compiled code on Win32 whether compiled with -fnative-struct or
1140 * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
1141 * from GTK+ 2.0.2 on, check some other struct, too, where the use of
1142 * -fnative-struct still matters. GtkBox is one such.
1145 check_sizeof_GtkBox (size_t sizeof_GtkBox)
1147 if (sizeof_GtkBox != sizeof (GtkBox))
1148 g_error ("Incompatible build!\n"
1149 "The code using GTK+ thinks GtkBox is of different\n"
1150 "size than it actually is in this build of GTK+.\n"
1151 "On Windows, this probably means that you have compiled\n"
1152 "your code with gcc without the -mms-bitfields switch,\n"
1153 "or that you are using an unsupported compiler.");
1156 /* These two functions might get more checks added later, thus pass
1157 * in the number of extra args.
1160 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1162 check_sizeof_GtkWindow (sizeof_GtkWindow);
1163 if (num_checks >= 2)
1164 check_sizeof_GtkBox (sizeof_GtkBox);
1165 gtk_init (argc, argv);
1169 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
1171 check_sizeof_GtkWindow (sizeof_GtkWindow);
1172 if (num_checks >= 2)
1173 check_sizeof_GtkBox (sizeof_GtkBox);
1174 return gtk_init_check (argc, argv);
1182 * Initializes internationalization support for GTK+. gtk_init()
1183 * automatically does this, so there is typically no point
1184 * in calling this function.
1186 * If you are calling this function because you changed the locale
1187 * after GTK+ is was initialized, then calling this function
1188 * may help a bit. (Note, however, that changing the locale
1189 * after GTK+ is initialized may produce inconsistent results and
1190 * is not really supported.)
1192 * In detail - sets the current locale according to the
1193 * program environment. This is the same as calling the C library function
1194 * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the
1195 * locale specific setup of the windowing system used by GDK.
1197 * Returns: a string corresponding to the locale set, typically in the
1198 * form lang_COUNTRY, where lang is an ISO-639 language code, and
1199 * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
1200 * result of the setlocale(); it is also used on other machines, such as
1201 * Windows, where the C library returns a different result. The string is
1202 * owned by GTK+ and should not be modified or freed.
1205 gtk_set_locale (void)
1207 return gdk_set_locale ();
1211 * _gtk_get_lc_ctype:
1213 * Return the Unix-style locale string for the language currently in
1214 * effect. On Unix systems, this is the return value from
1215 * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
1216 * affect this through the environment variables LC_ALL, LC_CTYPE or
1217 * LANG (checked in that order). The locale strings typically is in
1218 * the form lang_COUNTRY, where lang is an ISO-639 language code, and
1219 * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
1220 * Swedish as written in Finland or pt_BR for Portuguese as written in
1223 * On Windows, the C library doesn't use any such environment
1224 * variables, and setting them won't affect the behaviour of functions
1225 * like ctime(). The user sets the locale through the Regional Options
1226 * in the Control Panel. The C library (in the setlocale() function)
1227 * does not use country and language codes, but country and language
1228 * names spelled out in English.
1229 * However, this function does check the above environment
1230 * variables, and does return a Unix-style locale string based on
1231 * either said environment variables or the thread's current locale.
1233 * Return value: a dynamically allocated string, free with g_free().
1237 _gtk_get_lc_ctype (void)
1240 /* Somebody might try to set the locale for this process using the
1241 * LANG or LC_ environment variables. The Microsoft C library
1242 * doesn't know anything about them. You set the locale in the
1243 * Control Panel. Setting these env vars won't have any affect on
1244 * locale-dependent C library functions like ctime(). But just for
1245 * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
1246 * it easier to test GTK and Pango in various default languages, you
1247 * don't have to clickety-click in the Control Panel, you can simply
1248 * start the program with LC_ALL=something on the command line.)
1252 p = getenv ("LC_ALL");
1254 return g_strdup (p);
1256 p = getenv ("LC_CTYPE");
1258 return g_strdup (p);
1260 p = getenv ("LANG");
1262 return g_strdup (p);
1264 return g_win32_getlocale ();
1266 return g_strdup (setlocale (LC_CTYPE, NULL));
1271 * gtk_get_default_language:
1273 * Returns the #PangoLanguage for the default language currently in
1274 * effect. (Note that this can change over the life of an
1275 * application.) The default language is derived from the current
1276 * locale. It determines, for example, whether GTK+ uses the
1277 * right-to-left or left-to-right text direction.
1279 * This function is equivalent to pango_language_get_default(). See
1280 * that function for details.
1282 * Return value: the default language as a #PangoLanguage, must not be
1286 gtk_get_default_language (void)
1288 return pango_language_get_default ();
1296 GtkInitFunction *init;
1299 gtk_main_loop_level++;
1301 loop = g_main_loop_new (NULL, TRUE);
1302 main_loops = g_slist_prepend (main_loops, loop);
1304 tmp_list = functions = init_functions;
1305 init_functions = NULL;
1309 init = tmp_list->data;
1310 tmp_list = tmp_list->next;
1312 (* init->function) (init->data);
1315 g_list_free (functions);
1317 if (g_main_loop_is_running (main_loops->data))
1319 GDK_THREADS_LEAVE ();
1320 g_main_loop_run (loop);
1321 GDK_THREADS_ENTER ();
1327 GList *reinvoke_list = NULL;
1328 GtkQuitFunction *quitf;
1330 while (quit_functions)
1332 quitf = quit_functions->data;
1334 tmp_list = quit_functions;
1335 quit_functions = g_list_remove_link (quit_functions, quit_functions);
1336 g_list_free_1 (tmp_list);
1338 if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
1339 gtk_quit_invoke_function (quitf))
1341 reinvoke_list = g_list_prepend (reinvoke_list, quitf);
1345 gtk_quit_destroy (quitf);
1352 work = g_list_last (reinvoke_list);
1354 quit_functions->prev = work;
1355 work->next = quit_functions;
1356 quit_functions = work;
1362 main_loops = g_slist_remove (main_loops, loop);
1364 g_main_loop_unref (loop);
1366 gtk_main_loop_level--;
1368 if (gtk_main_loop_level == 0)
1370 /* Try storing all clipboard data we have */
1371 _gtk_clipboard_store_all ();
1373 /* Synchronize the recent manager singleton */
1374 _gtk_recent_manager_sync ();
1379 gtk_main_level (void)
1381 return gtk_main_loop_level;
1385 gtk_main_quit (void)
1387 g_return_if_fail (main_loops != NULL);
1389 g_main_loop_quit (main_loops->data);
1393 gtk_events_pending (void)
1397 GDK_THREADS_LEAVE ();
1398 result = g_main_context_pending (NULL);
1399 GDK_THREADS_ENTER ();
1405 gtk_main_iteration (void)
1407 GDK_THREADS_LEAVE ();
1408 g_main_context_iteration (NULL, TRUE);
1409 GDK_THREADS_ENTER ();
1412 return !g_main_loop_is_running (main_loops->data);
1418 gtk_main_iteration_do (gboolean blocking)
1420 GDK_THREADS_LEAVE ();
1421 g_main_context_iteration (NULL, blocking);
1422 GDK_THREADS_ENTER ();
1425 return !g_main_loop_is_running (main_loops->data);
1430 /* private libgtk to libgdk interfaces
1432 gboolean gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1434 GdkWindow **grab_window,
1435 gboolean *owner_events);
1438 rewrite_events_translate (GdkWindow *old_window,
1439 GdkWindow *new_window,
1443 gint old_origin_x, old_origin_y;
1444 gint new_origin_x, new_origin_y;
1446 gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1447 gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1449 *x += old_origin_x - new_origin_x;
1450 *y += old_origin_y - new_origin_y;
1454 rewrite_event_for_window (GdkEvent *event,
1455 GdkWindow *new_window)
1457 event = gdk_event_copy (event);
1459 switch (event->type)
1462 rewrite_events_translate (event->any.window,
1464 &event->scroll.x, &event->scroll.y);
1466 case GDK_BUTTON_PRESS:
1467 case GDK_2BUTTON_PRESS:
1468 case GDK_3BUTTON_PRESS:
1469 case GDK_BUTTON_RELEASE:
1470 rewrite_events_translate (event->any.window,
1472 &event->button.x, &event->button.y);
1474 case GDK_MOTION_NOTIFY:
1475 rewrite_events_translate (event->any.window,
1477 &event->motion.x, &event->motion.y);
1480 case GDK_KEY_RELEASE:
1481 case GDK_PROXIMITY_IN:
1482 case GDK_PROXIMITY_OUT:
1489 g_object_unref (event->any.window);
1490 event->any.window = g_object_ref (new_window);
1495 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1496 * then what X11 does is deliver the event normally if it was going to this
1497 * client, otherwise, delivers it in terms of the grab window. This function
1498 * rewrites events to the effect that events going to the same window group
1499 * are delivered normally, otherwise, the event is delivered in terms of the
1503 rewrite_event_for_grabs (GdkEvent *event)
1505 GdkWindow *grab_window;
1506 GtkWidget *event_widget, *grab_widget;
1507 gpointer grab_widget_ptr;
1508 gboolean owner_events;
1509 GdkDisplay *display;
1512 switch (event->type)
1515 case GDK_BUTTON_PRESS:
1516 case GDK_2BUTTON_PRESS:
1517 case GDK_3BUTTON_PRESS:
1518 case GDK_BUTTON_RELEASE:
1519 case GDK_MOTION_NOTIFY:
1520 case GDK_PROXIMITY_IN:
1521 case GDK_PROXIMITY_OUT:
1523 case GDK_KEY_RELEASE:
1524 display = gdk_drawable_get_display (event->any.window);
1525 device = gdk_event_get_device (event);
1527 if (!gdk_device_grab_info_libgtk_only (display, device, &grab_window, &owner_events) ||
1535 event_widget = gtk_get_event_widget (event);
1536 gdk_window_get_user_data (grab_window, &grab_widget_ptr);
1537 grab_widget = grab_widget_ptr;
1540 gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1541 return rewrite_event_for_window (event, grab_window);
1547 gtk_main_do_event (GdkEvent *event)
1549 GtkWidget *event_widget;
1550 GtkWidget *grab_widget = NULL;
1551 GtkWindowGroup *window_group;
1552 GdkEvent *rewritten_event = NULL;
1556 if (event->type == GDK_SETTING)
1558 _gtk_settings_handle_event (&event->setting);
1562 if (event->type == GDK_OWNER_CHANGE)
1564 _gtk_clipboard_handle_event (&event->owner_change);
1568 /* Find the widget which got the event. We store the widget
1569 * in the user_data field of GdkWindow's.
1570 * Ignore the event if we don't have a widget for it, except
1571 * for GDK_PROPERTY_NOTIFY events which are handled specialy.
1572 * Though this happens rarely, bogus events can occour
1573 * for e.g. destroyed GdkWindows.
1575 event_widget = gtk_get_event_widget (event);
1578 /* To handle selection INCR transactions, we select
1579 * PropertyNotify events on the requestor window and create
1580 * a corresponding (fake) GdkWindow so that events get
1581 * here. There won't be a widget though, so we have to handle
1584 if (event->type == GDK_PROPERTY_NOTIFY)
1585 _gtk_selection_incr_event (event->any.window,
1591 /* If pointer or keyboard grabs are in effect, munge the events
1592 * so that each window group looks like a separate app.
1594 rewritten_event = rewrite_event_for_grabs (event);
1595 if (rewritten_event)
1597 event = rewritten_event;
1598 event_widget = gtk_get_event_widget (event);
1601 window_group = gtk_main_get_window_group (event_widget);
1602 device = gdk_event_get_device (event);
1604 /* check whether there is a (device) grab in effect...
1607 grab_widget = gtk_window_group_get_current_device_grab (window_group, device);
1610 grab_widget = gtk_window_group_get_current_grab (window_group);
1612 /* If the grab widget is an ancestor of the event widget
1613 * then we send the event to the original event widget.
1614 * This is the key to implementing modality.
1617 (gtk_widget_is_sensitive (event_widget) &&
1618 gtk_widget_is_ancestor (event_widget, grab_widget)))
1619 grab_widget = event_widget;
1621 /* If the widget receiving events is actually blocked by another device GTK+ grab */
1623 _gtk_window_group_widget_is_blocked_for_device (window_group, grab_widget, device))
1625 if (rewritten_event)
1626 gdk_event_free (rewritten_event);
1631 /* Push the event onto a stack of current events for
1632 * gtk_current_event_get().
1634 current_events = g_list_prepend (current_events, event);
1636 /* Not all events get sent to the grabbing widget.
1637 * The delete, destroy, expose, focus change and resize
1638 * events still get sent to the event widget because
1639 * 1) these events have no meaning for the grabbing widget
1640 * and 2) redirecting these events to the grabbing widget
1641 * could cause the display to be messed up.
1643 * Drag events are also not redirected, since it isn't
1644 * clear what the semantics of that would be.
1646 switch (event->type)
1652 g_object_ref (event_widget);
1653 grab_widget = gtk_window_group_get_current_grab (window_group);
1654 if ((!grab_widget || gtk_widget_get_toplevel (grab_widget) == event_widget) &&
1655 !gtk_widget_event (event_widget, event))
1656 gtk_widget_destroy (event_widget);
1657 g_object_unref (event_widget);
1661 /* Unexpected GDK_DESTROY from the outside, ignore for
1662 * child windows, handle like a GDK_DELETE for toplevels
1664 if (!gtk_widget_get_parent (event_widget))
1666 g_object_ref (event_widget);
1667 if (!gtk_widget_event (event_widget, event) &&
1668 gtk_widget_get_realized (event_widget))
1669 gtk_widget_destroy (event_widget);
1670 g_object_unref (event_widget);
1675 if (event->any.window && gtk_widget_get_double_buffered (event_widget))
1677 gdk_window_begin_paint_region (event->any.window, event->expose.region);
1678 gtk_widget_send_expose (event_widget, event);
1679 gdk_window_end_paint (event->any.window);
1683 /* The app may paint with a previously allocated cairo_t,
1684 which will draw directly to the window. We can't catch cairo
1685 drap operatoins to automatically flush the window, thus we
1686 need to explicitly flush any outstanding moves or double
1688 gdk_window_flush (event->any.window);
1689 gtk_widget_send_expose (event_widget, event);
1693 case GDK_PROPERTY_NOTIFY:
1695 case GDK_FOCUS_CHANGE:
1699 case GDK_SELECTION_CLEAR:
1700 case GDK_SELECTION_REQUEST:
1701 case GDK_SELECTION_NOTIFY:
1702 case GDK_CLIENT_EVENT:
1703 case GDK_VISIBILITY_NOTIFY:
1704 case GDK_WINDOW_STATE:
1705 case GDK_GRAB_BROKEN:
1707 gtk_widget_event (event_widget, event);
1711 case GDK_BUTTON_PRESS:
1712 case GDK_2BUTTON_PRESS:
1713 case GDK_3BUTTON_PRESS:
1714 gtk_propagate_event (grab_widget, event);
1718 case GDK_KEY_RELEASE:
1721 if (gtk_invoke_key_snoopers (grab_widget, event))
1724 /* Catch alt press to enable auto-mnemonics;
1725 * menus are handled elsewhere
1727 if ((event->key.keyval == GDK_KEY_Alt_L || event->key.keyval == GDK_KEY_Alt_R) &&
1728 !GTK_IS_MENU_SHELL (grab_widget))
1730 gboolean auto_mnemonics;
1732 g_object_get (gtk_widget_get_settings (grab_widget),
1733 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
1737 gboolean mnemonics_visible;
1740 mnemonics_visible = (event->type == GDK_KEY_PRESS);
1742 window = gtk_widget_get_toplevel (grab_widget);
1744 if (GTK_IS_WINDOW (window))
1745 gtk_window_set_mnemonics_visible (GTK_WINDOW (window), mnemonics_visible);
1748 /* else fall through */
1749 case GDK_MOTION_NOTIFY:
1750 case GDK_BUTTON_RELEASE:
1751 case GDK_PROXIMITY_IN:
1752 case GDK_PROXIMITY_OUT:
1753 gtk_propagate_event (grab_widget, event);
1756 case GDK_ENTER_NOTIFY:
1757 _gtk_widget_set_device_window (event_widget,
1758 gdk_event_get_device (event),
1760 if (gtk_widget_is_sensitive (grab_widget))
1761 gtk_widget_event (grab_widget, event);
1764 case GDK_LEAVE_NOTIFY:
1765 _gtk_widget_set_device_window (event_widget,
1766 gdk_event_get_device (event),
1768 if (gtk_widget_is_sensitive (grab_widget))
1769 gtk_widget_event (grab_widget, event);
1772 case GDK_DRAG_STATUS:
1773 case GDK_DROP_FINISHED:
1774 _gtk_drag_source_handle_event (event_widget, event);
1776 case GDK_DRAG_ENTER:
1777 case GDK_DRAG_LEAVE:
1778 case GDK_DRAG_MOTION:
1779 case GDK_DROP_START:
1780 _gtk_drag_dest_handle_event (event_widget, event);
1783 g_assert_not_reached ();
1787 if (event->type == GDK_ENTER_NOTIFY
1788 || event->type == GDK_LEAVE_NOTIFY
1789 || event->type == GDK_BUTTON_PRESS
1790 || event->type == GDK_2BUTTON_PRESS
1791 || event->type == GDK_3BUTTON_PRESS
1792 || event->type == GDK_KEY_PRESS
1793 || event->type == GDK_DRAG_ENTER
1794 || event->type == GDK_GRAB_BROKEN
1795 || event->type == GDK_MOTION_NOTIFY
1796 || event->type == GDK_SCROLL)
1798 _gtk_tooltip_handle_event (event);
1801 tmp_list = current_events;
1802 current_events = g_list_remove_link (current_events, tmp_list);
1803 g_list_free_1 (tmp_list);
1805 if (rewritten_event)
1806 gdk_event_free (rewritten_event);
1821 static GtkWindowGroup *
1822 gtk_main_get_window_group (GtkWidget *widget)
1824 GtkWidget *toplevel = NULL;
1827 toplevel = gtk_widget_get_toplevel (widget);
1829 if (GTK_IS_WINDOW (toplevel))
1830 return gtk_window_get_group (GTK_WINDOW (toplevel));
1832 return gtk_window_get_group (NULL);
1837 GtkWidget *old_grab_widget;
1838 GtkWidget *new_grab_widget;
1839 gboolean was_grabbed;
1840 gboolean is_grabbed;
1842 GList *notified_windows;
1847 synth_crossing_for_grab_notify (GtkWidget *from,
1849 GrabNotifyInfo *info,
1851 GdkCrossingMode mode)
1855 GdkDevice *device = devices->data;
1856 GdkWindow *from_window, *to_window;
1858 /* Do not propagate events more than once to
1859 * the same windows if non-multidevice aware.
1865 from_window = _gtk_widget_get_device_window (from, device);
1868 !gdk_window_get_support_multidevice (from_window) &&
1869 g_list_find (info->notified_windows, from_window))
1877 to_window = _gtk_widget_get_device_window (to, device);
1880 !gdk_window_get_support_multidevice (to_window) &&
1881 g_list_find (info->notified_windows, to_window))
1885 if (from_window || to_window)
1887 _gtk_widget_synthesize_crossing ((from_window) ? from : NULL,
1888 (to_window) ? to : NULL,
1892 info->notified_windows = g_list_prepend (info->notified_windows, from_window);
1895 info->notified_windows = g_list_prepend (info->notified_windows, to_window);
1898 devices = devices->next;
1903 gtk_grab_notify_foreach (GtkWidget *child,
1906 GrabNotifyInfo *info = data;
1907 gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
1910 was_grabbed = info->was_grabbed;
1911 is_grabbed = info->is_grabbed;
1913 info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
1914 info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
1916 was_shadowed = info->old_grab_widget && !info->was_grabbed;
1917 is_shadowed = info->new_grab_widget && !info->is_grabbed;
1919 g_object_ref (child);
1921 if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
1922 gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1925 _gtk_widget_get_device_window (child, info->device))
1927 /* Device specified and is on widget */
1928 devices = g_list_prepend (NULL, info->device);
1931 devices = _gtk_widget_list_devices (child);
1935 GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
1936 if (!was_shadowed && devices &&
1937 gtk_widget_is_sensitive (child))
1938 synth_crossing_for_grab_notify (child, info->new_grab_widget,
1940 GDK_CROSSING_GTK_GRAB);
1944 GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
1945 if (was_shadowed && devices &&
1946 gtk_widget_is_sensitive (child))
1947 synth_crossing_for_grab_notify (info->old_grab_widget, child,
1949 info->from_grab ? GDK_CROSSING_GTK_GRAB :
1950 GDK_CROSSING_GTK_UNGRAB);
1953 if (was_shadowed != is_shadowed)
1954 _gtk_widget_grab_notify (child, was_shadowed);
1956 g_object_unref (child);
1957 g_list_free (devices);
1959 info->was_grabbed = was_grabbed;
1960 info->is_grabbed = is_grabbed;
1964 gtk_grab_notify (GtkWindowGroup *group,
1966 GtkWidget *old_grab_widget,
1967 GtkWidget *new_grab_widget,
1971 GrabNotifyInfo info = { 0 };
1973 if (old_grab_widget == new_grab_widget)
1976 info.old_grab_widget = old_grab_widget;
1977 info.new_grab_widget = new_grab_widget;
1978 info.from_grab = from_grab;
1979 info.device = device;
1981 g_object_ref (group);
1983 toplevels = gtk_window_list_toplevels ();
1984 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1988 GtkWindow *toplevel = toplevels->data;
1989 toplevels = g_list_delete_link (toplevels, toplevels);
1991 info.was_grabbed = FALSE;
1992 info.is_grabbed = FALSE;
1994 if (group == gtk_window_get_group (toplevel))
1995 gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
1996 g_object_unref (toplevel);
1999 g_list_free (info.notified_windows);
2000 g_object_unref (group);
2004 gtk_grab_add (GtkWidget *widget)
2006 GtkWindowGroup *group;
2007 GtkWidget *old_grab_widget;
2009 g_return_if_fail (widget != NULL);
2011 if (!gtk_widget_has_grab (widget) && gtk_widget_is_sensitive (widget))
2013 _gtk_widget_set_has_grab (widget, TRUE);
2015 group = gtk_main_get_window_group (widget);
2017 old_grab_widget = gtk_window_group_get_current_grab (group);
2019 g_object_ref (widget);
2020 //group->grabs = g_slist_prepend (group->grabs, widget);
2022 gtk_grab_notify (group, NULL, old_grab_widget, widget, TRUE);
2027 gtk_grab_get_current (void)
2029 GtkWindowGroup *group;
2031 group = gtk_main_get_window_group (NULL);
2033 return gtk_window_group_get_current_grab (group);
2037 gtk_grab_remove (GtkWidget *widget)
2039 GtkWindowGroup *group;
2040 GtkWidget *new_grab_widget;
2042 g_return_if_fail (widget != NULL);
2044 if (gtk_widget_has_grab (widget))
2046 _gtk_widget_set_has_grab (widget, FALSE);
2048 group = gtk_main_get_window_group (widget);
2049 //group->grabs = g_slist_remove (group->grabs, widget);
2051 new_grab_widget = gtk_window_group_get_current_grab (group);
2053 gtk_grab_notify (group, NULL, widget, new_grab_widget, FALSE);
2055 g_object_unref (widget);
2060 * gtk_device_grab_add:
2061 * @widget: a #GtkWidget
2062 * @device: a #GtkDevice to grab on.
2063 * @block_others: %TRUE to prevent other devices to interact with @widget.
2065 * Adds a GTK+ grab on @device, so all the events on @device and its
2066 * associated pointer or keyboard (if any) are delivered to @widget.
2067 * If the @block_others parameter is %TRUE, any other devices will be
2068 * unable to interact with @widget during the grab.
2073 gtk_device_grab_add (GtkWidget *widget,
2075 gboolean block_others)
2077 GtkWindowGroup *group;
2078 GtkWidget *old_grab_widget;
2080 g_return_if_fail (GTK_IS_WIDGET (widget));
2081 g_return_if_fail (GDK_IS_DEVICE (device));
2083 group = gtk_main_get_window_group (widget);
2084 old_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2086 if (old_grab_widget != widget)
2087 _gtk_window_group_add_device_grab (group, widget, device, block_others);
2089 gtk_grab_notify (group, device, old_grab_widget, widget, TRUE);
2093 * gtk_device_grab_remove:
2094 * @widget: a #GtkWidget
2095 * @device: a #GdkDevice
2097 * Removes a device grab from the given widget. You have to pair calls
2098 * to gtk_device_grab_add() and gtk_device_grab_remove().
2103 gtk_device_grab_remove (GtkWidget *widget,
2106 GtkWindowGroup *group;
2107 GtkWidget *new_grab_widget;
2109 g_return_if_fail (GTK_IS_WIDGET (widget));
2110 g_return_if_fail (GDK_IS_DEVICE (device));
2112 group = gtk_main_get_window_group (widget);
2113 _gtk_window_group_remove_device_grab (group, widget, device);
2114 new_grab_widget = gtk_window_group_get_current_device_grab (group, device);
2116 gtk_grab_notify (group, device, widget, new_grab_widget, FALSE);
2120 gtk_init_add (GtkFunction function,
2123 GtkInitFunction *init;
2125 init = g_new (GtkInitFunction, 1);
2126 init->function = function;
2129 init_functions = g_list_prepend (init_functions, init);
2133 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
2136 GtkKeySnooperData *data;
2137 static guint snooper_id = 1;
2139 g_return_val_if_fail (snooper != NULL, 0);
2141 data = g_new (GtkKeySnooperData, 1);
2142 data->func = snooper;
2143 data->func_data = func_data;
2144 data->id = snooper_id++;
2145 key_snoopers = g_slist_prepend (key_snoopers, data);
2151 gtk_key_snooper_remove (guint snooper_id)
2153 GtkKeySnooperData *data = NULL;
2156 slist = key_snoopers;
2160 if (data->id == snooper_id)
2163 slist = slist->next;
2168 key_snoopers = g_slist_remove (key_snoopers, data);
2174 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
2178 gint return_val = FALSE;
2180 slist = key_snoopers;
2181 while (slist && !return_val)
2183 GtkKeySnooperData *data;
2186 slist = slist->next;
2187 return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
2194 gtk_quit_add_full (guint main_level,
2195 GtkFunction function,
2196 GtkCallbackMarshal marshal,
2198 GDestroyNotify destroy)
2200 static guint quit_id = 1;
2201 GtkQuitFunction *quitf;
2203 g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
2205 quitf = g_slice_new (GtkQuitFunction);
2207 quitf->id = quit_id++;
2208 quitf->main_level = main_level;
2209 quitf->function = function;
2210 quitf->marshal = marshal;
2212 quitf->destroy = destroy;
2214 quit_functions = g_list_prepend (quit_functions, quitf);
2220 gtk_quit_destroy (GtkQuitFunction *quitf)
2223 quitf->destroy (quitf->data);
2224 g_slice_free (GtkQuitFunction, quitf);
2228 gtk_quit_destructor (GtkObject **object_p)
2231 gtk_object_destroy (*object_p);
2238 gtk_quit_add_destroy (guint main_level,
2241 GtkObject **object_p;
2243 g_return_if_fail (main_level > 0);
2244 g_return_if_fail (GTK_IS_OBJECT (object));
2246 object_p = g_new (GtkObject*, 1);
2248 g_signal_connect (object,
2250 G_CALLBACK (gtk_widget_destroyed),
2252 gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
2256 gtk_quit_add (guint main_level,
2257 GtkFunction function,
2260 return gtk_quit_add_full (main_level, function, NULL, data, NULL);
2264 gtk_quit_remove (guint id)
2266 GtkQuitFunction *quitf;
2269 tmp_list = quit_functions;
2272 quitf = tmp_list->data;
2274 if (quitf->id == id)
2276 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2277 g_list_free (tmp_list);
2278 gtk_quit_destroy (quitf);
2283 tmp_list = tmp_list->next;
2288 gtk_quit_remove_by_data (gpointer data)
2290 GtkQuitFunction *quitf;
2293 tmp_list = quit_functions;
2296 quitf = tmp_list->data;
2298 if (quitf->data == data)
2300 quit_functions = g_list_remove_link (quit_functions, tmp_list);
2301 g_list_free (tmp_list);
2302 gtk_quit_destroy (quitf);
2307 tmp_list = tmp_list->next;
2312 * gtk_get_current_event:
2314 * Obtains a copy of the event currently being processed by GTK+. For
2315 * example, if you get a "clicked" signal from #GtkButton, the current
2316 * event will be the #GdkEventButton that triggered the "clicked"
2317 * signal. The returned event must be freed with gdk_event_free().
2318 * If there is no current event, the function returns %NULL.
2320 * Return value: a copy of the current event, or %NULL if no current event.
2323 gtk_get_current_event (void)
2326 return gdk_event_copy (current_events->data);
2332 * gtk_get_current_event_time:
2334 * If there is a current event and it has a timestamp, return that
2335 * timestamp, otherwise return %GDK_CURRENT_TIME.
2337 * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
2340 gtk_get_current_event_time (void)
2343 return gdk_event_get_time (current_events->data);
2345 return GDK_CURRENT_TIME;
2349 * gtk_get_current_event_state:
2350 * @state: a location to store the state of the current event
2352 * If there is a current event and it has a state field, place
2353 * that state field in @state and return %TRUE, otherwise return
2356 * Return value: %TRUE if there was a current event and it had a state field
2359 gtk_get_current_event_state (GdkModifierType *state)
2361 g_return_val_if_fail (state != NULL, FALSE);
2364 return gdk_event_get_state (current_events->data, state);
2373 * gtk_get_current_event_device:
2375 * If there is a current event and it has a device, return that
2376 * device, otherwise return %NULL.
2378 * Returns: a #GdkDevice, or %NULL
2381 gtk_get_current_event_device (void)
2384 return gdk_event_get_device (current_events->data);
2390 * gtk_get_event_widget:
2391 * @event: a #GdkEvent
2393 * If @event is %NULL or the event was not associated with any widget,
2394 * returns %NULL, otherwise returns the widget that received the event
2397 * Return value: the widget that originally received @event, or %NULL
2400 gtk_get_event_widget (GdkEvent *event)
2403 gpointer widget_ptr;
2406 if (event && event->any.window &&
2407 (event->type == GDK_DESTROY || !GDK_WINDOW_DESTROYED (event->any.window)))
2409 gdk_window_get_user_data (event->any.window, &widget_ptr);
2410 widget = widget_ptr;
2417 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2419 if (!quitf->marshal)
2420 return quitf->function (quitf->data);
2424 gint ret_val = FALSE;
2426 args[0].name = NULL;
2427 args[0].type = G_TYPE_BOOLEAN;
2428 args[0].d.pointer_data = &ret_val;
2429 ((GtkCallbackMarshal) quitf->marshal) (NULL,
2437 * gtk_propagate_event:
2438 * @widget: a #GtkWidget
2441 * Sends an event to a widget, propagating the event to parent widgets
2442 * if the event remains unhandled. Events received by GTK+ from GDK
2443 * normally begin in gtk_main_do_event(). Depending on the type of
2444 * event, existence of modal dialogs, grabs, etc., the event may be
2445 * propagated; if so, this function is used. gtk_propagate_event()
2446 * calls gtk_widget_event() on each widget it decides to send the
2447 * event to. So gtk_widget_event() is the lowest-level function; it
2448 * simply emits the "event" and possibly an event-specific signal on a
2449 * widget. gtk_propagate_event() is a bit higher-level, and
2450 * gtk_main_do_event() is the highest level.
2452 * All that said, you most likely don't want to use any of these
2453 * functions; synthesizing events is rarely needed. Consider asking on
2454 * the mailing list for better ways to achieve your goals. For
2455 * example, use gdk_window_invalidate_rect() or
2456 * gtk_widget_queue_draw() instead of making up expose events.
2460 gtk_propagate_event (GtkWidget *widget,
2465 g_return_if_fail (GTK_IS_WIDGET (widget));
2466 g_return_if_fail (event != NULL);
2468 handled_event = FALSE;
2470 g_object_ref (widget);
2472 if ((event->type == GDK_KEY_PRESS) ||
2473 (event->type == GDK_KEY_RELEASE))
2475 /* Only send key events within Window widgets to the Window
2476 * The Window widget will in turn pass the
2477 * key event on to the currently focused widget
2482 window = gtk_widget_get_toplevel (widget);
2483 if (GTK_IS_WINDOW (window))
2485 /* If there is a grab within the window, give the grab widget
2486 * a first crack at the key event
2488 if (widget != window && gtk_widget_has_grab (widget))
2489 handled_event = gtk_widget_event (widget, event);
2493 window = gtk_widget_get_toplevel (widget);
2494 if (GTK_IS_WINDOW (window))
2496 if (gtk_widget_is_sensitive (window))
2497 gtk_widget_event (window, event);
2501 handled_event = TRUE; /* don't send to widget */
2505 /* Other events get propagated up the widget tree
2506 * so that parents can see the button and motion
2507 * events of the children.
2515 /* Scroll events are special cased here because it
2516 * feels wrong when scrolling a GtkViewport, say,
2517 * to have children of the viewport eat the scroll
2520 if (!gtk_widget_is_sensitive (widget))
2521 handled_event = event->type != GDK_SCROLL;
2523 handled_event = gtk_widget_event (widget, event);
2525 tmp = gtk_widget_get_parent (widget);
2526 g_object_unref (widget);
2530 if (!handled_event && widget)
2531 g_object_ref (widget);
2537 g_object_unref (widget);
2541 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2542 GValue *return_accu,
2543 const GValue *handler_return,
2546 gboolean continue_emission;
2547 gboolean signal_handled;
2549 signal_handled = g_value_get_boolean (handler_return);
2550 g_value_set_boolean (return_accu, signal_handled);
2551 continue_emission = !signal_handled;
2553 return continue_emission;