#include "gtkwidget.h"
#include "gtkwindow.h"
#include "gtkprivate.h"
-#include "gdk/gdki18n.h"
#include "config.h"
#include "gtkdebug.h"
#include "gtkintl.h"
guint id;
};
-static void gtk_exit_func (void);
static gint gtk_quit_invoke_function (GtkQuitFunction *quitf);
static void gtk_quit_destroy (GtkQuitFunction *quitf);
static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
{"plugsocket", GTK_DEBUG_PLUGSOCKET},
{"text", GTK_DEBUG_TEXT},
{"tree", GTK_DEBUG_TREE},
- {"updates", GTK_DEBUG_UPDATES}
+ {"updates", GTK_DEBUG_UPDATES},
+ {"keybindings", GTK_DEBUG_KEYBINDINGS}
};
static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
static gchar **
get_module_path (void)
{
- const gchar *module_path_env = g_getenv ("GTK_MODULE_PATH");
- const gchar *exe_prefix = g_getenv ("GTK_EXE_PREFIX");
- gchar **result;
+ const gchar *module_path_env;
+ const gchar *exe_prefix;
+ const gchar *home_dir;
+ gchar *home_gtk_dir = NULL;
gchar *module_path;
gchar *default_dir;
+ static gchar **result = NULL;
+
+ if (result)
+ return result;
+
+ home_dir = g_get_home_dir();
+ if (home_dir)
+ home_gtk_dir = g_build_filename (home_dir, ".gtk-2.0", NULL);
+
+ module_path_env = g_getenv ("GTK_PATH");
+ exe_prefix = g_getenv ("GTK_EXE_PREFIX");
if (exe_prefix)
- default_dir = g_build_filename (exe_prefix, "lib", "gtk-2.0", "modules", NULL);
+ default_dir = g_build_filename (exe_prefix, "lib", "gtk-2.0", NULL);
+ else
+ default_dir = g_build_filename (GTK_LIBDIR, "gtk-2.0", NULL);
+
+ if (module_path_env && home_gtk_dir)
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ module_path_env, home_gtk_dir, default_dir, NULL);
+ else if (module_path_env)
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ module_path_env, default_dir, NULL);
+ else if (home_gtk_dir)
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ home_gtk_dir, default_dir, NULL);
else
- default_dir = g_build_filename (GTK_LIBDIR, "gtk-2.0", "modules", NULL);
+ module_path = g_build_path (G_SEARCHPATH_SEPARATOR_S,
+ default_dir, NULL);
- module_path = g_strconcat (module_path_env ? module_path_env : "",
- module_path_env ? G_SEARCHPATH_SEPARATOR_S : "",
- default_dir, NULL);
+ g_free (home_gtk_dir);
+ g_free (default_dir);
result = pango_split_file_list (module_path);
-
- g_free (default_dir);
g_free (module_path);
return result;
}
-static GModule *
-find_module (gchar **module_path,
- const gchar *name)
+/**
+ * _gtk_get_module_path:
+ * @type: the type of the module, for instance 'modules', 'engines', immodules'
+ *
+ * Determines the search path for a particular type of module.
+ *
+ * Return value: the search path for the module type. Free with g_strfreev().
+ **/
+gchar **
+_gtk_get_module_path (const gchar *type)
{
- GModule *module;
- gchar *module_name;
- gint i;
+ gchar **paths = get_module_path();
+ gchar **path;
+ gchar **result;
+ gint count = 0;
- if (g_path_is_absolute (name))
- return g_module_open (name, G_MODULE_BIND_LAZY);
+ for (path = paths; *path; path++)
+ count++;
- for (i = 0; module_path[i]; i++)
- {
- gchar *version_directory;
+ result = g_new (gchar *, count * 4 + 1);
- version_directory = g_build_filename (module_path[i], GTK_BINARY_VERSION, NULL);
- module_name = g_module_build_path (version_directory, name);
- g_free (version_directory);
-
- if (g_file_test (module_name, G_FILE_TEST_EXISTS))
- {
- module = g_module_open (module_name, G_MODULE_BIND_LAZY);
- g_free (module_name);
- return module;
- }
+ count = 0;
+ for (path = get_module_path (); *path; path++)
+ {
+ gint use_version, use_host;
- g_free (module_name);
+ for (use_version = TRUE; use_version >= FALSE; use_version--)
+ for (use_host = TRUE; use_host >= FALSE; use_host--)
+ {
+ gchar *tmp_dir;
+
+ if (use_version && use_host)
+ tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, GTK_HOST, type, NULL);
+ else if (use_version)
+ tmp_dir = g_build_filename (*path, GTK_BINARY_VERSION, type, NULL);
+ else if (use_host)
+ tmp_dir = g_build_filename (*path, GTK_HOST, type, NULL);
+ else
+ tmp_dir = g_build_filename (*path, type, NULL);
+
+ result[count++] = tmp_dir;
+ }
+ }
- module_name = g_module_build_path (module_path[i], name);
-
- if (g_file_test (module_name, G_FILE_TEST_EXISTS))
+ result[count++] = NULL;
+
+ return result;
+}
+
+/**
+ * _gtk_find_module:
+ * @name: the name of the module
+ * @type: the type of the module, for instance 'modules', 'engines', immodules'
+ *
+ * Looks for a dynamically module named @name of type @type in the standard GTK+
+ * module search path.
+ *
+ * Return value: the pathname to the found module, or %NULL if it wasn't found.
+ * Free with g_free().
+ **/
+gchar *
+_gtk_find_module (const gchar *name,
+ const gchar *type)
+{
+ gchar **paths;
+ gchar **path;
+ gchar *module_name = NULL;
+
+ if (g_path_is_absolute (name))
+ return g_strdup (name);
+
+ paths = _gtk_get_module_path (type);
+ for (path = paths; *path; path++)
+ {
+ gchar *tmp_name = g_module_build_path (*path, name);
+
+ if (g_file_test (tmp_name, G_FILE_TEST_EXISTS))
{
- module = g_module_open (module_name, G_MODULE_BIND_LAZY);
- g_free (module_name);
- return module;
+ module_name = tmp_name;
+ goto found;
}
-
- g_free (module_name);
+ else
+ g_free(tmp_name);
}
- /* As last resort, try loading without an absolute path (using system
- * library path)
- */
- module_name = g_module_build_path (NULL, name);
+ g_strfreev (paths);
+
+ found:
+ return module_name;
+}
+
+static GModule *
+find_module (gchar **module_path,
+ const gchar *name)
+{
+ GModule *module;
+ gchar *module_name;
+
+ module_name = _gtk_find_module (name, "modules");
+ if (!module_name)
+ {
+ /* As last resort, try loading without an absolute path (using system
+ * library path)
+ */
+ module_name = g_module_build_path (NULL, name);
+ }
+
module = g_module_open (module_name, G_MODULE_BIND_LAZY);
g_free(module_name);
GString *gtk_modules_string = NULL;
GSList *gtk_modules = NULL;
GSList *slist;
- gchar *env_string;
+ const gchar *env_string;
if (gtk_initialized)
return TRUE;
#endif
if (do_setlocale)
- setlocale (LC_ALL, "");
+ {
+ if (!setlocale (LC_ALL, ""))
+ g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
+ }
/* Initialize "gdk". We pass along the 'argc' and 'argv'
* parameters as they contain information that GDK uses
_gtk_accel_map_init ();
_gtk_rc_init ();
- /* Register an exit function to make sure we are able to cleanup.
- */
- g_atexit (gtk_exit_func);
-
/* Set the 'initialized' flag.
*/
gtk_initialized = TRUE;
}
g_slist_free (gtk_modules);
-#ifndef G_OS_WIN32
- /* No use warning on Win32, there aren't any non-devel versions anyhow... */
- g_message ("" "YOU ARE USING THE DEVEL BRANCH 1.3.x OF GTK+ WHICH IS CURRENTLY\n"
- " UNDER HEAVY DEVELOPMENT AND FREQUENTLY INTRODUCES INSTABILITIES.\n"
- " if you don't know why you are getting this, you probably want to\n"
- " use the stable branch which can be retrieved from\n"
- " ftp://ftp.gtk.org/pub/gtk/v1.2/ or via CVS with\n"
- " cvs checkout -r glib-1-2 glib; cvs checkout -r gtk-1-2 gtk+");
-#endif
-
return TRUE;
}
{
/* Only if "gtk" has been initialized should we de-initialize.
*/
- /* de-initialisation is done by the gtk_exit_funct(),
- * no need to do this here (Alex J.)
- */
gdk_exit (errorcode);
}
return TRUE;
}
+/* private libgtk to libgdk interfaces
+ */
+gboolean gdk_pointer_grab_info_libgtk_only (GdkWindow **grab_window,
+ gboolean *owner_events);
+gboolean gdk_keyboard_grab_info_libgtk_only (GdkWindow **grab_window,
+ gboolean *owner_events);
+
+static void
+rewrite_events_translate (GdkWindow *old_window,
+ GdkWindow *new_window,
+ gdouble *x,
+ gdouble *y)
+{
+ gint old_origin_x, old_origin_y;
+ gint new_origin_x, new_origin_y;
+
+ gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
+ gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
+
+ *x += new_origin_x - old_origin_x;
+ *y += new_origin_y - old_origin_y;
+}
+
+GdkEvent *
+rewrite_event_for_window (GdkEvent *event,
+ GdkWindow *new_window)
+{
+ event = gdk_event_copy (event);
+
+ switch (event->type)
+ {
+ case GDK_SCROLL:
+ rewrite_events_translate (event->any.window,
+ new_window,
+ &event->scroll.x, &event->scroll.y);
+ break;
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ rewrite_events_translate (event->any.window,
+ new_window,
+ &event->button.x, &event->button.y);
+ break;
+ case GDK_MOTION_NOTIFY:
+ rewrite_events_translate (event->any.window,
+ new_window,
+ &event->motion.x, &event->motion.y);
+ break;
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ break;
+
+ default:
+ return event;
+ }
+
+ g_object_unref (event->any.window);
+ event->any.window = g_object_ref (new_window);
+
+ return event;
+}
+
+/* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
+ * then what X11 does is deliver the event normally if it was going to this
+ * client, otherwise, delivers it in terms of the grab window. This function
+ * rewrites events to the effect that events going to the same window group
+ * are delivered normally, otherwise, the event is delivered in terms of the
+ * grab window.
+ */
+static GdkEvent *
+rewrite_event_for_grabs (GdkEvent *event)
+{
+ GdkWindow *grab_window;
+ GtkWidget *event_widget, *grab_widget;;
+ gboolean owner_events;
+
+ switch (event->type)
+ {
+ case GDK_SCROLL:
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_MOTION_NOTIFY:
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ if (!gdk_pointer_grab_info_libgtk_only (&grab_window, &owner_events) ||
+ !owner_events)
+ return NULL;
+ break;
+
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ if (!gdk_keyboard_grab_info_libgtk_only (&grab_window, &owner_events) ||
+ !owner_events)
+ return NULL;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ event_widget = gtk_get_event_widget (event);
+ gdk_window_get_user_data (grab_window, (void**) &grab_widget);
+
+ if (grab_widget &&
+ gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
+ return rewrite_event_for_window (event, grab_window);
+ else
+ return NULL;
+}
+
void
gtk_main_do_event (GdkEvent *event)
{
GtkWidget *grab_widget;
GtkWindowGroup *window_group;
GdkEvent *next_event;
+ GdkEvent *rewritten_event = NULL;
GList *tmp_list;
/* If there are any events pending then get the next one.
return;
}
+
+ /* If pointer or keyboard grabs are in effect, munge the events
+ * so that each window group looks like a separate app.
+ */
+ rewritten_event = rewrite_event_for_grabs (event);
+ if (rewritten_event)
+ {
+ event = rewritten_event;
+ event_widget = gtk_get_event_widget (event);
+ }
+ window_group = gtk_main_get_window_group (event_widget);
+
/* Push the event onto a stack of current events for
* gtk_current_event_get().
*/
current_events = g_list_prepend (current_events, event);
- window_group = gtk_main_get_window_group (event_widget);
-
/* If there is a grab in effect...
*/
if (window_group->grabs)
tmp_list = current_events;
current_events = g_list_remove_link (current_events, tmp_list);
g_list_free_1 (tmp_list);
+
+ if (rewritten_event)
+ gdk_event_free (rewritten_event);
}
gboolean
return widget;
}
-static void
-gtk_exit_func (void)
-{
- if (gtk_initialized)
- {
- gtk_initialized = FALSE;
- }
-}
-
-
static gint
gtk_quit_invoke_function (GtkQuitFunction *quitf)
{