static void gtk_tooltips_destroy_data (GtkTooltipsData *tooltipsdata);
-static void gtk_tooltips_event_handler (GtkWidget *widget,
- GdkEvent *event);
-static void gtk_tooltips_widget_unmap (GtkWidget *widget,
- gpointer data);
static void gtk_tooltips_widget_remove (GtkWidget *widget,
gpointer data);
-static void gtk_tooltips_set_active_widget (GtkTooltips *tooltips,
- GtkWidget *widget);
-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 gboolean get_keyboard_mode (GtkWidget *widget);
static const gchar tooltips_data_key[] = "_GtkTooltipsData";
static const gchar tooltips_info_key[] = "_GtkTooltipsInfo";
static void
gtk_tooltips_destroy_data (GtkTooltipsData *tooltipsdata)
{
- gtk_tooltips_widget_unmap (tooltipsdata->widget, tooltipsdata);
-
g_free (tooltipsdata->tip_text);
g_free (tooltipsdata->tip_private);
- 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_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)
{
g_return_if_fail (tooltips != NULL);
- if (tooltips->timer_tag)
- {
- g_source_remove (tooltips->timer_tag);
- tooltips->timer_tag = 0;
- }
-
g_hash_table_remove_all (private->tips_data_table);
- 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 (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_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);
-
- 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);
- gtk_misc_set_alignment (GTK_MISC (tooltips->tip_label), 0.5, 0.5);
- gtk_widget_show (tooltips->tip_label);
-
- gtk_container_add (GTK_CONTAINER (tooltips->tip_window), tooltips->tip_label);
-
- g_signal_connect (tooltips->tip_window,
- "destroy",
- G_CALLBACK (gtk_widget_destroyed),
- &tooltips->tip_window);
- }
+ /* nop */
}
void
{
g_return_if_fail (tooltips != NULL);
- gtk_tooltips_set_active_widget (tooltips, NULL);
-
tooltips->enabled = FALSE;
}
tooltipsdata->tip_text = g_strdup (tip_text);
tooltipsdata->tip_private = g_strdup (tip_private);
-
- gtk_tooltips_draw_tips (tooltips);
}
else
{
g_hash_table_insert (GTK_TOOLTIPS_GET_PRIVATE (tooltips)->tips_data_table,
widget, tooltipsdata);
- g_signal_connect_after (widget, "event_after",
- G_CALLBACK (gtk_tooltips_event_handler),
- tooltipsdata);
-
g_object_set_data (G_OBJECT (widget), I_(tooltips_data_key),
tooltipsdata);
- g_signal_connect (widget, "unmap",
- G_CALLBACK (gtk_tooltips_widget_unmap),
- tooltipsdata);
-
- g_signal_connect (widget, "unrealize",
- G_CALLBACK (gtk_tooltips_widget_unmap),
- tooltipsdata);
-
g_signal_connect (widget, "destroy",
G_CALLBACK (gtk_tooltips_widget_remove),
tooltipsdata);
}
-}
-
-static gint
-gtk_tooltips_paint_window (GtkTooltips *tooltips)
-{
- 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 FALSE;
-}
-
-static void
-gtk_tooltips_draw_tips (GtkTooltips *tooltips)
-{
- GtkRequisition requisition;
- GtkWidget *widget;
- 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))
- g_get_current_time (&tooltips->last_popdown);
-
- gtk_widget_ensure_style (tooltips->tip_window);
-
- widget = tooltips->active_tips_data->widget;
- g_object_set_data (G_OBJECT (tooltips->tip_window), I_(tooltips_info_key),
- tooltips);
-
- keyboard_mode = get_keyboard_mode (widget);
-
- gtk_tooltips_update_screen (tooltips, FALSE);
-
- screen = gtk_widget_get_screen (widget);
-
- data = tooltips->active_tips_data;
-
- gtk_label_set_text (GTK_LABEL (tooltips->tip_label), data->tip_text);
-
- gtk_widget_size_request (tooltips->tip_window, &requisition);
- w = requisition.width;
- h = requisition.height;
-
- gdk_window_get_origin (widget->window, &x, &y);
- if (GTK_WIDGET_NO_WINDOW (widget))
- {
- 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);
-
- 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 ((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;
-
- 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 gboolean
-gtk_tooltips_timeout (gpointer data)
-{
- GtkTooltips *tooltips = (GtkTooltips *) data;
-
- if (tooltips->active_tips_data != NULL &&
- GTK_WIDGET_DRAWABLE (tooltips->active_tips_data->widget))
- gtk_tooltips_draw_tips (tooltips);
-
- tooltips->timer_tag = 0;
-
- return FALSE;
-}
-
-static void
-gtk_tooltips_set_active_widget (GtkTooltips *tooltips,
- GtkWidget *widget)
-{
- if (tooltips->tip_window)
- {
- if (GTK_WIDGET_VISIBLE (tooltips->tip_window))
- g_get_current_time (&tooltips->last_popdown);
- gtk_widget_hide (tooltips->tip_window);
- }
- if (tooltips->timer_tag)
- {
- g_source_remove (tooltips->timer_tag);
- tooltips->timer_tag = 0;
- }
-
- tooltips->active_tips_data = NULL;
-
- if (widget && GTK_WIDGET_DRAWABLE (widget))
- {
- GtkTooltipsPrivate *private = GTK_TOOLTIPS_GET_PRIVATE (tooltips);
- GtkTooltipsData *tooltipsdata;
-
- tooltipsdata = g_hash_table_lookup (private->tips_data_table, widget);
-
- if (tooltipsdata)
- tooltips->active_tips_data = tooltipsdata;
- }
- else
- {
- tooltips->use_sticky_delay = FALSE;
- }
-}
-
-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)
-{
- GTimeVal now;
- glong msec;
-
- g_get_current_time (&now);
- msec = (now.tv_sec - tooltips->last_popdown.tv_sec) * 1000 +
- (now.tv_usec - tooltips->last_popdown.tv_usec) / 1000;
- return (msec < STICKY_REVERT_DELAY);
-}
-
-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 = gdk_threads_add_timeout (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;
-
- old_tips_data = gtk_tooltips_data_get (widget);
- tooltips = old_tips_data->tooltips;
-
- if (keyboard_mode)
- {
- switch (event->type)
- {
- case GDK_FOCUS_CHANGE:
- if (event->focus_change.in)
- gtk_tooltips_show_tip (widget);
- else
- 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;
- }
- }
-}
-static void
-gtk_tooltips_widget_unmap (GtkWidget *widget,
- gpointer data)
-{
- GtkTooltipsData *tooltipsdata = (GtkTooltipsData *)data;
- GtkTooltips *tooltips = tooltipsdata->tooltips;
-
- if (tooltips->active_tips_data &&
- (tooltips->active_tips_data->widget == widget))
- gtk_tooltips_set_active_widget (tooltips, NULL);
+ gtk_widget_set_tooltip_text (widget, tip_text);
}
static void
g_hash_table_remove (private->tips_data_table, tooltipsdata->widget);
}
-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