X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktooltips.c;h=d203082d7cfdeb0355e0cd6286b13f6fe4f0148e;hb=ce503485cb983a0e49220d8b92f23aca2d0b9132;hp=fb25448f51d1c27437b3a57c6362c039705c447f;hpb=90f398a4132bdc09718508be8e0f58d7696ac82e;p=~andy%2Fgtk diff --git a/gtk/gtktooltips.c b/gtk/gtktooltips.c index fb25448f5..d203082d7 100644 --- a/gtk/gtktooltips.c +++ b/gtk/gtktooltips.c @@ -24,17 +24,21 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +#include #include #include #include #include "gtklabel.h" #include "gtkmain.h" +#include "gtkmenuitem.h" +#include "gtkprivate.h" #include "gtkwidget.h" #include "gtkwindow.h" -#include "gtksignal.h" #include "gtkstyle.h" #include "gtktooltips.h" +#include "gtkintl.h" +#include "gtkalias.h" #define DEFAULT_DELAY 500 /* Default delay in ms */ @@ -45,11 +49,9 @@ * to normal */ -static void gtk_tooltips_class_init (GtkTooltipsClass *klass); -static void gtk_tooltips_init (GtkTooltips *tooltips); static void gtk_tooltips_destroy (GtkObject *object); -static gint gtk_tooltips_event_handler (GtkWidget *widget, +static void gtk_tooltips_event_handler (GtkWidget *widget, GdkEvent *event); static void gtk_tooltips_widget_unmap (GtkWidget *widget, gpointer data); @@ -61,34 +63,14 @@ static gint gtk_tooltips_timeout (gpointer data); static gint gtk_tooltips_paint_window (GtkTooltips *tooltips); static void gtk_tooltips_draw_tips (GtkTooltips *tooltips); +static void gtk_tooltips_unset_tip_window (GtkTooltips *tooltips); -static GtkObjectClass *parent_class; -static const gchar *tooltips_data_key = "_GtkTooltipsData"; +static gboolean get_keyboard_mode (GtkWidget *widget); -GtkType -gtk_tooltips_get_type (void) -{ - static GtkType tooltips_type = 0; - - if (!tooltips_type) - { - static const GtkTypeInfo tooltips_info = - { - "GtkTooltips", - sizeof (GtkTooltips), - sizeof (GtkTooltipsClass), - (GtkClassInitFunc) gtk_tooltips_class_init, - (GtkObjectInitFunc) gtk_tooltips_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - tooltips_type = gtk_type_unique (GTK_TYPE_OBJECT, &tooltips_info); - } +static const gchar tooltips_data_key[] = "_GtkTooltipsData"; +static const gchar tooltips_info_key[] = "_GtkTooltipsInfo"; - return tooltips_type; -} +G_DEFINE_TYPE (GtkTooltips, gtk_tooltips, GTK_TYPE_OBJECT) static void gtk_tooltips_class_init (GtkTooltipsClass *class) @@ -96,7 +78,6 @@ gtk_tooltips_class_init (GtkTooltipsClass *class) GtkObjectClass *object_class; object_class = (GtkObjectClass*) class; - parent_class = gtk_type_class (GTK_TYPE_OBJECT); object_class->destroy = gtk_tooltips_destroy; } @@ -119,7 +100,7 @@ gtk_tooltips_init (GtkTooltips *tooltips) GtkTooltips * gtk_tooltips_new (void) { - return gtk_type_new (GTK_TYPE_TOOLTIPS); + return g_object_new (GTK_TYPE_TOOLTIPS, NULL); } static void @@ -127,13 +108,50 @@ gtk_tooltips_destroy_data (GtkTooltipsData *tooltipsdata) { g_free (tooltipsdata->tip_text); g_free (tooltipsdata->tip_private); - gtk_signal_disconnect_by_data (GTK_OBJECT (tooltipsdata->widget), - (gpointer) tooltipsdata); - gtk_object_remove_data (GTK_OBJECT (tooltipsdata->widget), tooltips_data_key); - gtk_widget_unref (tooltipsdata->widget); + + g_signal_handlers_disconnect_by_func (tooltipsdata->widget, + gtk_tooltips_event_handler, + tooltipsdata); + g_signal_handlers_disconnect_by_func (tooltipsdata->widget, + gtk_tooltips_widget_unmap, + tooltipsdata); + g_signal_handlers_disconnect_by_func (tooltipsdata->widget, + gtk_tooltips_widget_remove, + tooltipsdata); + + g_object_set_data (G_OBJECT (tooltipsdata->widget), I_(tooltips_data_key), NULL); + g_object_unref (tooltipsdata->widget); g_free (tooltipsdata); } +static void +tip_window_display_closed (GdkDisplay *display, + gboolean was_error, + GtkTooltips *tooltips) +{ + gtk_tooltips_unset_tip_window (tooltips); +} + +static void +disconnect_tip_window_display_closed (GtkTooltips *tooltips) +{ + g_signal_handlers_disconnect_by_func (gtk_widget_get_display (tooltips->tip_window), + (gpointer) tip_window_display_closed, + tooltips); +} + +static void +gtk_tooltips_unset_tip_window (GtkTooltips *tooltips) +{ + if (tooltips->tip_window) + { + disconnect_tip_window_display_closed (tooltips); + + gtk_widget_destroy (tooltips->tip_window); + tooltips->tip_window = NULL; + } +} + static void gtk_tooltips_destroy (GtkObject *object) { @@ -145,7 +163,7 @@ gtk_tooltips_destroy (GtkObject *object) if (tooltips->timer_tag) { - gtk_timeout_remove (tooltips->timer_tag); + g_source_remove (tooltips->timer_tag); tooltips->timer_tag = 0; } @@ -160,28 +178,58 @@ gtk_tooltips_destroy (GtkObject *object) } } - if (tooltips->tip_window) - gtk_widget_destroy (tooltips->tip_window); + gtk_tooltips_unset_tip_window (tooltips); + + GTK_OBJECT_CLASS (gtk_tooltips_parent_class)->destroy (object); +} + +static void +gtk_tooltips_update_screen (GtkTooltips *tooltips, + gboolean new_window) +{ + gboolean screen_changed = FALSE; + + if (tooltips->active_tips_data && + tooltips->active_tips_data->widget) + { + GdkScreen *screen = gtk_widget_get_screen (tooltips->active_tips_data->widget); + + screen_changed = (screen != gtk_widget_get_screen (tooltips->tip_window)); + + if (screen_changed) + { + if (!new_window) + disconnect_tip_window_display_closed (tooltips); + + gtk_window_set_screen (GTK_WINDOW (tooltips->tip_window), screen); + } + } + + if (screen_changed || new_window) + g_signal_connect (gtk_widget_get_display (tooltips->tip_window), "closed", + G_CALLBACK (tip_window_display_closed), tooltips); + } void gtk_tooltips_force_window (GtkTooltips *tooltips) { - g_return_if_fail (tooltips != NULL); g_return_if_fail (GTK_IS_TOOLTIPS (tooltips)); if (!tooltips->tip_window) { tooltips->tip_window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_type_hint (GTK_WINDOW (tooltips->tip_window), GDK_WINDOW_TYPE_HINT_TOOLTIP); + gtk_tooltips_update_screen (tooltips, TRUE); gtk_widget_set_app_paintable (tooltips->tip_window, TRUE); - gtk_window_set_policy (GTK_WINDOW (tooltips->tip_window), FALSE, FALSE, TRUE); + gtk_window_set_resizable (GTK_WINDOW (tooltips->tip_window), FALSE); gtk_widget_set_name (tooltips->tip_window, "gtk-tooltips"); gtk_container_set_border_width (GTK_CONTAINER (tooltips->tip_window), 4); - gtk_signal_connect_object (GTK_OBJECT (tooltips->tip_window), - "expose_event", - GTK_SIGNAL_FUNC (gtk_tooltips_paint_window), - GTK_OBJECT (tooltips)); + g_signal_connect_swapped (tooltips->tip_window, + "expose_event", + G_CALLBACK (gtk_tooltips_paint_window), + tooltips); tooltips->tip_label = gtk_label_new (NULL); gtk_label_set_line_wrap (GTK_LABEL (tooltips->tip_label), TRUE); @@ -190,10 +238,10 @@ gtk_tooltips_force_window (GtkTooltips *tooltips) gtk_container_add (GTK_CONTAINER (tooltips->tip_window), tooltips->tip_label); - gtk_signal_connect (GTK_OBJECT (tooltips->tip_window), - "destroy", - GTK_SIGNAL_FUNC (gtk_widget_destroyed), - &tooltips->tip_window); + g_signal_connect (tooltips->tip_window, + "destroy", + G_CALLBACK (gtk_widget_destroyed), + &tooltips->tip_window); } } @@ -229,7 +277,7 @@ gtk_tooltips_data_get (GtkWidget *widget) { g_return_val_if_fail (widget != NULL, NULL); - return gtk_object_get_data ((GtkObject*) widget, tooltips_data_key); + return g_object_get_data (G_OBJECT (widget), tooltips_data_key); } void @@ -240,97 +288,112 @@ gtk_tooltips_set_tip (GtkTooltips *tooltips, { GtkTooltipsData *tooltipsdata; - g_return_if_fail (tooltips != NULL); g_return_if_fail (GTK_IS_TOOLTIPS (tooltips)); g_return_if_fail (widget != NULL); tooltipsdata = gtk_tooltips_data_get (widget); - if (tooltipsdata) - gtk_tooltips_widget_remove (tooltipsdata->widget, tooltipsdata); if (!tip_text) - return; - - tooltipsdata = g_new0 (GtkTooltipsData, 1); + { + if (tooltipsdata) + gtk_tooltips_widget_remove (tooltipsdata->widget, tooltipsdata); + return; + } + + if (tooltips->active_tips_data + && tooltips->active_tips_data->widget == widget + && GTK_WIDGET_DRAWABLE (tooltips->active_tips_data->widget)) + { + g_free (tooltipsdata->tip_text); + g_free (tooltipsdata->tip_private); - if (tooltipsdata != NULL) + tooltipsdata->tip_text = g_strdup (tip_text); + tooltipsdata->tip_private = g_strdup (tip_private); + + gtk_tooltips_draw_tips (tooltips); + } + else { + g_object_ref (widget); + + if (tooltipsdata) + gtk_tooltips_widget_remove (tooltipsdata->widget, tooltipsdata); + + tooltipsdata = g_new0 (GtkTooltipsData, 1); + tooltipsdata->tooltips = tooltips; tooltipsdata->widget = widget; - gtk_widget_ref (widget); tooltipsdata->tip_text = g_strdup (tip_text); tooltipsdata->tip_private = g_strdup (tip_private); tooltips->tips_data_list = g_list_append (tooltips->tips_data_list, - tooltipsdata); - gtk_signal_connect_after(GTK_OBJECT (widget), "event", - (GtkSignalFunc) gtk_tooltips_event_handler, - (gpointer) tooltipsdata); + tooltipsdata); + g_signal_connect_after (widget, "event_after", + G_CALLBACK (gtk_tooltips_event_handler), + tooltipsdata); - gtk_object_set_data (GTK_OBJECT (widget), tooltips_data_key, - (gpointer) tooltipsdata); + g_object_set_data (G_OBJECT (widget), I_(tooltips_data_key), + tooltipsdata); - gtk_signal_connect (GTK_OBJECT (widget), "unmap", - (GtkSignalFunc) gtk_tooltips_widget_unmap, - (gpointer) tooltipsdata); + g_signal_connect (widget, "unmap", + G_CALLBACK (gtk_tooltips_widget_unmap), + tooltipsdata); - gtk_signal_connect (GTK_OBJECT (widget), "unrealize", - (GtkSignalFunc) gtk_tooltips_widget_unmap, - (gpointer) tooltipsdata); + g_signal_connect (widget, "unrealize", + G_CALLBACK (gtk_tooltips_widget_unmap), + tooltipsdata); - gtk_signal_connect (GTK_OBJECT (widget), "destroy", - (GtkSignalFunc) gtk_tooltips_widget_remove, - (gpointer) tooltipsdata); + g_signal_connect (widget, "destroy", + G_CALLBACK (gtk_tooltips_widget_remove), + tooltipsdata); } } -void -gtk_tooltips_set_colors (GtkTooltips *tooltips, - GdkColor *background, - GdkColor *foreground) -{ - g_return_if_fail (tooltips != NULL); - - g_warning ("gtk_tooltips_set_colors is deprecated and does nothing.\n" - "The colors for tooltips are now taken from the style."); -} - static gint gtk_tooltips_paint_window (GtkTooltips *tooltips) { - gtk_paint_flat_box(tooltips->tip_window->style, tooltips->tip_window->window, - GTK_STATE_NORMAL, GTK_SHADOW_OUT, - NULL, GTK_WIDGET(tooltips->tip_window), "tooltip", - 0, 0, -1, -1); + GtkRequisition req; + + gtk_widget_size_request (tooltips->tip_window, &req); + gtk_paint_flat_box (tooltips->tip_window->style, tooltips->tip_window->window, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + NULL, GTK_WIDGET(tooltips->tip_window), "tooltip", + 0, 0, req.width, req.height); - return TRUE; + return FALSE; } static void -gtk_tooltips_draw_tips (GtkTooltips * tooltips) +gtk_tooltips_draw_tips (GtkTooltips *tooltips) { GtkRequisition requisition; GtkWidget *widget; - GtkStyle *style; - gint x, y, w, h, scr_w, scr_h; + gint x, y, w, h; GtkTooltipsData *data; + gboolean keyboard_mode; + GdkScreen *screen; + GdkScreen *pointer_screen; + gint monitor_num, px, py; + GdkRectangle monitor; + GtkWindow *toplevel; if (!tooltips->tip_window) gtk_tooltips_force_window (tooltips); else if (GTK_WIDGET_VISIBLE (tooltips->tip_window)) - { - gtk_widget_hide (tooltips->tip_window); - g_get_current_time (&tooltips->last_popdown); - } + g_get_current_time (&tooltips->last_popdown); gtk_widget_ensure_style (tooltips->tip_window); - style = tooltips->tip_window->style; widget = tooltips->active_tips_data->widget; + g_object_set_data (G_OBJECT (tooltips->tip_window), I_(tooltips_info_key), + tooltips); - scr_w = gdk_screen_width (); - scr_h = gdk_screen_height (); + keyboard_mode = get_keyboard_mode (widget); + + gtk_tooltips_update_screen (tooltips, FALSE); + + screen = gtk_widget_get_screen (widget); data = tooltips->active_tips_data; @@ -340,24 +403,47 @@ gtk_tooltips_draw_tips (GtkTooltips * tooltips) w = requisition.width; h = requisition.height; - gdk_window_get_pointer (NULL, &x, NULL, NULL); - gdk_window_get_origin (widget->window, NULL, &y); + gdk_window_get_origin (widget->window, &x, &y); if (GTK_WIDGET_NO_WINDOW (widget)) - y += widget->allocation.y; + { + x += widget->allocation.x; + y += widget->allocation.y; + } + + x += widget->allocation.width / 2; + + if (!keyboard_mode) + gdk_window_get_pointer (gdk_screen_get_root_window (screen), + &x, NULL, NULL); x -= (w / 2 + 4); - if ((x + w) > scr_w) - x -= (x + w) - scr_w; - else if (x < 0) - x = 0; + gdk_display_get_pointer (gdk_screen_get_display (screen), + &pointer_screen, &px, &py, NULL); + if (pointer_screen != screen) + { + px = x; + py = y; + } + monitor_num = gdk_screen_get_monitor_at_point (screen, px, py); + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); - if ((y + h + widget->allocation.height + 4) > scr_h) + if ((x + w) > monitor.x + monitor.width) + x -= (x + w) - (monitor.x + monitor.width); + else if (x < monitor.x) + x = monitor.x; + + if ((y + h + widget->allocation.height + 4) > monitor.y + monitor.height) y = y - h - 4; else y = y + widget->allocation.height + 4; - gtk_widget_popup (tooltips->tip_window, x, y); + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (widget)); + if (toplevel && GTK_IS_WINDOW (toplevel)) + gtk_window_set_transient_for (GTK_WINDOW (tooltips->tip_window), toplevel); + + gtk_window_move (GTK_WINDOW (tooltips->tip_window), x, y); + gtk_widget_show (tooltips->tip_window); } static gint @@ -371,6 +457,8 @@ gtk_tooltips_timeout (gpointer data) GTK_WIDGET_DRAWABLE (tooltips->active_tips_data->widget)) gtk_tooltips_draw_tips (tooltips); + tooltips->timer_tag = 0; + GDK_THREADS_LEAVE (); return FALSE; @@ -388,7 +476,7 @@ gtk_tooltips_set_active_widget (GtkTooltips *tooltips, } if (tooltips->timer_tag) { - gtk_timeout_remove (tooltips->timer_tag); + g_source_remove (tooltips->timer_tag); tooltips->timer_tag = 0; } @@ -418,6 +506,35 @@ gtk_tooltips_set_active_widget (GtkTooltips *tooltips, } } +static void +gtk_tooltips_show_tip (GtkWidget *widget) +{ + GtkTooltipsData *tooltipsdata; + + tooltipsdata = gtk_tooltips_data_get (widget); + + if (tooltipsdata && + (!tooltipsdata->tooltips->active_tips_data || + tooltipsdata->tooltips->active_tips_data->widget != widget)) + { + gtk_tooltips_set_active_widget (tooltipsdata->tooltips, widget); + gtk_tooltips_draw_tips (tooltipsdata->tooltips); + } +} + +static void +gtk_tooltips_hide_tip (GtkWidget *widget) +{ + GtkTooltipsData *tooltipsdata; + + tooltipsdata = gtk_tooltips_data_get (widget); + + if (tooltipsdata && + (tooltipsdata->tooltips->active_tips_data && + tooltipsdata->tooltips->active_tips_data->widget == widget)) + gtk_tooltips_set_active_widget (tooltipsdata->tooltips, NULL); +} + static gboolean gtk_tooltips_recently_shown (GtkTooltips *tooltips) { @@ -430,70 +547,171 @@ gtk_tooltips_recently_shown (GtkTooltips *tooltips) return (msec < STICKY_REVERT_DELAY); } -static gint +static gboolean +get_keyboard_mode (GtkWidget *widget) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (widget); + if (GTK_IS_WINDOW (toplevel)) + return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toplevel), "gtk-tooltips-keyboard-mode")); + else + return FALSE; +} + +static void +start_keyboard_mode (GtkWidget *widget) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (widget); + if (GTK_IS_WINDOW (toplevel)) + { + GtkWidget *focus = GTK_WINDOW (toplevel)->focus_widget; + + g_object_set_data (G_OBJECT (toplevel), I_("gtk-tooltips-keyboard-mode"), GUINT_TO_POINTER (TRUE)); + + if (focus) + gtk_tooltips_show_tip (focus); + } +} + +static void +stop_keyboard_mode (GtkWidget *widget) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (widget); + if (GTK_IS_WINDOW (toplevel)) + { + GtkWidget *focus = GTK_WINDOW (toplevel)->focus_widget; + if (focus) + gtk_tooltips_hide_tip (focus); + + g_object_set_data (G_OBJECT (toplevel), I_("gtk-tooltips-keyboard-mode"), GUINT_TO_POINTER (FALSE)); + } +} + +static gboolean +tooltips_enabled (GtkTooltips *tooltips, GtkWidget *w) +{ + GtkSettings *settings; + gboolean touchscreen; + + if (!tooltips->enabled) + return FALSE; + + settings = gtk_widget_get_settings (w); + g_object_get (settings, "gtk-touchscreen-mode", &touchscreen, NULL); + + return !touchscreen; +} + +static void +gtk_tooltips_start_delay (GtkTooltips *tooltips, + GtkWidget *widget) +{ + GtkTooltipsData *old_tips_data; + + old_tips_data = tooltips->active_tips_data; + if (tooltips_enabled (tooltips, widget) && + (!old_tips_data || old_tips_data->widget != widget)) + { + guint delay; + + gtk_tooltips_set_active_widget (tooltips, widget); + + if (tooltips->use_sticky_delay && + gtk_tooltips_recently_shown (tooltips)) + delay = STICKY_DELAY; + else + delay = tooltips->delay; + tooltips->timer_tag = g_timeout_add (delay, + gtk_tooltips_timeout, + (gpointer) tooltips); + } +} + +static void gtk_tooltips_event_handler (GtkWidget *widget, GdkEvent *event) { GtkTooltips *tooltips; GtkTooltipsData *old_tips_data; GtkWidget *event_widget; + gboolean keyboard_mode = get_keyboard_mode (widget); if ((event->type == GDK_LEAVE_NOTIFY || event->type == GDK_ENTER_NOTIFY) && event->crossing.detail == GDK_NOTIFY_INFERIOR) - return FALSE; + return; - event_widget = gtk_get_event_widget (event); - if (event_widget != widget) - return FALSE; - old_tips_data = gtk_tooltips_data_get (widget); tooltips = old_tips_data->tooltips; - switch (event->type) + if (keyboard_mode) { - case GDK_MOTION_NOTIFY: - case GDK_EXPOSE: - /* do nothing */ - break; - - case GDK_ENTER_NOTIFY: - old_tips_data = tooltips->active_tips_data; - if (tooltips->enabled && - (!old_tips_data || old_tips_data->widget != widget)) + switch (event->type) { - guint delay; - - gtk_tooltips_set_active_widget (tooltips, widget); - - if (tooltips->use_sticky_delay && - gtk_tooltips_recently_shown (tooltips)) - delay = STICKY_DELAY; + case GDK_FOCUS_CHANGE: + if (event->focus_change.in) + gtk_tooltips_show_tip (widget); else - delay = tooltips->delay; - tooltips->timer_tag = gtk_timeout_add (delay, - gtk_tooltips_timeout, - (gpointer) tooltips); + gtk_tooltips_hide_tip (widget); + break; + default: + break; + } + } + else + { + if (event->type != GDK_KEY_PRESS && event->type != GDK_KEY_RELEASE) + { + event_widget = gtk_get_event_widget (event); + if (event_widget != widget) + return; + } + + switch (event->type) + { + case GDK_EXPOSE: + /* do nothing */ + break; + case GDK_ENTER_NOTIFY: + if (!(GTK_IS_MENU_ITEM (widget) && GTK_MENU_ITEM (widget)->submenu)) + gtk_tooltips_start_delay (tooltips, widget); + break; + + case GDK_LEAVE_NOTIFY: + { + gboolean use_sticky_delay; + + use_sticky_delay = tooltips->tip_window && + GTK_WIDGET_VISIBLE (tooltips->tip_window); + gtk_tooltips_set_active_widget (tooltips, NULL); + tooltips->use_sticky_delay = use_sticky_delay; + } + break; + + case GDK_MOTION_NOTIFY: + /* Handle menu items specially ... pend popup for each motion + * on other widgets, we ignore motion. + */ + if (GTK_IS_MENU_ITEM (widget) && !GTK_MENU_ITEM (widget)->submenu) + { + /* Completely evil hack to make sure we get the LEAVE_NOTIFY + */ + GTK_PRIVATE_SET_FLAG (widget, GTK_LEAVE_PENDING); + gtk_tooltips_set_active_widget (tooltips, NULL); + gtk_tooltips_start_delay (tooltips, widget); + break; + } + break; /* ignore */ + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + case GDK_PROXIMITY_IN: + case GDK_SCROLL: + gtk_tooltips_set_active_widget (tooltips, NULL); + break; + default: + break; } - break; - - case GDK_LEAVE_NOTIFY: - { - gboolean use_sticky_delay; - - use_sticky_delay = tooltips->tip_window && - GTK_WIDGET_VISIBLE (tooltips->tip_window); - gtk_tooltips_set_active_widget (tooltips, NULL); - tooltips->use_sticky_delay = use_sticky_delay; - } - break; - - default: - gtk_tooltips_set_active_widget (tooltips, NULL); - return FALSE; - break; } - - return FALSE; } static void @@ -520,3 +738,55 @@ gtk_tooltips_widget_remove (GtkWidget *widget, tooltipsdata); gtk_tooltips_destroy_data (tooltipsdata); } + +void +_gtk_tooltips_toggle_keyboard_mode (GtkWidget *widget) +{ + if (get_keyboard_mode (widget)) + stop_keyboard_mode (widget); + else + start_keyboard_mode (widget); +} + +/** + * gtk_tooltips_get_info_from_tip_window: + * @tip_window: a #GtkWindow + * @tooltips: the return location for the tooltips which are displayed + * in @tip_window, or %NULL + * @current_widget: the return location for the widget whose tooltips + * are displayed, or %NULL + * + * Determines the tooltips and the widget they belong to from the window in + * which they are displayed. + * + * This function is mostly intended for use by accessibility technologies; + * applications should have little use for it. + * + * Return value: %TRUE if @tip_window is displaying tooltips, otherwise %FALSE. + * + * Since: 2.4 + **/ +gboolean +gtk_tooltips_get_info_from_tip_window (GtkWindow *tip_window, + GtkTooltips **tooltips, + GtkWidget **current_widget) +{ + GtkTooltips *current_tooltips; + gboolean has_tips; + + g_return_val_if_fail (GTK_IS_WINDOW (tip_window), FALSE); + + current_tooltips = g_object_get_data (G_OBJECT (tip_window), tooltips_info_key); + + has_tips = current_tooltips != NULL; + + if (tooltips) + *tooltips = current_tooltips; + if (current_widget) + *current_widget = has_tips ? current_tooltips->active_tips_data->widget : NULL; + + return has_tips; +} + +#define __GTK_TOOLTIPS_C__ +#include "gtkaliasdef.c"