* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "gdkx.h" /* For GDK_WINDOWING */
+
+#if GDK_WINDOWING == GDK_WINDOWING_X11
#include <X11/Xlocale.h> /* so we get the right setlocale */
+#else
+#include <locale.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmodule.h>
#include "gtkbutton.h"
#include "gtkdnd.h"
-#include "gtkfeatures.h"
+#include "gtkcompat.h"
#include "gtkhscrollbar.h"
#include "gtkhseparator.h"
#include "gtkmain.h"
#include "gtkpreview.h"
#include "gtkrc.h"
+#include "gtkscrolledwindow.h"
#include "gtkselection.h"
#include "gtksignal.h"
#include "gtktable.h"
static void gtk_quit_destroy (GtkQuitFunction *quitf);
static gint gtk_invoke_key_snoopers (GtkWidget *grab_widget,
GdkEvent *event);
-static void gtk_propagate_event (GtkWidget *widget,
- GdkEvent *event);
static void gtk_destroy_closure (gpointer data);
static gboolean gtk_invoke_idle_timeout (gpointer data);
guint gtk_debug_flags = 0; /* Global GTK debug flag */
-GMutex *gtk_threads_mutex = NULL; /* Global GTK lock */
-
#ifdef G_ENABLE_DEBUG
static const GDebugKey gtk_debug_keys[] = {
{"objects", GTK_DEBUG_OBJECTS},
{"misc", GTK_DEBUG_MISC},
{"signals", GTK_DEBUG_SIGNALS},
- {"dnd", GTK_DEBUG_DND}
+ {"dnd", GTK_DEBUG_DND},
+ {"plugsocket", GTK_DEBUG_PLUGSOCKET}
};
static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
guint required_micro)
{
if (required_major > GTK_MAJOR_VERSION)
- return "Gtk+ version to old (major mismatch)";
+ return "Gtk+ version too old (major mismatch)";
if (required_major < GTK_MAJOR_VERSION)
- return "Gtk+ version to new (major mismatch)";
+ return "Gtk+ version too new (major mismatch)";
if (required_minor > GTK_MINOR_VERSION)
- return "Gtk+ version to old (minor mismatch)";
+ return "Gtk+ version too old (minor mismatch)";
if (required_minor < GTK_MINOR_VERSION)
- return "Gtk+ version to new (minor mismatch)";
+ return "Gtk+ version too new (minor mismatch)";
if (required_micro < GTK_MICRO_VERSION - GTK_BINARY_AGE)
- return "Gtk+ version to new (micro mismatch)";
+ return "Gtk+ version too new (micro mismatch)";
if (required_micro > GTK_MICRO_VERSION)
- return "Gtk+ version to old (micro mismatch)";
+ return "Gtk+ version too old (micro mismatch)";
return NULL;
}
+#ifdef __EMX__
+static gchar *add_dll_suffix(gchar *module_name)
+{
+ gchar *suffix = strrchr(module_name, '.');
+
+ if (!suffix || stricmp(suffix, ".dll"))
+ {
+ gchar *old = module_name;
+
+ module_name = g_strconcat (module_name, ".dll", NULL);
+ g_free (old);
+ }
+ return (module_name);
+}
+#endif
-void
-gtk_init (int *argc,
- char ***argv)
+gboolean
+gtk_init_check (int *argc,
+ char ***argv)
{
+ extern void gtk_object_post_arg_parsing_init (void);
GSList *gtk_modules = NULL;
GSList *slist;
gchar *env_string = NULL;
if (gtk_initialized)
- return;
-
- /* There is some argument for putting this in a separate
- * function ... but I don't think that it is much
- * of a restriction to require that GTK+ be used
- * single threaded until gtk_init().
- */
+ return TRUE;
- if (g_thread_supported ())
- gtk_threads_mutex = g_mutex_new ();
-
#if 0
g_set_error_handler (gtk_error);
g_set_warning_handler (gtk_warning);
/* Initialize "gdk". We pass along the 'argc' and 'argv'
* parameters as they contain information that GDK uses
*/
- gdk_init (argc, argv);
+ if (!gdk_init_check (argc, argv))
+ return FALSE;
gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
{
gchar **modules, **as;
- modules = g_strsplit (env_string, ":", -1);
+#ifndef __EMX__
+ modules = g_strsplit (env_string, G_SEARCHPATH_SEPARATOR_S, -1);
+#else
+ modules = g_strsplit (env_string, ";", -1);
+#endif
for (as = modules; *as; as++)
{
if (**as)
module_name = slist->data;
slist->data = NULL;
- if (!(module_name[0] == '/' ||
- (module_name[0] == 'l' &&
- module_name[1] == 'i' &&
- module_name[2] == 'b')))
+#ifndef __EMX__
+ if (!g_path_is_absolute (module_name))
{
gchar *old = module_name;
- module_name = g_strconcat ("lib", module_name, ".so", NULL);
+ module_name = g_module_build_path (NULL, module_name);
g_free (old);
}
+#else
+ module_name = add_dll_suffix(module_name);
+#endif
if (g_module_supported ())
{
module = g_module_open (module_name, G_MODULE_BIND_LAZY);
}
#ifdef ENABLE_NLS
- bindtextdomain("gtk+",GTK_LOCALEDIR);
+ bindtextdomain("gtk+", GTK_LOCALEDIR);
#endif
/* Initialize the default visual and colormap to be
gtk_colormap = gdk_colormap_get_system ();
gtk_type_init ();
+ gtk_object_post_arg_parsing_init ();
gtk_signal_init ();
gtk_rc_init ();
}
}
g_slist_free (gtk_modules);
+
+#ifndef NATIVE_WIN32
+ /* No use warning on Win32, there aren't any non-devel versions anyhow... */
+ g_warning ("" "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 retrived 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;
+}
+void
+gtk_init (int *argc, char ***argv)
+{
+ if (!gtk_init_check (argc, argv))
+ {
+ g_warning ("cannot open display: %s", gdk_get_display ());
+ exit(1);
+ }
}
void
GList *tmp_list;
GList *functions;
GtkInitFunction *init;
-
GMainLoop *loop;
- GSList *tmp_node;
gtk_main_loop_level++;
+ loop = g_main_new (TRUE);
+ main_loops = g_slist_prepend (main_loops, loop);
+
tmp_list = functions = init_functions;
init_functions = NULL;
g_free (init);
}
g_list_free (functions);
-
- loop = g_main_new ();
- main_loops = g_slist_prepend (main_loops, loop);
- GTK_THREADS_LEAVE ();
- g_main_run (loop);
- GTK_THREADS_ENTER ();
-
- g_main_destroy (loop);
-
- tmp_node = main_loops;
- main_loops = g_slist_remove_link (main_loops, main_loops);
- g_slist_free_1 (tmp_node);
+ if (g_main_is_running (main_loops->data))
+ {
+ GDK_THREADS_LEAVE ();
+ g_main_run (loop);
+ GDK_THREADS_ENTER ();
+ gdk_flush ();
+ }
if (quit_functions)
{
work->next = quit_functions;
quit_functions = work;
}
+
+ gdk_flush ();
}
+ main_loops = g_slist_remove (main_loops, loop);
+
+ g_main_destroy (loop);
+
gtk_main_loop_level--;
}
void
gtk_main_quit (void)
{
+ g_return_if_fail (main_loops != NULL);
+
g_main_quit (main_loops->data);
}
gint
gtk_main_iteration (void)
{
- return g_main_iteration (TRUE);
+ g_main_iteration (TRUE);
+
+ if (main_loops)
+ return !g_main_is_running (main_loops->data);
+ else
+ return TRUE;
}
gint
gtk_main_iteration_do (gboolean blocking)
{
- return g_main_iteration (blocking);
+ g_main_iteration (blocking);
+
+ if (main_loops)
+ return !g_main_is_running (main_loops->data);
+ else
+ return TRUE;
}
void
/* If there are any events pending then get the next one.
*/
- next_event = gdk_event_get ();
+ next_event = gdk_event_peek ();
/* Try to compress enter/leave notify events. These event
* pairs occur when the mouse is dragged quickly across
(next_event->type != event->type) &&
(next_event->any.window == event->any.window))
{
+ /* Throw both the peeked copy and the queued copy away
+ */
+ gdk_event_free (next_event);
+ next_event = gdk_event_get ();
gdk_event_free (next_event);
- next_event = NULL;
return;
}
-
if (next_event)
- gdk_event_put (next_event);
- next_event = NULL;
+ gdk_event_free (next_event);
/* Find the widget which got the event. We store the widget
* in the user_data field of GdkWindow's.
{
grab_widget = event_widget;
}
-
+
/* Not all events get sent to the grabbing widget.
* The delete, destroy, expose, focus change and resize
* events still get sent to the event widget because
case GDK_VISIBILITY_NOTIFY:
gtk_widget_event (event_widget, event);
break;
-
+
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ /* We treat button 4-5 specially, assume we have
+ * a MS-style scrollwheel mouse, and try to find
+ * a plausible widget to scroll. We also trap
+ * button 4-5 double and triple clicks here, since
+ * they will be generated if the user scrolls quickly.
+ */
+ if ((grab_widget == event_widget) &&
+ (event->button.button == 4 || event->button.button == 5))
+ {
+ GtkWidget *range = NULL;
+ GtkWidget *scrollwin;
+
+ if (GTK_IS_RANGE (event_widget))
+ range = event_widget;
+ else
+ {
+ scrollwin = gtk_widget_get_ancestor (event_widget,
+ GTK_TYPE_SCROLLED_WINDOW);
+ if (scrollwin)
+ range = GTK_SCROLLED_WINDOW (scrollwin)->vscrollbar;
+ }
+
+ if (range && GTK_WIDGET_VISIBLE (range))
+ {
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
+ gfloat new_value = adj->value + ((event->button.button == 4) ?
+ -adj->page_increment / 2:
+ adj->page_increment / 2);
+ new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
+ gtk_adjustment_set_value (adj, new_value);
+ }
+ break;
+ }
+ }
+ gtk_propagate_event (grab_widget, event);
+ break;
+
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
if (key_snoopers)
}
/* else fall through */
case GDK_MOTION_NOTIFY:
- case GDK_BUTTON_PRESS:
- case GDK_2BUTTON_PRESS:
- case GDK_3BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
case GDK_PROXIMITY_IN:
case GDK_PROXIMITY_OUT:
return g_timeout_add_full (0, interval, function, data, NULL);
}
-guint
-gtk_timeout_add_interp (guint32 interval,
- GtkCallbackMarshal function,
- gpointer data,
- GtkDestroyNotify destroy)
-{
- return gtk_timeout_add_full (interval, NULL, function, data, destroy);
-}
-
void
gtk_timeout_remove (guint tag)
{
return g_idle_add_full (priority, function, data, NULL);
}
-guint
-gtk_idle_add_interp (GtkCallbackMarshal marshal,
- gpointer data,
- GtkDestroyNotify destroy)
-{
- return gtk_idle_add_full (GTK_PRIORITY_DEFAULT, NULL, marshal, data, destroy);
-}
-
void
gtk_idle_remove (guint tag)
{
void
gtk_idle_remove_by_data (gpointer data)
{
- g_source_remove_by_user_data (data);
+ if (!g_idle_remove_by_data (data))
+ g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
}
guint
}
}
-static void
+void
gtk_propagate_event (GtkWidget *widget,
GdkEvent *event)
{
gint handled_event;
g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (event != NULL);
handled_event = FALSE;
*/
GtkWidget *window;
- window = gtk_widget_get_ancestor (widget, gtk_window_get_type ());
+ window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
if (window)
{
if (GTK_WIDGET_IS_SENSITIVE (window))
}
}
-void
-gtk_threads_enter ()
-{
- GTK_THREADS_ENTER ();
-}
-
-void
-gtk_threads_leave ()
-{
- GTK_THREADS_LEAVE ();
-}
-
#if 0
static void
gtk_error (gchar *str)