
2001-01-26 Havoc Pennington <hp@redhat.com> * gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor * gtk/gtktreeview.c (gtk_tree_view_widget_to_tree_coords): fix to not offset by TREE_VIEW_HEADER_HEIGHT (gtk_tree_view_tree_to_widget_coords): fix to not offset by TREE_VIEW_HEADER_HEIGHT * configure.in (included_loaders): for me, --with-included-loaders generates the error "the specified loader yes does not exist", i.e. the arg defaults to "yes", so change test for value "" to test for value "yes", and include all loaders in that case. * gtk/gtkrbtree.c (_gtk_rbtree_get_depth): new function * gtk/gtktreeview.c (gtk_tree_view_get_cell_rect): fix to properly handle TREE_VIEW_VERTICAL_SEPARATOR (gtk_tree_view_bin_expose): fix to consider the row offset as pointing halfway into vertical separator. (gtk_tree_view_draw_node_focus_rect): ditto * gtk/gtkdebug.h, gtk/gtkmain.c (gtk_init_check): Add --gtk-debug=updates, which causes gdk_window_set_debug_updates (TRUE) to be called. * gdk/gdkwindow.c (gdk_window_set_debug_updates): Allow enabling a debug mode where the invalid region is colored in on invalidate, so you can see the flicker and know whether your redraw code is doing a good job. * gtk/gtktreeview.c (gtk_tree_view_queue_draw_node): Work in tree window coordinates (clip rect is in tree window coords) * gtk/Makefile.am: add gtktreednd.[hc] * gtk/gtkliststore.c: implement gtktreednd interfaces. * gtk/gtktreednd.c, gtk/gtktreednd.h: New interface to support drag-and-drop data operations on a model (so we can set up tree drag-and-drop automatically) * gtk/testgtk.c: Add a window to change sensitivity in the GtkLabel test; add a way to change the entry frame in GtkEntry test * gtk/gtkentry.c (gtk_entry_set_has_frame): (gtk_entry_get_has_frame): new functions to remove the frame around an entry (gtk_entry_size_request): shrink requisition if no frame (gtk_entry_draw_focus): don't draw frame if no frame * gtk/gtkstyle.c (gtk_default_draw_check): draw custom look for checks inside a cell renderer (gtk_default_draw_option): ditto for options * gtk/gtktreeviewcolumn.c (update_button_contents): add/remove children from the alignment, not the button (gtk_tree_view_column_init): ref/sink the column, to emulate GObject refcounting. * gtk/gtkcellrenderer.c (gtk_cell_renderer_init): ref/sink * gtk/gtkcellrenderertoggle.c (gtk_cell_renderer_toggle_render): Use theme functions to draw the toggles * gdk/gdkpango.c (gdk_pango_get_gc): use GdkRGB to alloc colors * gdk/gdkpango.h, gdk/gdkpango.c: Add GdkPangoAttrStipple and GdkPangoAttrEmbossed to use in rendering insensitive text * gdk/gdkpango.c (gdk_draw_layout_line): render new properties * gtk/gtkstyle.c (gtk_default_draw_layout): handle sensitivity using new GDK features
1549 lines
36 KiB
C
1549 lines
36 KiB
C
/* GTK - The GIMP Toolkit
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/*
|
|
* Modified by the GTK+ Team and others 1997-2000. 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/.
|
|
*/
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
#include <X11/Xlocale.h> /* so we get the right setlocale */
|
|
#else
|
|
#include <locale.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
|
|
#include <libintl.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <gmodule.h>
|
|
#include "gtkdnd.h"
|
|
#include "gtkcompat.h"
|
|
#include "gtkmain.h"
|
|
#include "gtkrc.h"
|
|
#include "gtkselection.h"
|
|
#include "gtksignal.h"
|
|
#include "gtkwidget.h"
|
|
#include "gtkwindow.h"
|
|
#include "gtkprivate.h"
|
|
#include "gdk/gdki18n.h"
|
|
#include "config.h"
|
|
#include "gtkdebug.h"
|
|
#include "gtkintl.h"
|
|
|
|
/* Private type definitions
|
|
*/
|
|
typedef struct _GtkInitFunction GtkInitFunction;
|
|
typedef struct _GtkQuitFunction GtkQuitFunction;
|
|
typedef struct _GtkClosure GtkClosure;
|
|
typedef struct _GtkKeySnooperData GtkKeySnooperData;
|
|
|
|
struct _GtkInitFunction
|
|
{
|
|
GtkFunction function;
|
|
gpointer data;
|
|
};
|
|
|
|
struct _GtkQuitFunction
|
|
{
|
|
guint id;
|
|
guint main_level;
|
|
GtkCallbackMarshal marshal;
|
|
GtkFunction function;
|
|
gpointer data;
|
|
GtkDestroyNotify destroy;
|
|
};
|
|
|
|
struct _GtkClosure
|
|
{
|
|
GtkCallbackMarshal marshal;
|
|
gpointer data;
|
|
GtkDestroyNotify destroy;
|
|
};
|
|
|
|
struct _GtkKeySnooperData
|
|
{
|
|
GtkKeySnoopFunc func;
|
|
gpointer func_data;
|
|
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,
|
|
GdkEvent *event);
|
|
|
|
static void gtk_destroy_closure (gpointer data);
|
|
static gboolean gtk_invoke_idle_timeout (gpointer data);
|
|
static void gtk_invoke_input (gpointer data,
|
|
gint source,
|
|
GdkInputCondition condition);
|
|
|
|
#if 0
|
|
static void gtk_error (gchar *str);
|
|
static void gtk_warning (gchar *str);
|
|
static void gtk_message (gchar *str);
|
|
static void gtk_print (gchar *str);
|
|
#endif
|
|
|
|
const guint gtk_major_version = GTK_MAJOR_VERSION;
|
|
const guint gtk_minor_version = GTK_MINOR_VERSION;
|
|
const guint gtk_micro_version = GTK_MICRO_VERSION;
|
|
const guint gtk_binary_age = GTK_BINARY_AGE;
|
|
const guint gtk_interface_age = GTK_INTERFACE_AGE;
|
|
|
|
static guint gtk_main_loop_level = 0;
|
|
static gint gtk_initialized = FALSE;
|
|
static GList *current_events = NULL;
|
|
|
|
static GSList *main_loops = NULL; /* stack of currently executing main loops */
|
|
|
|
static GSList *grabs = NULL; /* A stack of unique grabs. The grabbing
|
|
* widget is the first one on the list.
|
|
*/
|
|
static GList *init_functions = NULL; /* A list of init functions.
|
|
*/
|
|
static GList *quit_functions = NULL; /* A list of quit functions.
|
|
*/
|
|
static GMemChunk *quit_mem_chunk = NULL;
|
|
|
|
static GSList *key_snoopers = NULL;
|
|
|
|
static GdkVisual *gtk_visual; /* The visual to be used in creating new
|
|
* widgets.
|
|
*/
|
|
static GdkColormap *gtk_colormap; /* The colormap to be used in creating new
|
|
* widgets.
|
|
*/
|
|
|
|
guint gtk_debug_flags = 0; /* Global GTK debug flag */
|
|
|
|
#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},
|
|
{"plugsocket", GTK_DEBUG_PLUGSOCKET},
|
|
{"text", GTK_DEBUG_TEXT},
|
|
{"tree", GTK_DEBUG_TREE},
|
|
{"updates", GTK_DEBUG_UPDATES}
|
|
};
|
|
|
|
static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
|
|
|
|
#endif /* G_ENABLE_DEBUG */
|
|
|
|
gchar*
|
|
gtk_check_version (guint required_major,
|
|
guint required_minor,
|
|
guint required_micro)
|
|
{
|
|
if (required_major > GTK_MAJOR_VERSION)
|
|
return "Gtk+ version too old (major mismatch)";
|
|
if (required_major < GTK_MAJOR_VERSION)
|
|
return "Gtk+ version too new (major mismatch)";
|
|
if (required_minor > GTK_MINOR_VERSION)
|
|
return "Gtk+ version too old (minor mismatch)";
|
|
if (required_minor < GTK_MINOR_VERSION)
|
|
return "Gtk+ version too new (minor mismatch)";
|
|
if (required_micro < GTK_MICRO_VERSION - GTK_BINARY_AGE)
|
|
return "Gtk+ version too new (micro mismatch)";
|
|
if (required_micro > GTK_MICRO_VERSION)
|
|
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
|
|
|
|
#undef gtk_init_check
|
|
|
|
gboolean
|
|
gtk_init_check (int *argc,
|
|
char ***argv)
|
|
{
|
|
GSList *gtk_modules = NULL;
|
|
GSList *slist;
|
|
gchar *env_string = NULL;
|
|
|
|
if (gtk_initialized)
|
|
return TRUE;
|
|
|
|
#if 0
|
|
g_set_error_handler (gtk_error);
|
|
g_set_warning_handler (gtk_warning);
|
|
g_set_message_handler (gtk_message);
|
|
g_set_print_handler (gtk_print);
|
|
#endif
|
|
|
|
/* Initialize "gdk". We pass along the 'argc' and 'argv'
|
|
* parameters as they contain information that GDK uses
|
|
*/
|
|
if (!gdk_init_check (argc, argv))
|
|
return FALSE;
|
|
|
|
gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
|
|
|
|
#ifdef G_ENABLE_DEBUG
|
|
env_string = getenv ("GTK_DEBUG");
|
|
if (env_string != NULL)
|
|
{
|
|
gtk_debug_flags = g_parse_debug_string (env_string,
|
|
gtk_debug_keys,
|
|
gtk_ndebug_keys);
|
|
env_string = NULL;
|
|
}
|
|
#endif /* G_ENABLE_DEBUG */
|
|
|
|
env_string = getenv ("GTK_MODULES");
|
|
if (env_string)
|
|
{
|
|
gchar **modules, **as;
|
|
|
|
#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)
|
|
gtk_modules = g_slist_prepend (gtk_modules, *as);
|
|
else
|
|
g_free (*as);
|
|
}
|
|
g_free (modules);
|
|
env_string = NULL;
|
|
}
|
|
|
|
if (argc && argv)
|
|
{
|
|
gint i, j, k;
|
|
|
|
for (i = 1; i < *argc;)
|
|
{
|
|
if (strcmp ("--gtk-module", (*argv)[i]) == 0 ||
|
|
strncmp ("--gtk-module=", (*argv)[i], 13) == 0)
|
|
{
|
|
gchar *module_name = (*argv)[i] + 12;
|
|
|
|
if (*module_name == '=')
|
|
module_name++;
|
|
else if (i + 1 < *argc)
|
|
{
|
|
(*argv)[i] = NULL;
|
|
i += 1;
|
|
module_name = (*argv)[i];
|
|
}
|
|
(*argv)[i] = NULL;
|
|
|
|
if (module_name && *module_name)
|
|
gtk_modules = g_slist_prepend (gtk_modules, g_strdup (module_name));
|
|
}
|
|
else if (strcmp ("--g-fatal-warnings", (*argv)[i]) == 0)
|
|
{
|
|
GLogLevelFlags fatal_mask;
|
|
|
|
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
|
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
|
g_log_set_always_fatal (fatal_mask);
|
|
(*argv)[i] = NULL;
|
|
}
|
|
#ifdef G_ENABLE_DEBUG
|
|
else if ((strcmp ("--gtk-debug", (*argv)[i]) == 0) ||
|
|
(strncmp ("--gtk-debug=", (*argv)[i], 12) == 0))
|
|
{
|
|
gchar *equal_pos = strchr ((*argv)[i], '=');
|
|
|
|
if (equal_pos != NULL)
|
|
{
|
|
gtk_debug_flags |= g_parse_debug_string (equal_pos+1,
|
|
gtk_debug_keys,
|
|
gtk_ndebug_keys);
|
|
}
|
|
else if ((i + 1) < *argc && (*argv)[i + 1])
|
|
{
|
|
gtk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
|
|
gtk_debug_keys,
|
|
gtk_ndebug_keys);
|
|
(*argv)[i] = NULL;
|
|
i += 1;
|
|
}
|
|
(*argv)[i] = NULL;
|
|
}
|
|
else if ((strcmp ("--gtk-no-debug", (*argv)[i]) == 0) ||
|
|
(strncmp ("--gtk-no-debug=", (*argv)[i], 15) == 0))
|
|
{
|
|
gchar *equal_pos = strchr ((*argv)[i], '=');
|
|
|
|
if (equal_pos != NULL)
|
|
{
|
|
gtk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
|
|
gtk_debug_keys,
|
|
gtk_ndebug_keys);
|
|
}
|
|
else if ((i + 1) < *argc && (*argv)[i + 1])
|
|
{
|
|
gtk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
|
|
gtk_debug_keys,
|
|
gtk_ndebug_keys);
|
|
(*argv)[i] = NULL;
|
|
i += 1;
|
|
}
|
|
(*argv)[i] = NULL;
|
|
}
|
|
#endif /* G_ENABLE_DEBUG */
|
|
i += 1;
|
|
}
|
|
|
|
for (i = 1; i < *argc; i++)
|
|
{
|
|
for (k = i; k < *argc; k++)
|
|
if ((*argv)[k] != NULL)
|
|
break;
|
|
|
|
if (k > i)
|
|
{
|
|
k -= i;
|
|
for (j = i + k; j < *argc; j++)
|
|
(*argv)[j-k] = (*argv)[j];
|
|
*argc -= k;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_UPDATES)
|
|
gdk_window_set_debug_updates (TRUE);
|
|
|
|
/* load gtk modules */
|
|
gtk_modules = g_slist_reverse (gtk_modules);
|
|
for (slist = gtk_modules; slist; slist = slist->next)
|
|
{
|
|
gchar *module_name;
|
|
GModule *module = NULL;
|
|
GtkModuleInitFunc modinit_func = NULL;
|
|
|
|
module_name = slist->data;
|
|
slist->data = NULL;
|
|
#ifndef __EMX__
|
|
if (!g_path_is_absolute (module_name))
|
|
{
|
|
gchar *old = module_name;
|
|
|
|
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);
|
|
if (module &&
|
|
g_module_symbol (module, "gtk_module_init", (gpointer*) &modinit_func) &&
|
|
modinit_func)
|
|
{
|
|
if (!g_slist_find (gtk_modules, modinit_func))
|
|
{
|
|
g_module_make_resident (module);
|
|
slist->data = modinit_func;
|
|
}
|
|
else
|
|
{
|
|
g_module_close (module);
|
|
module = NULL;
|
|
}
|
|
}
|
|
}
|
|
if (!modinit_func)
|
|
{
|
|
g_message ("Failed to load module \"%s\": %s",
|
|
module ? g_module_name (module) : module_name,
|
|
g_module_error ());
|
|
if (module)
|
|
g_module_close (module);
|
|
}
|
|
g_free (module_name);
|
|
}
|
|
|
|
#ifdef ENABLE_NLS
|
|
# ifndef G_OS_WIN32
|
|
bindtextdomain(GETTEXT_PACKAGE, GTK_LOCALEDIR);
|
|
# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
|
|
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
|
# endif
|
|
# else /* !G_OS_WIN32 */
|
|
{
|
|
bindtextdomain (GETTEXT_PACKAGE,
|
|
g_win32_get_package_installation_subdirectory (GETTEXT_PACKAGE,
|
|
g_strdup_printf ("gtk-%d.%d.dll", GTK_MAJOR_VERSION, GTK_MINOR_VERSION),
|
|
"locale"));
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
{
|
|
/* Translate to default:RTL if you want your widgets
|
|
* to be RTL, otherwise translate to default:LTR.
|
|
* Do *not* translate it to "predefinito:LTR", if it
|
|
* it isn't default:LTR or default:RTL it will not work
|
|
*/
|
|
char *e = _("default:LTR");
|
|
if (strcmp (e, "default:RTL")==0) {
|
|
gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
|
|
} else if (strcmp (e, "default:LTR")) {
|
|
g_warning ("Whoever translated default:LTR did so wrongly.\n");
|
|
}
|
|
}
|
|
|
|
/* Initialize the default visual and colormap to be
|
|
* used in creating widgets. (We want to use the system
|
|
* defaults so as to be nice to the colormap).
|
|
*/
|
|
gtk_visual = gdk_visual_get_system ();
|
|
gtk_colormap = gdk_colormap_get_system ();
|
|
|
|
gtk_type_init ();
|
|
gtk_signal_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;
|
|
|
|
/* initialize gtk modules
|
|
*/
|
|
for (slist = gtk_modules; slist; slist = slist->next)
|
|
{
|
|
if (slist->data)
|
|
{
|
|
GtkModuleInitFunc modinit;
|
|
|
|
modinit = slist->data;
|
|
modinit (argc, argv);
|
|
}
|
|
}
|
|
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 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;
|
|
}
|
|
|
|
#undef gtk_init
|
|
|
|
void
|
|
gtk_init (int *argc, char ***argv)
|
|
{
|
|
if (!gtk_init_check (argc, argv))
|
|
{
|
|
g_warning ("cannot open display: %s", gdk_get_display ());
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
static void
|
|
check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
|
|
{
|
|
if (sizeof_GtkWindow != sizeof (GtkWindow))
|
|
g_error ("Incompatible build!\n"
|
|
"The code using GTK+ thinks GtkWindow is of different\n"
|
|
"size than it actually is in this build of GTK+.\n"
|
|
"On Windows, this probably means that you have compiled\n"
|
|
"your code with gcc without the -fnative-struct switch.");
|
|
}
|
|
|
|
/* These two functions might get more checks added later, thus pass
|
|
* in the number of extra args.
|
|
*/
|
|
void
|
|
gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow)
|
|
{
|
|
check_sizeof_GtkWindow (sizeof_GtkWindow);
|
|
gtk_init (argc, argv);
|
|
}
|
|
|
|
gboolean
|
|
gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow)
|
|
{
|
|
check_sizeof_GtkWindow (sizeof_GtkWindow);
|
|
return gtk_init_check (argc, argv);
|
|
}
|
|
|
|
#endif
|
|
|
|
void
|
|
gtk_exit (gint errorcode)
|
|
{
|
|
/* 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);
|
|
}
|
|
|
|
gchar*
|
|
gtk_set_locale (void)
|
|
{
|
|
return gdk_set_locale ();
|
|
}
|
|
|
|
gchar*
|
|
gtk_get_default_language (void)
|
|
{
|
|
gchar *lang;
|
|
gchar *p;
|
|
|
|
lang = g_strdup (setlocale (LC_CTYPE, NULL));
|
|
p = strchr (lang, '.');
|
|
if (p)
|
|
*p = '\0';
|
|
p = strchr (lang, '@');
|
|
if (p)
|
|
*p = '\0';
|
|
|
|
return lang;
|
|
}
|
|
|
|
void
|
|
gtk_main (void)
|
|
{
|
|
GList *tmp_list;
|
|
GList *functions;
|
|
GtkInitFunction *init;
|
|
GMainLoop *loop;
|
|
|
|
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;
|
|
|
|
while (tmp_list)
|
|
{
|
|
init = tmp_list->data;
|
|
tmp_list = tmp_list->next;
|
|
|
|
(* init->function) (init->data);
|
|
g_free (init);
|
|
}
|
|
g_list_free (functions);
|
|
|
|
if (g_main_is_running (main_loops->data))
|
|
{
|
|
GDK_THREADS_LEAVE ();
|
|
g_main_run (loop);
|
|
GDK_THREADS_ENTER ();
|
|
gdk_flush ();
|
|
}
|
|
|
|
if (quit_functions)
|
|
{
|
|
GList *reinvoke_list = NULL;
|
|
GtkQuitFunction *quitf;
|
|
|
|
while (quit_functions)
|
|
{
|
|
quitf = quit_functions->data;
|
|
|
|
tmp_list = quit_functions;
|
|
quit_functions = g_list_remove_link (quit_functions, quit_functions);
|
|
g_list_free_1 (tmp_list);
|
|
|
|
if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
|
|
gtk_quit_invoke_function (quitf))
|
|
{
|
|
reinvoke_list = g_list_prepend (reinvoke_list, quitf);
|
|
}
|
|
else
|
|
{
|
|
gtk_quit_destroy (quitf);
|
|
}
|
|
}
|
|
if (reinvoke_list)
|
|
{
|
|
GList *work;
|
|
|
|
work = g_list_last (reinvoke_list);
|
|
if (quit_functions)
|
|
quit_functions->prev = work;
|
|
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--;
|
|
}
|
|
|
|
guint
|
|
gtk_main_level (void)
|
|
{
|
|
return gtk_main_loop_level;
|
|
}
|
|
|
|
void
|
|
gtk_main_quit (void)
|
|
{
|
|
g_return_if_fail (main_loops != NULL);
|
|
|
|
g_main_quit (main_loops->data);
|
|
}
|
|
|
|
gint
|
|
gtk_events_pending (void)
|
|
{
|
|
gboolean result;
|
|
|
|
GDK_THREADS_LEAVE ();
|
|
result = g_main_pending();
|
|
GDK_THREADS_ENTER ();
|
|
|
|
return result;
|
|
}
|
|
|
|
gint
|
|
gtk_main_iteration (void)
|
|
{
|
|
GDK_THREADS_LEAVE ();
|
|
g_main_iteration (TRUE);
|
|
GDK_THREADS_ENTER ();
|
|
|
|
if (main_loops)
|
|
return !g_main_is_running (main_loops->data);
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
gint
|
|
gtk_main_iteration_do (gboolean blocking)
|
|
{
|
|
GDK_THREADS_LEAVE ();
|
|
g_main_iteration (blocking);
|
|
GDK_THREADS_ENTER ();
|
|
|
|
if (main_loops)
|
|
return !g_main_is_running (main_loops->data);
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
gtk_main_do_event (GdkEvent *event)
|
|
{
|
|
GtkWidget *event_widget;
|
|
GtkWidget *grab_widget;
|
|
GdkEvent *next_event;
|
|
GList *tmp_list;
|
|
|
|
/* If there are any events pending then get the next one.
|
|
*/
|
|
next_event = gdk_event_peek ();
|
|
|
|
/* Try to compress enter/leave notify events. These event
|
|
* pairs occur when the mouse is dragged quickly across
|
|
* a window with many buttons (or through a menu). Instead
|
|
* of highlighting and de-highlighting each widget that
|
|
* is crossed it is better to simply de-highlight the widget
|
|
* which contained the mouse initially and highlight the
|
|
* widget which ends up containing the mouse.
|
|
*/
|
|
if (next_event)
|
|
if (((event->type == GDK_ENTER_NOTIFY) ||
|
|
(event->type == GDK_LEAVE_NOTIFY)) &&
|
|
((next_event->type == GDK_ENTER_NOTIFY) ||
|
|
(next_event->type == GDK_LEAVE_NOTIFY)) &&
|
|
(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);
|
|
|
|
return;
|
|
}
|
|
|
|
if (next_event)
|
|
gdk_event_free (next_event);
|
|
|
|
/* Find the widget which got the event. We store the widget
|
|
* in the user_data field of GdkWindow's.
|
|
* Ignore the event if we don't have a widget for it, except
|
|
* for GDK_PROPERTY_NOTIFY events which are handled specialy.
|
|
* Though this happens rarely, bogus events can occour
|
|
* for e.g. destroyed GdkWindows.
|
|
*/
|
|
event_widget = gtk_get_event_widget (event);
|
|
if (!event_widget)
|
|
{
|
|
/* To handle selection INCR transactions, we select
|
|
* PropertyNotify events on the requestor window and create
|
|
* a corresponding (fake) GdkWindow so that events get
|
|
* here. There won't be a widget though, so we have to handle
|
|
* them specially
|
|
*/
|
|
if (event->type == GDK_PROPERTY_NOTIFY)
|
|
gtk_selection_incr_event (event->any.window,
|
|
&event->property);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Push the event onto a stack of current events for
|
|
* gtk_current_event_get().
|
|
*/
|
|
current_events = g_list_prepend (current_events, event);
|
|
|
|
/* If there is a grab in effect...
|
|
*/
|
|
if (grabs)
|
|
{
|
|
grab_widget = grabs->data;
|
|
|
|
/* If the grab widget is an ancestor of the event widget
|
|
* then we send the event to the original event widget.
|
|
* This is the key to implementing modality.
|
|
*/
|
|
if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
|
|
gtk_widget_is_ancestor (event_widget, grab_widget))
|
|
grab_widget = event_widget;
|
|
}
|
|
else
|
|
{
|
|
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
|
|
* 1) these events have no meaning for the grabbing widget
|
|
* and 2) redirecting these events to the grabbing widget
|
|
* could cause the display to be messed up.
|
|
*
|
|
* Drag events are also not redirected, since it isn't
|
|
* clear what the semantics of that would be.
|
|
*/
|
|
switch (event->type)
|
|
{
|
|
case GDK_NOTHING:
|
|
break;
|
|
|
|
case GDK_DELETE:
|
|
gtk_widget_ref (event_widget);
|
|
if ((!grabs || gtk_widget_get_toplevel (grabs->data) == event_widget) &&
|
|
!gtk_widget_event (event_widget, event))
|
|
gtk_widget_destroy (event_widget);
|
|
gtk_widget_unref (event_widget);
|
|
break;
|
|
|
|
case GDK_DESTROY:
|
|
/* Unexpected GDK_DESTROY from the outside, ignore for
|
|
* child windows, handle like a GDK_DELETE for toplevels
|
|
*/
|
|
if (!event_widget->parent)
|
|
{
|
|
gtk_widget_ref (event_widget);
|
|
if (!gtk_widget_event (event_widget, event) &&
|
|
!GTK_OBJECT_DESTROYED (event_widget))
|
|
gtk_widget_destroy (event_widget);
|
|
gtk_widget_unref (event_widget);
|
|
}
|
|
break;
|
|
|
|
case GDK_EXPOSE:
|
|
if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
|
|
gdk_window_begin_paint_rect (event->any.window, &event->expose.area);
|
|
|
|
gtk_widget_event (event_widget, event);
|
|
|
|
if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
|
|
gdk_window_end_paint (event->any.window);
|
|
break;
|
|
|
|
case GDK_PROPERTY_NOTIFY:
|
|
case GDK_NO_EXPOSE:
|
|
case GDK_FOCUS_CHANGE:
|
|
case GDK_CONFIGURE:
|
|
case GDK_MAP:
|
|
case GDK_UNMAP:
|
|
case GDK_SELECTION_CLEAR:
|
|
case GDK_SELECTION_REQUEST:
|
|
case GDK_SELECTION_NOTIFY:
|
|
case GDK_CLIENT_EVENT:
|
|
case GDK_VISIBILITY_NOTIFY:
|
|
gtk_widget_event (event_widget, event);
|
|
break;
|
|
|
|
case GDK_SCROLL:
|
|
case GDK_BUTTON_PRESS:
|
|
case GDK_2BUTTON_PRESS:
|
|
case GDK_3BUTTON_PRESS:
|
|
gtk_propagate_event (grab_widget, event);
|
|
break;
|
|
|
|
case GDK_KEY_PRESS:
|
|
case GDK_KEY_RELEASE:
|
|
if (key_snoopers)
|
|
{
|
|
if (gtk_invoke_key_snoopers (grab_widget, event))
|
|
break;
|
|
}
|
|
/* else fall through */
|
|
case GDK_MOTION_NOTIFY:
|
|
case GDK_BUTTON_RELEASE:
|
|
case GDK_PROXIMITY_IN:
|
|
case GDK_PROXIMITY_OUT:
|
|
gtk_propagate_event (grab_widget, event);
|
|
break;
|
|
|
|
case GDK_ENTER_NOTIFY:
|
|
if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
|
|
{
|
|
gtk_widget_event (grab_widget, event);
|
|
if (event_widget == grab_widget)
|
|
GTK_PRIVATE_SET_FLAG (event_widget, GTK_LEAVE_PENDING);
|
|
}
|
|
break;
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
|
if (GTK_WIDGET_LEAVE_PENDING (event_widget))
|
|
{
|
|
GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_LEAVE_PENDING);
|
|
gtk_widget_event (event_widget, event);
|
|
}
|
|
else if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
|
|
gtk_widget_event (grab_widget, event);
|
|
break;
|
|
|
|
case GDK_DRAG_STATUS:
|
|
case GDK_DROP_FINISHED:
|
|
gtk_drag_source_handle_event (event_widget, event);
|
|
break;
|
|
case GDK_DRAG_ENTER:
|
|
case GDK_DRAG_LEAVE:
|
|
case GDK_DRAG_MOTION:
|
|
case GDK_DROP_START:
|
|
gtk_drag_dest_handle_event (event_widget, event);
|
|
break;
|
|
}
|
|
|
|
tmp_list = current_events;
|
|
current_events = g_list_remove_link (current_events, tmp_list);
|
|
g_list_free_1 (tmp_list);
|
|
}
|
|
|
|
gint
|
|
gtk_true (void)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
gint
|
|
gtk_false (void)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gtk_grab_add (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (widget != NULL);
|
|
|
|
if (!GTK_WIDGET_HAS_GRAB (widget))
|
|
{
|
|
GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
|
|
|
|
grabs = g_slist_prepend (grabs, widget);
|
|
gtk_widget_ref (widget);
|
|
}
|
|
}
|
|
|
|
GtkWidget*
|
|
gtk_grab_get_current (void)
|
|
{
|
|
if (grabs)
|
|
return GTK_WIDGET (grabs->data);
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
gtk_grab_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (widget != NULL);
|
|
|
|
if (GTK_WIDGET_HAS_GRAB (widget))
|
|
{
|
|
GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
|
|
|
|
grabs = g_slist_remove (grabs, widget);
|
|
gtk_widget_unref (widget);
|
|
}
|
|
}
|
|
|
|
void
|
|
gtk_init_add (GtkFunction function,
|
|
gpointer data)
|
|
{
|
|
GtkInitFunction *init;
|
|
|
|
init = g_new (GtkInitFunction, 1);
|
|
init->function = function;
|
|
init->data = data;
|
|
|
|
init_functions = g_list_prepend (init_functions, init);
|
|
}
|
|
|
|
guint
|
|
gtk_key_snooper_install (GtkKeySnoopFunc snooper,
|
|
gpointer func_data)
|
|
{
|
|
GtkKeySnooperData *data;
|
|
static guint snooper_id = 1;
|
|
|
|
g_return_val_if_fail (snooper != NULL, 0);
|
|
|
|
data = g_new (GtkKeySnooperData, 1);
|
|
data->func = snooper;
|
|
data->func_data = func_data;
|
|
data->id = snooper_id++;
|
|
key_snoopers = g_slist_prepend (key_snoopers, data);
|
|
|
|
return data->id;
|
|
}
|
|
|
|
void
|
|
gtk_key_snooper_remove (guint snooper_id)
|
|
{
|
|
GtkKeySnooperData *data = NULL;
|
|
GSList *slist;
|
|
|
|
slist = key_snoopers;
|
|
while (slist)
|
|
{
|
|
data = slist->data;
|
|
if (data->id == snooper_id)
|
|
break;
|
|
|
|
slist = slist->next;
|
|
data = NULL;
|
|
}
|
|
if (data)
|
|
key_snoopers = g_slist_remove (key_snoopers, data);
|
|
}
|
|
|
|
static gint
|
|
gtk_invoke_key_snoopers (GtkWidget *grab_widget,
|
|
GdkEvent *event)
|
|
{
|
|
GSList *slist;
|
|
gint return_val = FALSE;
|
|
|
|
slist = key_snoopers;
|
|
while (slist && !return_val)
|
|
{
|
|
GtkKeySnooperData *data;
|
|
|
|
data = slist->data;
|
|
slist = slist->next;
|
|
return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
|
|
}
|
|
|
|
return return_val;
|
|
}
|
|
|
|
guint
|
|
gtk_quit_add_full (guint main_level,
|
|
GtkFunction function,
|
|
GtkCallbackMarshal marshal,
|
|
gpointer data,
|
|
GtkDestroyNotify destroy)
|
|
{
|
|
static guint quit_id = 1;
|
|
GtkQuitFunction *quitf;
|
|
|
|
g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
|
|
|
|
if (!quit_mem_chunk)
|
|
quit_mem_chunk = g_mem_chunk_new ("quit mem chunk", sizeof (GtkQuitFunction),
|
|
512, G_ALLOC_AND_FREE);
|
|
|
|
quitf = g_chunk_new (GtkQuitFunction, quit_mem_chunk);
|
|
|
|
quitf->id = quit_id++;
|
|
quitf->main_level = main_level;
|
|
quitf->function = function;
|
|
quitf->marshal = marshal;
|
|
quitf->data = data;
|
|
quitf->destroy = destroy;
|
|
|
|
quit_functions = g_list_prepend (quit_functions, quitf);
|
|
|
|
return quitf->id;
|
|
}
|
|
|
|
static void
|
|
gtk_quit_destroy (GtkQuitFunction *quitf)
|
|
{
|
|
if (quitf->destroy)
|
|
quitf->destroy (quitf->data);
|
|
g_mem_chunk_free (quit_mem_chunk, quitf);
|
|
}
|
|
|
|
static gint
|
|
gtk_quit_destructor (GtkObject **object_p)
|
|
{
|
|
if (*object_p)
|
|
gtk_object_destroy (*object_p);
|
|
g_free (object_p);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gtk_quit_add_destroy (guint main_level,
|
|
GtkObject *object)
|
|
{
|
|
GtkObject **object_p;
|
|
|
|
g_return_if_fail (main_level > 0);
|
|
g_return_if_fail (object != NULL);
|
|
g_return_if_fail (GTK_IS_OBJECT (object));
|
|
|
|
object_p = g_new (GtkObject*, 1);
|
|
*object_p = object;
|
|
gtk_signal_connect (object,
|
|
"destroy",
|
|
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
|
|
object_p);
|
|
gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
|
|
}
|
|
|
|
guint
|
|
gtk_quit_add (guint main_level,
|
|
GtkFunction function,
|
|
gpointer data)
|
|
{
|
|
return gtk_quit_add_full (main_level, function, NULL, data, NULL);
|
|
}
|
|
|
|
void
|
|
gtk_quit_remove (guint id)
|
|
{
|
|
GtkQuitFunction *quitf;
|
|
GList *tmp_list;
|
|
|
|
tmp_list = quit_functions;
|
|
while (tmp_list)
|
|
{
|
|
quitf = tmp_list->data;
|
|
|
|
if (quitf->id == id)
|
|
{
|
|
quit_functions = g_list_remove_link (quit_functions, tmp_list);
|
|
g_list_free (tmp_list);
|
|
gtk_quit_destroy (quitf);
|
|
|
|
return;
|
|
}
|
|
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
}
|
|
|
|
void
|
|
gtk_quit_remove_by_data (gpointer data)
|
|
{
|
|
GtkQuitFunction *quitf;
|
|
GList *tmp_list;
|
|
|
|
tmp_list = quit_functions;
|
|
while (tmp_list)
|
|
{
|
|
quitf = tmp_list->data;
|
|
|
|
if (quitf->data == data)
|
|
{
|
|
quit_functions = g_list_remove_link (quit_functions, tmp_list);
|
|
g_list_free (tmp_list);
|
|
gtk_quit_destroy (quitf);
|
|
|
|
return;
|
|
}
|
|
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
}
|
|
|
|
guint
|
|
gtk_timeout_add_full (guint32 interval,
|
|
GtkFunction function,
|
|
GtkCallbackMarshal marshal,
|
|
gpointer data,
|
|
GtkDestroyNotify destroy)
|
|
{
|
|
if (marshal)
|
|
{
|
|
GtkClosure *closure;
|
|
|
|
closure = g_new (GtkClosure, 1);
|
|
closure->marshal = marshal;
|
|
closure->data = data;
|
|
closure->destroy = destroy;
|
|
|
|
return g_timeout_add_full (0, interval,
|
|
gtk_invoke_idle_timeout,
|
|
closure,
|
|
gtk_destroy_closure);
|
|
}
|
|
else
|
|
return g_timeout_add_full (0, interval, function, data, destroy);
|
|
}
|
|
|
|
guint
|
|
gtk_timeout_add (guint32 interval,
|
|
GtkFunction function,
|
|
gpointer data)
|
|
{
|
|
return g_timeout_add_full (0, interval, function, data, NULL);
|
|
}
|
|
|
|
void
|
|
gtk_timeout_remove (guint tag)
|
|
{
|
|
g_source_remove (tag);
|
|
}
|
|
|
|
guint
|
|
gtk_idle_add_full (gint priority,
|
|
GtkFunction function,
|
|
GtkCallbackMarshal marshal,
|
|
gpointer data,
|
|
GtkDestroyNotify destroy)
|
|
{
|
|
if (marshal)
|
|
{
|
|
GtkClosure *closure;
|
|
|
|
closure = g_new (GtkClosure, 1);
|
|
closure->marshal = marshal;
|
|
closure->data = data;
|
|
closure->destroy = destroy;
|
|
|
|
return g_idle_add_full (priority,
|
|
gtk_invoke_idle_timeout,
|
|
closure,
|
|
gtk_destroy_closure);
|
|
}
|
|
else
|
|
return g_idle_add_full (priority, function, data, destroy);
|
|
}
|
|
|
|
guint
|
|
gtk_idle_add (GtkFunction function,
|
|
gpointer data)
|
|
{
|
|
return g_idle_add_full (GTK_PRIORITY_DEFAULT, function, data, NULL);
|
|
}
|
|
|
|
guint
|
|
gtk_idle_add_priority (gint priority,
|
|
GtkFunction function,
|
|
gpointer data)
|
|
{
|
|
return g_idle_add_full (priority, function, data, NULL);
|
|
}
|
|
|
|
void
|
|
gtk_idle_remove (guint tag)
|
|
{
|
|
g_source_remove (tag);
|
|
}
|
|
|
|
void
|
|
gtk_idle_remove_by_data (gpointer data)
|
|
{
|
|
if (!g_idle_remove_by_data (data))
|
|
g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
|
|
}
|
|
|
|
guint
|
|
gtk_input_add_full (gint source,
|
|
GdkInputCondition condition,
|
|
GdkInputFunction function,
|
|
GtkCallbackMarshal marshal,
|
|
gpointer data,
|
|
GtkDestroyNotify destroy)
|
|
{
|
|
if (marshal)
|
|
{
|
|
GtkClosure *closure;
|
|
|
|
closure = g_new (GtkClosure, 1);
|
|
closure->marshal = marshal;
|
|
closure->data = data;
|
|
closure->destroy = destroy;
|
|
|
|
return gdk_input_add_full (source,
|
|
condition,
|
|
(GdkInputFunction) gtk_invoke_input,
|
|
closure,
|
|
(GdkDestroyNotify) gtk_destroy_closure);
|
|
}
|
|
else
|
|
return gdk_input_add_full (source, condition, function, data, destroy);
|
|
}
|
|
|
|
void
|
|
gtk_input_remove (guint tag)
|
|
{
|
|
g_source_remove (tag);
|
|
}
|
|
|
|
static void
|
|
gtk_destroy_closure (gpointer data)
|
|
{
|
|
GtkClosure *closure = data;
|
|
|
|
if (closure->destroy)
|
|
(closure->destroy) (closure->data);
|
|
g_free (closure);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_invoke_idle_timeout (gpointer data)
|
|
{
|
|
GtkClosure *closure = data;
|
|
|
|
GtkArg args[1];
|
|
gint ret_val = FALSE;
|
|
args[0].name = NULL;
|
|
args[0].type = GTK_TYPE_BOOL;
|
|
args[0].d.pointer_data = &ret_val;
|
|
closure->marshal (NULL, closure->data, 0, args);
|
|
return ret_val;
|
|
}
|
|
|
|
static void
|
|
gtk_invoke_input (gpointer data,
|
|
gint source,
|
|
GdkInputCondition condition)
|
|
{
|
|
GtkClosure *closure = data;
|
|
|
|
GtkArg args[3];
|
|
args[0].type = GTK_TYPE_INT;
|
|
args[0].name = NULL;
|
|
GTK_VALUE_INT(args[0]) = source;
|
|
args[1].type = GTK_TYPE_GDK_INPUT_CONDITION;
|
|
args[1].name = NULL;
|
|
GTK_VALUE_FLAGS(args[1]) = condition;
|
|
args[2].type = GTK_TYPE_NONE;
|
|
args[2].name = NULL;
|
|
|
|
closure->marshal (NULL, closure->data, 2, args);
|
|
}
|
|
|
|
GdkEvent*
|
|
gtk_get_current_event (void)
|
|
{
|
|
if (current_events)
|
|
return gdk_event_copy (current_events->data);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gtk_get_current_event_time:
|
|
*
|
|
* If there is a current event and it has a timestamp, return that
|
|
* timestamp, otherwise return %GDK_CURRENT_TIME.
|
|
*
|
|
* Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
|
|
**/
|
|
guint32
|
|
gtk_get_current_event_time (void)
|
|
{
|
|
if (current_events)
|
|
return gdk_event_get_time (current_events->data);
|
|
else
|
|
return GDK_CURRENT_TIME;
|
|
}
|
|
|
|
gboolean
|
|
gtk_get_current_event_state (GdkModifierType *state)
|
|
{
|
|
g_return_val_if_fail (state != NULL, FALSE);
|
|
|
|
if (current_events)
|
|
return gdk_event_get_state (current_events->data, state);
|
|
else
|
|
{
|
|
*state = 0;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
GtkWidget*
|
|
gtk_get_event_widget (GdkEvent *event)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
widget = NULL;
|
|
if (event && event->any.window)
|
|
gdk_window_get_user_data (event->any.window, (void**) &widget);
|
|
|
|
return widget;
|
|
}
|
|
|
|
static void
|
|
gtk_exit_func (void)
|
|
{
|
|
if (gtk_initialized)
|
|
{
|
|
gtk_initialized = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
static gint
|
|
gtk_quit_invoke_function (GtkQuitFunction *quitf)
|
|
{
|
|
if (!quitf->marshal)
|
|
return quitf->function (quitf->data);
|
|
else
|
|
{
|
|
GtkArg args[1];
|
|
gint ret_val = FALSE;
|
|
|
|
args[0].name = NULL;
|
|
args[0].type = GTK_TYPE_BOOL;
|
|
args[0].d.pointer_data = &ret_val;
|
|
((GtkCallbackMarshal) quitf->marshal) (NULL,
|
|
quitf->data,
|
|
0, args);
|
|
return ret_val;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
if ((event->type == GDK_KEY_PRESS) ||
|
|
(event->type == GDK_KEY_RELEASE))
|
|
{
|
|
/* Only send key events within Window widgets to the Window
|
|
* The Window widget will in turn pass the
|
|
* key event on to the currently focused widget
|
|
* for that window.
|
|
*/
|
|
GtkWidget *window;
|
|
|
|
window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
|
|
if (window)
|
|
{
|
|
if (GTK_WIDGET_IS_SENSITIVE (window))
|
|
gtk_widget_event (window, event);
|
|
|
|
handled_event = TRUE; /* don't send to widget */
|
|
}
|
|
}
|
|
|
|
/* Other events get propagated up the widget tree
|
|
* so that parents can see the button and motion
|
|
* events of the children.
|
|
*/
|
|
while (!handled_event && widget)
|
|
{
|
|
GtkWidget *tmp;
|
|
|
|
gtk_widget_ref (widget);
|
|
handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event);
|
|
tmp = widget->parent;
|
|
gtk_widget_unref (widget);
|
|
widget = tmp;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
gtk_error (gchar *str)
|
|
{
|
|
gtk_print (str);
|
|
}
|
|
|
|
static void
|
|
gtk_warning (gchar *str)
|
|
{
|
|
gtk_print (str);
|
|
}
|
|
|
|
static void
|
|
gtk_message (gchar *str)
|
|
{
|
|
gtk_print (str);
|
|
}
|
|
|
|
static void
|
|
gtk_print (gchar *str)
|
|
{
|
|
static GtkWidget *window = NULL;
|
|
static GtkWidget *text;
|
|
static int level = 0;
|
|
GtkWidget *box1;
|
|
GtkWidget *box2;
|
|
GtkWidget *table;
|
|
GtkWidget *hscrollbar;
|
|
GtkWidget *vscrollbar;
|
|
GtkWidget *separator;
|
|
GtkWidget *button;
|
|
|
|
if (level > 0)
|
|
{
|
|
fputs (str, stdout);
|
|
fflush (stdout);
|
|
return;
|
|
}
|
|
|
|
if (!window)
|
|
{
|
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (window), "destroy",
|
|
(GtkSignalFunc) gtk_widget_destroyed,
|
|
&window);
|
|
|
|
gtk_window_set_title (GTK_WINDOW (window), "Messages");
|
|
|
|
box1 = gtk_vbox_new (FALSE, 0);
|
|
gtk_container_add (GTK_CONTAINER (window), box1);
|
|
gtk_widget_show (box1);
|
|
|
|
|
|
box2 = gtk_vbox_new (FALSE, 10);
|
|
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
|
|
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
|
|
gtk_widget_show (box2);
|
|
|
|
|
|
table = gtk_table_new (2, 2, FALSE);
|
|
gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
|
|
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
|
|
gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
|
|
gtk_widget_show (table);
|
|
|
|
text = gtk_text_new (NULL, NULL);
|
|
gtk_text_set_editable (GTK_TEXT (text), FALSE);
|
|
gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
|
|
gtk_widget_show (text);
|
|
gtk_widget_realize (text);
|
|
|
|
hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
|
|
gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
|
|
GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
|
|
gtk_widget_show (hscrollbar);
|
|
|
|
vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
|
|
gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
|
|
GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
|
|
gtk_widget_show (vscrollbar);
|
|
|
|
separator = gtk_hseparator_new ();
|
|
gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
|
|
gtk_widget_show (separator);
|
|
|
|
|
|
box2 = gtk_vbox_new (FALSE, 10);
|
|
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
|
|
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
|
|
gtk_widget_show (box2);
|
|
|
|
|
|
button = gtk_button_new_with_label ("close");
|
|
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
|
|
(GtkSignalFunc) gtk_widget_hide,
|
|
GTK_OBJECT (window));
|
|
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
|
|
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
|
|
gtk_widget_grab_default (button);
|
|
gtk_widget_show (button);
|
|
}
|
|
|
|
level += 1;
|
|
gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
|
|
level -= 1;
|
|
|
|
if (!GTK_WIDGET_VISIBLE (window))
|
|
gtk_widget_show (window);
|
|
}
|
|
#endif
|