gtktooltips.c 16.8 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* 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
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * 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
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * 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/. 
 */

Elliot Lee's avatar
Elliot Lee committed
27 28
#include <stdlib.h>
#include <string.h>
29
#include <stdio.h>
Elliot Lee's avatar
Elliot Lee committed
30

31
#include "gtklabel.h"
Elliot Lee's avatar
Elliot Lee committed
32 33
#include "gtkmain.h"
#include "gtkwidget.h"
Owen Taylor's avatar
Owen Taylor committed
34
#include "gtkwindow.h"
Elliot Lee's avatar
Elliot Lee committed
35 36 37 38 39 40
#include "gtksignal.h"
#include "gtkstyle.h"
#include "gtktooltips.h"


#define DEFAULT_DELAY 500           /* Default delay in ms */
41 42 43 44 45 46
#define STICKY_DELAY 0              /* Delay before popping up next tip
                                     * if we're sticky
                                     */
#define STICKY_REVERT_DELAY 1000    /* Delay before sticky tooltips revert
				     * to normal
                                     */
Elliot Lee's avatar
Elliot Lee committed
47

48 49 50
static void gtk_tooltips_class_init        (GtkTooltipsClass *klass);
static void gtk_tooltips_init              (GtkTooltips      *tooltips);
static void gtk_tooltips_destroy           (GtkObject        *object);
Elliot Lee's avatar
Elliot Lee committed
51

52
static void gtk_tooltips_event_handler     (GtkWidget   *widget,
Elliot Lee's avatar
Elliot Lee committed
53 54 55 56 57 58 59 60
                                            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);
61

62
static gint gtk_tooltips_paint_window      (GtkTooltips *tooltips);
Elliot Lee's avatar
Elliot Lee committed
63 64
static void gtk_tooltips_draw_tips         (GtkTooltips *tooltips);

65 66
static gboolean get_keyboard_mode          (GtkWidget   *widget);

Havoc Pennington's avatar
Delete.  
Havoc Pennington committed
67
static GtkObjectClass *parent_class;
68
static const gchar  *tooltips_data_key = "_GtkTooltipsData";
Elliot Lee's avatar
Elliot Lee committed
69

70
GtkType
71
gtk_tooltips_get_type (void)
72
{
73
  static GtkType tooltips_type = 0;
Elliot Lee's avatar
Elliot Lee committed
74

75
  if (!tooltips_type)
Elliot Lee's avatar
Elliot Lee committed
76
    {
77
      static const GtkTypeInfo tooltips_info =
78 79 80 81 82 83
      {
	"GtkTooltips",
	sizeof (GtkTooltips),
	sizeof (GtkTooltipsClass),
	(GtkClassInitFunc) gtk_tooltips_class_init,
	(GtkObjectInitFunc) gtk_tooltips_init,
84 85
	/* reserved_1 */ NULL,
	/* reserved_2 */ NULL,
86
        (GtkClassInitFunc) NULL,
87 88
      };

Havoc Pennington's avatar
Delete.  
Havoc Pennington committed
89
      tooltips_type = gtk_type_unique (GTK_TYPE_OBJECT, &tooltips_info);
Elliot Lee's avatar
Elliot Lee committed
90 91
    }

92
  return tooltips_type;
Elliot Lee's avatar
Elliot Lee committed
93 94
}

95 96
static void
gtk_tooltips_class_init (GtkTooltipsClass *class)
Elliot Lee's avatar
Elliot Lee committed
97
{
98 99 100
  GtkObjectClass *object_class;

  object_class = (GtkObjectClass*) class;
Havoc Pennington's avatar
Delete.  
Havoc Pennington committed
101
  parent_class = gtk_type_class (GTK_TYPE_OBJECT);
102 103

  object_class->destroy = gtk_tooltips_destroy;
Elliot Lee's avatar
Elliot Lee committed
104 105
}

106 107
static void
gtk_tooltips_init (GtkTooltips *tooltips)
Elliot Lee's avatar
Elliot Lee committed
108
{
109 110 111 112 113 114 115
  tooltips->tip_window = NULL;
  tooltips->active_tips_data = NULL;
  tooltips->tips_data_list = NULL;
  
  tooltips->delay = DEFAULT_DELAY;
  tooltips->enabled = TRUE;
  tooltips->timer_tag = 0;
116 117 118
  tooltips->use_sticky_delay = FALSE;
  tooltips->last_popdown.tv_sec = -1;
  tooltips->last_popdown.tv_usec = -1;
119 120 121
}

GtkTooltips *
122
gtk_tooltips_new (void)
123
{
124
  return gtk_type_new (GTK_TYPE_TOOLTIPS);
Elliot Lee's avatar
Elliot Lee committed
125 126 127
}

static void
128
gtk_tooltips_destroy_data (GtkTooltipsData *tooltipsdata)
Elliot Lee's avatar
Elliot Lee committed
129
{
130 131
  g_free (tooltipsdata->tip_text);
  g_free (tooltipsdata->tip_private);
Elliot Lee's avatar
Elliot Lee committed
132
  gtk_signal_disconnect_by_data (GTK_OBJECT (tooltipsdata->widget),
133
 				 (gpointer) tooltipsdata);
134
  gtk_object_remove_data (GTK_OBJECT (tooltipsdata->widget), tooltips_data_key);
135
  gtk_widget_unref (tooltipsdata->widget);
Elliot Lee's avatar
Elliot Lee committed
136 137 138
  g_free (tooltipsdata);
}

139
static void
140
gtk_tooltips_destroy (GtkObject *object)
Elliot Lee's avatar
Elliot Lee committed
141
{
142
  GtkTooltips *tooltips = GTK_TOOLTIPS (object);
Elliot Lee's avatar
Elliot Lee committed
143 144 145 146 147
  GList *current;
  GtkTooltipsData *tooltipsdata;

  g_return_if_fail (tooltips != NULL);

148
  if (tooltips->timer_tag)
Elliot Lee's avatar
Elliot Lee committed
149 150
    {
      gtk_timeout_remove (tooltips->timer_tag);
151
      tooltips->timer_tag = 0;
Elliot Lee's avatar
Elliot Lee committed
152 153
    }

154
  if (tooltips->tips_data_list != NULL)
Elliot Lee's avatar
Elliot Lee committed
155
    {
156
      current = g_list_first (tooltips->tips_data_list);
Elliot Lee's avatar
Elliot Lee committed
157 158 159 160
      while (current != NULL)
	{
	  tooltipsdata = (GtkTooltipsData*) current->data;
	  current = current->next;
161
	  gtk_tooltips_widget_remove (tooltipsdata->widget, tooltipsdata);
Elliot Lee's avatar
Elliot Lee committed
162 163 164
	}
    }

165 166
  if (tooltips->tip_window)
    gtk_widget_destroy (tooltips->tip_window);
Elliot Lee's avatar
Elliot Lee committed
167 168
}

169 170
void
gtk_tooltips_force_window (GtkTooltips *tooltips)
171
{
172 173 174 175
  g_return_if_fail (GTK_IS_TOOLTIPS (tooltips));

  if (!tooltips->tip_window)
    {
Owen Taylor's avatar
Owen Taylor committed
176
      tooltips->tip_window = gtk_window_new (GTK_WINDOW_POPUP);
177
      gtk_widget_set_app_paintable (tooltips->tip_window, TRUE);
178
      gtk_window_set_policy (GTK_WINDOW (tooltips->tip_window), FALSE, FALSE, TRUE);
179
      gtk_widget_set_name (tooltips->tip_window, "gtk-tooltips");
180 181
      gtk_container_set_border_width (GTK_CONTAINER (tooltips->tip_window), 4);

182 183
      gtk_signal_connect_object (GTK_OBJECT (tooltips->tip_window), 
				 "expose_event",
184 185
				 GTK_SIGNAL_FUNC (gtk_tooltips_paint_window), 
				 GTK_OBJECT (tooltips));
186

187 188 189 190 191 192 193
      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);

194 195
      gtk_signal_connect (GTK_OBJECT (tooltips->tip_window),
			  "destroy",
Havoc Pennington's avatar
Havoc Pennington committed
196
			  GTK_SIGNAL_FUNC (gtk_widget_destroyed),
197 198
			  &tooltips->tip_window);
    }
199 200
}

Elliot Lee's avatar
Elliot Lee committed
201 202 203 204 205 206 207 208 209 210 211 212 213
void
gtk_tooltips_enable (GtkTooltips *tooltips)
{
  g_return_if_fail (tooltips != NULL);

  tooltips->enabled = TRUE;
}

void
gtk_tooltips_disable (GtkTooltips *tooltips)
{
  g_return_if_fail (tooltips != NULL);

214
  gtk_tooltips_set_active_widget (tooltips, NULL);
Elliot Lee's avatar
Elliot Lee committed
215

216
  tooltips->enabled = FALSE;
Elliot Lee's avatar
Elliot Lee committed
217 218 219 220
}

void
gtk_tooltips_set_delay (GtkTooltips *tooltips,
221
                        guint         delay)
Elliot Lee's avatar
Elliot Lee committed
222 223 224 225 226 227
{
  g_return_if_fail (tooltips != NULL);

  tooltips->delay = delay;
}

228 229 230 231 232 233 234 235
GtkTooltipsData*
gtk_tooltips_data_get (GtkWidget       *widget)
{
  g_return_val_if_fail (widget != NULL, NULL);

  return gtk_object_get_data ((GtkObject*) widget, tooltips_data_key);
}

Elliot Lee's avatar
Elliot Lee committed
236
void
237 238 239 240
gtk_tooltips_set_tip (GtkTooltips *tooltips,
		      GtkWidget   *widget,
		      const gchar *tip_text,
		      const gchar *tip_private)
Elliot Lee's avatar
Elliot Lee committed
241 242 243
{
  GtkTooltipsData *tooltipsdata;

244
  g_return_if_fail (GTK_IS_TOOLTIPS (tooltips));
Elliot Lee's avatar
Elliot Lee committed
245 246
  g_return_if_fail (widget != NULL);

247
  tooltipsdata = gtk_tooltips_data_get (widget);
Elliot Lee's avatar
Elliot Lee committed
248

249
  if (!tip_text)
250 251 252 253 254 255 256 257 258 259 260 261
    {
      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);
Elliot Lee's avatar
Elliot Lee committed
262

263 264 265 266 267 268
      tooltipsdata->tip_text = g_strdup (tip_text);
      tooltipsdata->tip_private = g_strdup (tip_private);
      
      gtk_tooltips_draw_tips (tooltips);
    }
  else 
Elliot Lee's avatar
Elliot Lee committed
269
    {
270 271 272 273 274 275 276
      gtk_widget_ref (widget);
      
      if (tooltipsdata)
        gtk_tooltips_widget_remove (tooltipsdata->widget, tooltipsdata);
      
      tooltipsdata = g_new0 (GtkTooltipsData, 1);
      
277
      tooltipsdata->tooltips = tooltips;
Elliot Lee's avatar
Elliot Lee committed
278 279
      tooltipsdata->widget = widget;

280 281
      tooltipsdata->tip_text = g_strdup (tip_text);
      tooltipsdata->tip_private = g_strdup (tip_private);
Elliot Lee's avatar
Elliot Lee committed
282

283
      tooltips->tips_data_list = g_list_append (tooltips->tips_data_list,
284
                                                tooltipsdata);
285
      gtk_signal_connect_after (GTK_OBJECT (widget), "event-after",
Elliot Lee's avatar
Elliot Lee committed
286
                               (GtkSignalFunc) gtk_tooltips_event_handler,
287
                               tooltipsdata);
Elliot Lee's avatar
Elliot Lee committed
288

289
      gtk_object_set_data (GTK_OBJECT (widget), tooltips_data_key,
290
                           tooltipsdata);
Elliot Lee's avatar
Elliot Lee committed
291 292 293

      gtk_signal_connect (GTK_OBJECT (widget), "unmap",
                          (GtkSignalFunc) gtk_tooltips_widget_unmap,
294
                          tooltipsdata);
Elliot Lee's avatar
Elliot Lee committed
295 296 297

      gtk_signal_connect (GTK_OBJECT (widget), "unrealize",
                          (GtkSignalFunc) gtk_tooltips_widget_unmap,
298
                          tooltipsdata);
299 300

      gtk_signal_connect (GTK_OBJECT (widget), "destroy",
301 302
                          (GtkSignalFunc) gtk_tooltips_widget_remove,
                          tooltipsdata);
Elliot Lee's avatar
Elliot Lee committed
303 304 305
    }
}

306
static gint
307
gtk_tooltips_paint_window (GtkTooltips *tooltips)
308
{
309 310 311 312
  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);
313

314
  return FALSE;
315 316
}

Elliot Lee's avatar
Elliot Lee committed
317
static void
318
gtk_tooltips_draw_tips (GtkTooltips *tooltips)
Elliot Lee's avatar
Elliot Lee committed
319
{
320
  GtkRequisition requisition;
Elliot Lee's avatar
Elliot Lee committed
321
  GtkWidget *widget;
322
  GtkStyle *style;
323
  gint x, y, w, h, scr_w, scr_h;
Elliot Lee's avatar
Elliot Lee committed
324
  GtkTooltipsData *data;
325
  gboolean keyboard_mode;
Elliot Lee's avatar
Elliot Lee committed
326

327
  if (!tooltips->tip_window)
328
    gtk_tooltips_force_window (tooltips);
329
  else if (GTK_WIDGET_VISIBLE (tooltips->tip_window))
330
    g_get_current_time (&tooltips->last_popdown);
Elliot Lee's avatar
Elliot Lee committed
331

332
  gtk_widget_ensure_style (tooltips->tip_window);
333 334
  style = tooltips->tip_window->style;
  
335
  widget = tooltips->active_tips_data->widget;
Elliot Lee's avatar
Elliot Lee committed
336

337 338
  keyboard_mode = get_keyboard_mode (widget);

Elliot Lee's avatar
Elliot Lee committed
339 340 341
  scr_w = gdk_screen_width ();
  scr_h = gdk_screen_height ();

342
  data = tooltips->active_tips_data;
343

344
  gtk_label_set_text (GTK_LABEL (tooltips->tip_label), data->tip_text);
345

346 347 348
  gtk_widget_size_request (tooltips->tip_window, &requisition);
  w = requisition.width;
  h = requisition.height;
Elliot Lee's avatar
Elliot Lee committed
349

350
  gdk_window_get_origin (widget->window, &x, &y);
351
  if (GTK_WIDGET_NO_WINDOW (widget))
352 353 354 355 356 357 358 359 360
    {
      x += widget->allocation.x;
      y += widget->allocation.y;
    }

  x += widget->allocation.width / 2;
    
  if (!keyboard_mode)
    gdk_window_get_pointer (NULL, &x, NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
361

362
  x -= (w / 2 + 4);
Elliot Lee's avatar
Elliot Lee committed
363 364 365 366 367 368 369 370 371 372 373

  if ((x + w) > scr_w)
    x -= (x + w) - scr_w;
  else if (x < 0)
    x = 0;

  if ((y + h + widget->allocation.height + 4) > scr_h)
    y = y - h - 4;
  else
    y = y + widget->allocation.height + 4;

374
  gtk_window_move (GTK_WINDOW (tooltips->tip_window), x, y);
375
  gtk_widget_show (tooltips->tip_window);
Elliot Lee's avatar
Elliot Lee committed
376 377 378 379 380 381 382
}

static gint
gtk_tooltips_timeout (gpointer data)
{
  GtkTooltips *tooltips = (GtkTooltips *) data;

383
  GDK_THREADS_ENTER ();
384
  
385 386
  if (tooltips->active_tips_data != NULL &&
      GTK_WIDGET_DRAWABLE (tooltips->active_tips_data->widget))
Elliot Lee's avatar
Elliot Lee committed
387 388
    gtk_tooltips_draw_tips (tooltips);

389
  GDK_THREADS_LEAVE ();
390

Elliot Lee's avatar
Elliot Lee committed
391 392 393 394 395 396 397
  return FALSE;
}

static void
gtk_tooltips_set_active_widget (GtkTooltips *tooltips,
                                GtkWidget   *widget)
{
398
  if (tooltips->tip_window)
399 400 401 402 403
    {
      if (GTK_WIDGET_VISIBLE (tooltips->tip_window))
	g_get_current_time (&tooltips->last_popdown);
      gtk_widget_hide (tooltips->tip_window);
    }
404
  if (tooltips->timer_tag)
Elliot Lee's avatar
Elliot Lee committed
405
    {
406 407 408 409 410 411 412 413 414 415 416
      gtk_timeout_remove (tooltips->timer_tag);
      tooltips->timer_tag = 0;
    }
  
  tooltips->active_tips_data = NULL;
  
  if (widget)
    {
      GList *list;
      
      for (list = tooltips->tips_data_list; list; list = list->next)
Elliot Lee's avatar
Elliot Lee committed
417
	{
418 419 420 421 422 423 424 425 426 427
	  GtkTooltipsData *tooltipsdata;
	  
	  tooltipsdata = list->data;
	  
	  if (tooltipsdata->widget == widget &&
	      GTK_WIDGET_DRAWABLE (widget))
	    {
	      tooltips->active_tips_data = tooltipsdata;
	      break;
	    }
Elliot Lee's avatar
Elliot Lee committed
428 429
	}
    }
430 431 432 433 434 435
  else
    {
      tooltips->use_sticky_delay = FALSE;
    }
}

436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
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);
}

465 466 467 468 469 470 471 472 473 474
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);
Elliot Lee's avatar
Elliot Lee committed
475 476
}

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
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;
494 495 496

      g_object_set_data (G_OBJECT (toplevel), "gtk-tooltips-keyboard-mode", GUINT_TO_POINTER (TRUE));

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
      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), "gtk-tooltips-keyboard-mode", GUINT_TO_POINTER (FALSE));
    }
}

static void
Elliot Lee's avatar
Elliot Lee committed
517 518 519 520
gtk_tooltips_event_handler (GtkWidget *widget,
                            GdkEvent  *event)
{
  GtkTooltips *tooltips;
521
  GtkTooltipsData *old_tips_data;
522
  GtkWidget *event_widget;
523
  gboolean keyboard_mode = get_keyboard_mode (widget);
Elliot Lee's avatar
Elliot Lee committed
524 525 526

  if ((event->type == GDK_LEAVE_NOTIFY || event->type == GDK_ENTER_NOTIFY) &&
      event->crossing.detail == GDK_NOTIFY_INFERIOR)
527
    return;
528 529 530

  old_tips_data = gtk_tooltips_data_get (widget);
  tooltips = old_tips_data->tooltips;
Elliot Lee's avatar
Elliot Lee committed
531

532
  if (keyboard_mode)
Elliot Lee's avatar
Elliot Lee committed
533
    {
534
      switch (event->type)
Elliot Lee's avatar
Elliot Lee committed
535
	{
536 537 538 539 540 541 542 543 544 545 546 547
	case GDK_FOCUS_CHANGE:
	  if (event->focus_change.in)
	    gtk_tooltips_show_tip (widget);
	  else
	    gtk_tooltips_hide_tip (widget);
	  break;
	default:
	  break;
	}
    }
  else
    {
548 549 550 551 552 553
      if (event->type != GDK_KEY_PRESS && event->type != GDK_KEY_RELEASE)
	{
	  event_widget = gtk_get_event_widget (event);
	  if (event_widget != widget)
	    return;
	}
554 555 556 557 558 559 560
  
      switch (event->type)
	{
	case GDK_MOTION_NOTIFY:
	case GDK_EXPOSE:
	  /* do nothing */
	  break;
561
	  
562 563 564 565 566 567 568 569 570 571
	case GDK_ENTER_NOTIFY:
	  old_tips_data = tooltips->active_tips_data;
	  if (tooltips->enabled &&
	      (!old_tips_data || old_tips_data->widget != widget))
	    {
	      guint delay;
	      
	      gtk_tooltips_set_active_widget (tooltips, widget);
	      
	      if (tooltips->use_sticky_delay  &&
572
	      gtk_tooltips_recently_shown (tooltips))
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
		delay = STICKY_DELAY;
	      else
		delay = tooltips->delay;
	      tooltips->timer_tag = gtk_timeout_add (delay,
						     gtk_tooltips_timeout,
						     (gpointer) tooltips);
	    }
	  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;
592 593 594 595 596 597 598

	case GDK_BUTTON_PRESS:
	case GDK_BUTTON_RELEASE:
	case GDK_KEY_PRESS:
	case GDK_KEY_RELEASE:
	case GDK_PROXIMITY_IN:
	case GDK_SCROLL:
599 600
	  gtk_tooltips_set_active_widget (tooltips, NULL);
	  break;
601 602
	default:
	  break;
Elliot Lee's avatar
Elliot Lee committed
603 604 605 606 607 608 609 610
	}
    }
}

static void
gtk_tooltips_widget_unmap (GtkWidget *widget,
			   gpointer   data)
{
611 612
  GtkTooltipsData *tooltipsdata = (GtkTooltipsData *)data;
  GtkTooltips *tooltips = tooltipsdata->tooltips;
613 614 615 616
  
  if (tooltips->active_tips_data &&
      (tooltips->active_tips_data->widget == widget))
    gtk_tooltips_set_active_widget (tooltips, NULL);
Elliot Lee's avatar
Elliot Lee committed
617 618 619 620 621 622
}

static void
gtk_tooltips_widget_remove (GtkWidget *widget,
			    gpointer   data)
{
623
  GtkTooltipsData *tooltipsdata = (GtkTooltipsData*) data;
624
  GtkTooltips *tooltips = tooltipsdata->tooltips;
Elliot Lee's avatar
Elliot Lee committed
625 626

  gtk_tooltips_widget_unmap (widget, data);
627 628
  tooltips->tips_data_list = g_list_remove (tooltips->tips_data_list,
					    tooltipsdata);
629
  gtk_tooltips_destroy_data (tooltipsdata);
Elliot Lee's avatar
Elliot Lee committed
630
}
631

632 633
void
_gtk_tooltips_toggle_keyboard_mode (GtkWidget *widget)
634
{
635 636 637 638
  if (get_keyboard_mode (widget))
    stop_keyboard_mode (widget);
  else
    start_keyboard_mode (widget);
639
}
640