]> Pileus Git - ~andy/gtk/blob - gtk/gtktooltips.c
e3e64720e77557b883896f78c25a7a2579370405
[~andy/gtk] / gtk / gtktooltips.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <config.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "gtklabel.h"
33 #include "gtkmain.h"
34 #include "gtkmenuitem.h"
35 #include "gtkprivate.h"
36 #include "gtkwidget.h"
37 #include "gtkwindow.h"
38 #include "gtkstyle.h"
39 #include "gtktooltips.h"
40 #include "gtkintl.h"
41 #include "gtkalias.h"
42
43
44 #define DEFAULT_DELAY 500           /* Default delay in ms */
45 #define STICKY_DELAY 0              /* Delay before popping up next tip
46                                      * if we're sticky
47                                      */
48 #define STICKY_REVERT_DELAY 1000    /* Delay before sticky tooltips revert
49                                      * to normal
50                                      */
51 #define GTK_TOOLTIPS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TOOLTIPS, GtkTooltipsPrivate))
52
53 typedef struct _GtkTooltipsPrivate GtkTooltipsPrivate;
54
55 struct _GtkTooltipsPrivate
56 {
57   GHashTable *tips_data_table;
58 };
59
60
61 static void gtk_tooltips_finalize          (GObject         *object);
62 static void gtk_tooltips_destroy           (GtkObject       *object);
63
64 static void gtk_tooltips_destroy_data      (GtkTooltipsData *tooltipsdata);
65
66 static void gtk_tooltips_event_handler     (GtkWidget       *widget,
67                                             GdkEvent        *event);
68 static void gtk_tooltips_widget_unmap      (GtkWidget       *widget,
69                                             gpointer         data);
70 static void gtk_tooltips_widget_remove     (GtkWidget       *widget,
71                                             gpointer         data);
72 static void gtk_tooltips_set_active_widget (GtkTooltips     *tooltips,
73                                             GtkWidget       *widget);
74 static gint gtk_tooltips_timeout           (gpointer         data);
75
76 static gint gtk_tooltips_paint_window      (GtkTooltips     *tooltips);
77 static void gtk_tooltips_draw_tips         (GtkTooltips     *tooltips);
78 static void gtk_tooltips_unset_tip_window  (GtkTooltips     *tooltips);
79
80 static gboolean get_keyboard_mode          (GtkWidget       *widget);
81
82 static const gchar  tooltips_data_key[] = "_GtkTooltipsData";
83 static const gchar  tooltips_info_key[] = "_GtkTooltipsInfo";
84
85 G_DEFINE_TYPE (GtkTooltips, gtk_tooltips, GTK_TYPE_OBJECT)
86
87 static void
88 gtk_tooltips_class_init (GtkTooltipsClass *class)
89 {
90   GtkObjectClass *object_class = (GtkObjectClass *) class;
91   GObjectClass *gobject_class = (GObjectClass *) class;
92
93   gobject_class->finalize = gtk_tooltips_finalize;
94
95   object_class->destroy = gtk_tooltips_destroy;
96
97   g_type_class_add_private (gobject_class, sizeof (GtkTooltipsPrivate));
98 }
99
100 static void
101 gtk_tooltips_init (GtkTooltips *tooltips)
102 {
103   GtkTooltipsPrivate *private = GTK_TOOLTIPS_GET_PRIVATE (tooltips);
104
105   tooltips->tip_window = NULL;
106   tooltips->active_tips_data = NULL;
107   tooltips->_tips_data_list = NULL;
108
109   tooltips->delay = DEFAULT_DELAY;
110   tooltips->enabled = TRUE;
111   tooltips->timer_tag = 0;
112   tooltips->use_sticky_delay = FALSE;
113   tooltips->last_popdown.tv_sec = -1;
114   tooltips->last_popdown.tv_usec = -1;
115
116   private->tips_data_table =
117     g_hash_table_new_full (NULL, NULL, NULL,
118                            (GDestroyNotify) gtk_tooltips_destroy_data);
119 }
120
121 static void
122 gtk_tooltips_finalize (GObject *object)
123 {
124   GtkTooltipsPrivate *private = GTK_TOOLTIPS_GET_PRIVATE (object);
125
126   g_hash_table_destroy (private->tips_data_table);
127
128   G_OBJECT_CLASS (gtk_tooltips_parent_class)->finalize (object);
129 }
130
131 GtkTooltips *
132 gtk_tooltips_new (void)
133 {
134   return g_object_new (GTK_TYPE_TOOLTIPS, NULL);
135 }
136
137 static void
138 gtk_tooltips_destroy_data (GtkTooltipsData *tooltipsdata)
139 {
140   gtk_tooltips_widget_unmap (tooltipsdata->widget, tooltipsdata);
141
142   g_free (tooltipsdata->tip_text);
143   g_free (tooltipsdata->tip_private);
144
145   g_signal_handlers_disconnect_by_func (tooltipsdata->widget,
146                                         gtk_tooltips_event_handler,
147                                         tooltipsdata);
148   g_signal_handlers_disconnect_by_func (tooltipsdata->widget,
149                                         gtk_tooltips_widget_unmap,
150                                         tooltipsdata);
151   g_signal_handlers_disconnect_by_func (tooltipsdata->widget,
152                                         gtk_tooltips_widget_remove,
153                                         tooltipsdata);
154
155   g_object_set_data (G_OBJECT (tooltipsdata->widget), I_(tooltips_data_key), NULL);
156   g_object_unref (tooltipsdata->widget);
157   g_free (tooltipsdata);
158 }
159
160 static void
161 tip_window_display_closed (GdkDisplay  *display,
162                            gboolean     was_error,
163                            GtkTooltips *tooltips)
164 {
165   gtk_tooltips_unset_tip_window (tooltips);
166 }
167
168 static void
169 disconnect_tip_window_display_closed (GtkTooltips *tooltips)
170 {
171   g_signal_handlers_disconnect_by_func (gtk_widget_get_display (tooltips->tip_window),
172                                         (gpointer) tip_window_display_closed,
173                                         tooltips);
174 }
175
176 static void
177 gtk_tooltips_unset_tip_window (GtkTooltips *tooltips)
178 {
179   if (tooltips->tip_window)
180     {
181       disconnect_tip_window_display_closed (tooltips);
182       
183       gtk_widget_destroy (tooltips->tip_window);
184       tooltips->tip_window = NULL;
185     }
186 }
187
188 static void
189 gtk_tooltips_destroy (GtkObject *object)
190 {
191   GtkTooltips *tooltips = GTK_TOOLTIPS (object);
192   GtkTooltipsPrivate *private = GTK_TOOLTIPS_GET_PRIVATE (tooltips);
193
194   g_return_if_fail (tooltips != NULL);
195
196   if (tooltips->timer_tag)
197     {
198       g_source_remove (tooltips->timer_tag);
199       tooltips->timer_tag = 0;
200     }
201
202   g_hash_table_remove_all (private->tips_data_table);
203
204   gtk_tooltips_unset_tip_window (tooltips);
205
206   GTK_OBJECT_CLASS (gtk_tooltips_parent_class)->destroy (object);
207 }
208
209 static void
210 gtk_tooltips_update_screen (GtkTooltips *tooltips,
211                             gboolean     new_window)
212 {
213   gboolean screen_changed = FALSE;
214   
215   if (tooltips->active_tips_data &&
216       tooltips->active_tips_data->widget)
217     {
218       GdkScreen *screen = gtk_widget_get_screen (tooltips->active_tips_data->widget);
219
220       screen_changed = (screen != gtk_widget_get_screen (tooltips->tip_window));
221
222       if (screen_changed)
223         {
224           if (!new_window)
225             disconnect_tip_window_display_closed (tooltips);
226       
227           gtk_window_set_screen (GTK_WINDOW (tooltips->tip_window), screen);
228         }
229     }
230
231   if (screen_changed || new_window)
232     g_signal_connect (gtk_widget_get_display (tooltips->tip_window), "closed",
233                       G_CALLBACK (tip_window_display_closed), tooltips);
234
235 }
236
237 void
238 gtk_tooltips_force_window (GtkTooltips *tooltips)
239 {
240   g_return_if_fail (GTK_IS_TOOLTIPS (tooltips));
241
242   if (!tooltips->tip_window)
243     {
244       tooltips->tip_window = gtk_window_new (GTK_WINDOW_POPUP);
245       gtk_window_set_type_hint (GTK_WINDOW (tooltips->tip_window), GDK_WINDOW_TYPE_HINT_TOOLTIP);
246       gtk_tooltips_update_screen (tooltips, TRUE);
247       gtk_widget_set_app_paintable (tooltips->tip_window, TRUE);
248       gtk_window_set_resizable (GTK_WINDOW (tooltips->tip_window), FALSE);
249       gtk_widget_set_name (tooltips->tip_window, "gtk-tooltips");
250       gtk_container_set_border_width (GTK_CONTAINER (tooltips->tip_window), 4);
251
252       g_signal_connect_swapped (tooltips->tip_window,
253                                 "expose_event",
254                                 G_CALLBACK (gtk_tooltips_paint_window), 
255                                 tooltips);
256
257       tooltips->tip_label = gtk_label_new (NULL);
258       gtk_label_set_line_wrap (GTK_LABEL (tooltips->tip_label), TRUE);
259       gtk_misc_set_alignment (GTK_MISC (tooltips->tip_label), 0.5, 0.5);
260       gtk_widget_show (tooltips->tip_label);
261       
262       gtk_container_add (GTK_CONTAINER (tooltips->tip_window), tooltips->tip_label);
263
264       g_signal_connect (tooltips->tip_window,
265                         "destroy",
266                         G_CALLBACK (gtk_widget_destroyed),
267                         &tooltips->tip_window);
268     }
269 }
270
271 void
272 gtk_tooltips_enable (GtkTooltips *tooltips)
273 {
274   g_return_if_fail (tooltips != NULL);
275
276   tooltips->enabled = TRUE;
277 }
278
279 void
280 gtk_tooltips_disable (GtkTooltips *tooltips)
281 {
282   g_return_if_fail (tooltips != NULL);
283
284   gtk_tooltips_set_active_widget (tooltips, NULL);
285
286   tooltips->enabled = FALSE;
287 }
288
289 void
290 gtk_tooltips_set_delay (GtkTooltips *tooltips,
291                         guint         delay)
292 {
293   g_return_if_fail (tooltips != NULL);
294
295   tooltips->delay = delay;
296 }
297
298 GtkTooltipsData*
299 gtk_tooltips_data_get (GtkWidget       *widget)
300 {
301   g_return_val_if_fail (widget != NULL, NULL);
302
303   return g_object_get_data (G_OBJECT (widget), tooltips_data_key);
304 }
305
306 void
307 gtk_tooltips_set_tip (GtkTooltips *tooltips,
308                       GtkWidget   *widget,
309                       const gchar *tip_text,
310                       const gchar *tip_private)
311 {
312   GtkTooltipsData *tooltipsdata;
313
314   g_return_if_fail (GTK_IS_TOOLTIPS (tooltips));
315   g_return_if_fail (widget != NULL);
316
317   tooltipsdata = gtk_tooltips_data_get (widget);
318
319   if (!tip_text)
320     {
321       if (tooltipsdata)
322         gtk_tooltips_widget_remove (tooltipsdata->widget, tooltipsdata);
323       return;
324     }
325   
326   if (tooltips->active_tips_data 
327       && tooltips->active_tips_data->widget == widget
328       && GTK_WIDGET_DRAWABLE (tooltips->active_tips_data->widget))
329     {
330       g_free (tooltipsdata->tip_text);
331       g_free (tooltipsdata->tip_private);
332
333       tooltipsdata->tip_text = g_strdup (tip_text);
334       tooltipsdata->tip_private = g_strdup (tip_private);
335       
336       gtk_tooltips_draw_tips (tooltips);
337     }
338   else 
339     {
340       g_object_ref (widget);
341       
342       if (tooltipsdata)
343         gtk_tooltips_widget_remove (tooltipsdata->widget, tooltipsdata);
344       
345       tooltipsdata = g_new0 (GtkTooltipsData, 1);
346       
347       tooltipsdata->tooltips = tooltips;
348       tooltipsdata->widget = widget;
349
350       tooltipsdata->tip_text = g_strdup (tip_text);
351       tooltipsdata->tip_private = g_strdup (tip_private);
352
353       g_hash_table_insert (GTK_TOOLTIPS_GET_PRIVATE (tooltips)->tips_data_table,
354                            widget, tooltipsdata);
355
356       g_signal_connect_after (widget, "event_after",
357                               G_CALLBACK (gtk_tooltips_event_handler),
358                               tooltipsdata);
359
360       g_object_set_data (G_OBJECT (widget), I_(tooltips_data_key),
361                          tooltipsdata);
362
363       g_signal_connect (widget, "unmap",
364                         G_CALLBACK (gtk_tooltips_widget_unmap),
365                         tooltipsdata);
366
367       g_signal_connect (widget, "unrealize",
368                         G_CALLBACK (gtk_tooltips_widget_unmap),
369                         tooltipsdata);
370
371       g_signal_connect (widget, "destroy",
372                         G_CALLBACK (gtk_tooltips_widget_remove),
373                         tooltipsdata);
374     }
375 }
376
377 static gint
378 gtk_tooltips_paint_window (GtkTooltips *tooltips)
379 {
380   GtkRequisition req;
381
382   gtk_widget_size_request (tooltips->tip_window, &req);
383   gtk_paint_flat_box (tooltips->tip_window->style, tooltips->tip_window->window,
384                       GTK_STATE_NORMAL, GTK_SHADOW_OUT, 
385                       NULL, GTK_WIDGET(tooltips->tip_window), "tooltip",
386                       0, 0, req.width, req.height);
387
388   return FALSE;
389 }
390
391 static void
392 gtk_tooltips_draw_tips (GtkTooltips *tooltips)
393 {
394   GtkRequisition requisition;
395   GtkWidget *widget;
396   gint x, y, w, h;
397   GtkTooltipsData *data;
398   gboolean keyboard_mode;
399   GdkScreen *screen;
400   GdkScreen *pointer_screen;
401   gint monitor_num, px, py;
402   GdkRectangle monitor;
403   GtkWindow *toplevel;
404
405   if (!tooltips->tip_window)
406     gtk_tooltips_force_window (tooltips);
407   else if (GTK_WIDGET_VISIBLE (tooltips->tip_window))
408     g_get_current_time (&tooltips->last_popdown);
409
410   gtk_widget_ensure_style (tooltips->tip_window);
411   
412   widget = tooltips->active_tips_data->widget;
413   g_object_set_data (G_OBJECT (tooltips->tip_window), I_(tooltips_info_key),
414                      tooltips);
415
416   keyboard_mode = get_keyboard_mode (widget);
417
418   gtk_tooltips_update_screen (tooltips, FALSE);
419   
420   screen = gtk_widget_get_screen (widget);
421
422   data = tooltips->active_tips_data;
423
424   gtk_label_set_text (GTK_LABEL (tooltips->tip_label), data->tip_text);
425
426   gtk_widget_size_request (tooltips->tip_window, &requisition);
427   w = requisition.width;
428   h = requisition.height;
429
430   gdk_window_get_origin (widget->window, &x, &y);
431   if (GTK_WIDGET_NO_WINDOW (widget))
432     {
433       x += widget->allocation.x;
434       y += widget->allocation.y;
435     }
436
437   x += widget->allocation.width / 2;
438     
439   if (!keyboard_mode)
440     gdk_window_get_pointer (gdk_screen_get_root_window (screen),
441                             &x, NULL, NULL);
442
443   x -= (w / 2 + 4);
444
445   gdk_display_get_pointer (gdk_screen_get_display (screen),
446                            &pointer_screen, &px, &py, NULL);
447   if (pointer_screen != screen) 
448     {
449       px = x;
450       py = y;
451     }
452   monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
453   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
454
455   if ((x + w) > monitor.x + monitor.width)
456     x -= (x + w) - (monitor.x + monitor.width);
457   else if (x < monitor.x)
458     x = monitor.x;
459
460   if ((y + h + widget->allocation.height + 4) > monitor.y + monitor.height)
461     y = y - h - 4;
462   else
463     y = y + widget->allocation.height + 4;
464
465   toplevel = GTK_WINDOW (gtk_widget_get_toplevel (widget));
466   if (toplevel && GTK_IS_WINDOW (toplevel))
467     gtk_window_set_transient_for (GTK_WINDOW (tooltips->tip_window), toplevel);
468   
469   gtk_window_move (GTK_WINDOW (tooltips->tip_window), x, y);
470   gtk_widget_show (tooltips->tip_window);
471 }
472
473 static gboolean
474 gtk_tooltips_timeout (gpointer data)
475 {
476   GtkTooltips *tooltips = (GtkTooltips *) data;
477
478   if (tooltips->active_tips_data != NULL &&
479       GTK_WIDGET_DRAWABLE (tooltips->active_tips_data->widget))
480     gtk_tooltips_draw_tips (tooltips);
481
482   tooltips->timer_tag = 0;
483
484   return FALSE;
485 }
486
487 static void
488 gtk_tooltips_set_active_widget (GtkTooltips *tooltips,
489                                 GtkWidget   *widget)
490 {
491   if (tooltips->tip_window)
492     {
493       if (GTK_WIDGET_VISIBLE (tooltips->tip_window))
494         g_get_current_time (&tooltips->last_popdown);
495       gtk_widget_hide (tooltips->tip_window);
496     }
497   if (tooltips->timer_tag)
498     {
499       g_source_remove (tooltips->timer_tag);
500       tooltips->timer_tag = 0;
501     }
502   
503   tooltips->active_tips_data = NULL;
504   
505   if (widget && GTK_WIDGET_DRAWABLE (widget))
506     {
507       GtkTooltipsPrivate *private = GTK_TOOLTIPS_GET_PRIVATE (tooltips);
508       GtkTooltipsData    *tooltipsdata;
509
510       tooltipsdata = g_hash_table_lookup (private->tips_data_table, widget);
511
512       if (tooltipsdata)
513         tooltips->active_tips_data = tooltipsdata;
514     }
515   else
516     {
517       tooltips->use_sticky_delay = FALSE;
518     }
519 }
520
521 static void
522 gtk_tooltips_show_tip (GtkWidget *widget)
523 {
524   GtkTooltipsData *tooltipsdata;
525
526   tooltipsdata = gtk_tooltips_data_get (widget);
527
528   if (tooltipsdata &&
529       (!tooltipsdata->tooltips->active_tips_data ||
530        tooltipsdata->tooltips->active_tips_data->widget != widget))
531     {
532       gtk_tooltips_set_active_widget (tooltipsdata->tooltips, widget);
533       gtk_tooltips_draw_tips (tooltipsdata->tooltips);
534     }
535 }
536
537 static void
538 gtk_tooltips_hide_tip (GtkWidget *widget)
539 {
540   GtkTooltipsData *tooltipsdata;
541
542   tooltipsdata = gtk_tooltips_data_get (widget);
543
544   if (tooltipsdata &&
545       (tooltipsdata->tooltips->active_tips_data &&
546        tooltipsdata->tooltips->active_tips_data->widget == widget))
547     gtk_tooltips_set_active_widget (tooltipsdata->tooltips, NULL);
548 }
549
550 static gboolean
551 gtk_tooltips_recently_shown (GtkTooltips *tooltips)
552 {
553   GTimeVal now;
554   glong msec;
555   
556   g_get_current_time (&now);
557   msec = (now.tv_sec  - tooltips->last_popdown.tv_sec) * 1000 +
558           (now.tv_usec - tooltips->last_popdown.tv_usec) / 1000;
559   return (msec < STICKY_REVERT_DELAY);
560 }
561
562 static gboolean
563 get_keyboard_mode (GtkWidget *widget)
564 {
565   GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
566   if (GTK_IS_WINDOW (toplevel))
567     return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toplevel), "gtk-tooltips-keyboard-mode"));
568   else
569     return FALSE;
570 }
571
572 static void
573 start_keyboard_mode (GtkWidget *widget)
574 {
575   GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
576   if (GTK_IS_WINDOW (toplevel))
577     {
578       GtkWidget *focus = GTK_WINDOW (toplevel)->focus_widget;
579
580       g_object_set_data (G_OBJECT (toplevel), I_("gtk-tooltips-keyboard-mode"), GUINT_TO_POINTER (TRUE));
581
582       if (focus)
583         gtk_tooltips_show_tip (focus);
584     }
585 }
586
587 static void
588 stop_keyboard_mode (GtkWidget *widget)
589 {
590   GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
591   if (GTK_IS_WINDOW (toplevel))
592     {
593       GtkWidget *focus = GTK_WINDOW (toplevel)->focus_widget;
594       if (focus)
595         gtk_tooltips_hide_tip (focus);
596       
597       g_object_set_data (G_OBJECT (toplevel), I_("gtk-tooltips-keyboard-mode"), GUINT_TO_POINTER (FALSE));
598     }
599 }
600
601 static gboolean
602 tooltips_enabled (GtkTooltips *tooltips, GtkWidget *w)
603 {
604   GtkSettings *settings;
605   gboolean touchscreen;
606
607   if (!tooltips->enabled)
608     return FALSE;
609
610   settings = gtk_widget_get_settings (w);
611   g_object_get (settings, "gtk-touchscreen-mode", &touchscreen, NULL);
612   
613   return !touchscreen;
614 }
615
616 static void
617 gtk_tooltips_start_delay (GtkTooltips *tooltips,
618                           GtkWidget   *widget)
619 {
620   GtkTooltipsData *old_tips_data;
621   
622   old_tips_data = tooltips->active_tips_data;
623   if (tooltips_enabled (tooltips, widget) &&
624       (!old_tips_data || old_tips_data->widget != widget))
625     {
626       guint delay;
627       
628       gtk_tooltips_set_active_widget (tooltips, widget);
629       
630       if (tooltips->use_sticky_delay &&
631           gtk_tooltips_recently_shown (tooltips))
632         delay = STICKY_DELAY;
633       else
634         delay = tooltips->delay;
635       tooltips->timer_tag = gdk_threads_add_timeout (delay,
636                                            gtk_tooltips_timeout,
637                                            (gpointer) tooltips);
638     }
639 }
640
641 static void
642 gtk_tooltips_event_handler (GtkWidget *widget,
643                             GdkEvent  *event)
644 {
645   GtkTooltips *tooltips;
646   GtkTooltipsData *old_tips_data;
647   GtkWidget *event_widget;
648   gboolean keyboard_mode = get_keyboard_mode (widget);
649
650   if ((event->type == GDK_LEAVE_NOTIFY || event->type == GDK_ENTER_NOTIFY) &&
651       event->crossing.detail == GDK_NOTIFY_INFERIOR)
652     return;
653
654   old_tips_data = gtk_tooltips_data_get (widget);
655   tooltips = old_tips_data->tooltips;
656
657   if (keyboard_mode)
658     {
659       switch (event->type)
660         {
661         case GDK_FOCUS_CHANGE:
662           if (event->focus_change.in)
663             gtk_tooltips_show_tip (widget);
664           else
665             gtk_tooltips_hide_tip (widget);
666           break;
667         default:
668           break;
669         }
670     }
671   else
672     {
673       if (event->type != GDK_KEY_PRESS && event->type != GDK_KEY_RELEASE)
674         {
675           event_widget = gtk_get_event_widget (event);
676           if (event_widget != widget)
677             return;
678         }
679   
680       switch (event->type)
681         {
682         case GDK_EXPOSE:
683           /* do nothing */
684           break;
685         case GDK_ENTER_NOTIFY:
686           if (!(GTK_IS_MENU_ITEM (widget) && GTK_MENU_ITEM (widget)->submenu))
687             gtk_tooltips_start_delay (tooltips, widget);
688           break;
689           
690         case GDK_LEAVE_NOTIFY:
691           {
692             gboolean use_sticky_delay;
693             
694             use_sticky_delay = tooltips->tip_window &&
695               GTK_WIDGET_VISIBLE (tooltips->tip_window);
696             gtk_tooltips_set_active_widget (tooltips, NULL);
697             tooltips->use_sticky_delay = use_sticky_delay;
698           }
699           break;
700
701         case GDK_MOTION_NOTIFY:
702           /* Handle menu items specially ... pend popup for each motion
703            * on other widgets, we ignore motion.
704            */
705           if (GTK_IS_MENU_ITEM (widget) && !GTK_MENU_ITEM (widget)->submenu)
706             {
707               /* Completely evil hack to make sure we get the LEAVE_NOTIFY
708                */
709               GTK_PRIVATE_SET_FLAG (widget, GTK_LEAVE_PENDING);
710               gtk_tooltips_set_active_widget (tooltips, NULL);
711               gtk_tooltips_start_delay (tooltips, widget);
712               break;
713             }
714           break;                /* ignore */
715         case GDK_BUTTON_PRESS:
716         case GDK_BUTTON_RELEASE:
717         case GDK_KEY_PRESS:
718         case GDK_KEY_RELEASE:
719         case GDK_PROXIMITY_IN:
720         case GDK_SCROLL:
721           gtk_tooltips_set_active_widget (tooltips, NULL);
722           break;
723         default:
724           break;
725         }
726     }
727 }
728
729 static void
730 gtk_tooltips_widget_unmap (GtkWidget *widget,
731                            gpointer   data)
732 {
733   GtkTooltipsData *tooltipsdata = (GtkTooltipsData *)data;
734   GtkTooltips *tooltips = tooltipsdata->tooltips;
735   
736   if (tooltips->active_tips_data &&
737       (tooltips->active_tips_data->widget == widget))
738     gtk_tooltips_set_active_widget (tooltips, NULL);
739 }
740
741 static void
742 gtk_tooltips_widget_remove (GtkWidget *widget,
743                             gpointer   data)
744 {
745   GtkTooltipsData *tooltipsdata = (GtkTooltipsData*) data;
746   GtkTooltips *tooltips = tooltipsdata->tooltips;
747   GtkTooltipsPrivate *private = GTK_TOOLTIPS_GET_PRIVATE (tooltips);
748
749   g_hash_table_remove (private->tips_data_table, tooltipsdata->widget);
750 }
751
752 void
753 _gtk_tooltips_toggle_keyboard_mode (GtkWidget *widget)
754 {
755   if (get_keyboard_mode (widget))
756     stop_keyboard_mode (widget);
757   else
758     start_keyboard_mode (widget);
759 }
760
761 /**
762  * gtk_tooltips_get_info_from_tip_window:
763  * @tip_window: a #GtkWindow 
764  * @tooltips: the return location for the tooltips which are displayed 
765  *    in @tip_window, or %NULL
766  * @current_widget: the return location for the widget whose tooltips 
767  *    are displayed, or %NULL
768  * 
769  * Determines the tooltips and the widget they belong to from the window in 
770  * which they are displayed. 
771  *
772  * This function is mostly intended for use by accessibility technologies;
773  * applications should have little use for it.
774  * 
775  * Return value: %TRUE if @tip_window is displaying tooltips, otherwise %FALSE.
776  *
777  * Since: 2.4
778  *
779  * Deprecated: 2.12:
780  **/
781 gboolean
782 gtk_tooltips_get_info_from_tip_window (GtkWindow    *tip_window,
783                                        GtkTooltips **tooltips,
784                                        GtkWidget   **current_widget)
785 {
786   GtkTooltips  *current_tooltips;  
787   gboolean has_tips;
788
789   g_return_val_if_fail (GTK_IS_WINDOW (tip_window), FALSE);
790
791   current_tooltips = g_object_get_data (G_OBJECT (tip_window), tooltips_info_key);
792
793   has_tips = current_tooltips != NULL;
794
795   if (tooltips)
796     *tooltips = current_tooltips;
797   if (current_widget)
798     *current_widget = (has_tips && current_tooltips->active_tips_data) ? current_tooltips->active_tips_data->widget : NULL;
799
800   return has_tips;
801 }
802
803 #define __GTK_TOOLTIPS_C__
804 #include "gtkaliasdef.c"