]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/gtk+/gtk+-2.6.4-1.osso7/gtkwidget.c.diff
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / gtk+ / gtk+-2.6.4-1.osso7 / gtkwidget.c.diff
1 --- gtk+-2.6.4/gtk/gtkwidget.c  2005-02-24 18:44:02.000000000 +0200
2 +++ gtk+-2.6.4/gtk/gtkwidget.c  2005-04-06 16:19:38.386702696 +0300
3 @@ -28,6 +28,8 @@
4  #include <stdarg.h>
5  #include <string.h>
6  #include <locale.h>
7 +#include <stdlib.h>
8 +#include <x11/gdkx.h>
9  #include "gtkalias.h"
10  #include "gtkcontainer.h"
11  #include "gtkaccelmap.h"
12 @@ -44,6 +46,11 @@
13  #include "gtkwindow.h"
14  #include "gtkbindings.h"
15  #include "gtkprivate.h"
16 +#include "gtktreeview.h"
17 +#include "gtkentry.h"
18 +#include "gtktextview.h"
19 +#include "gtkimcontext.h"
20 +#include "gtkmenu.h"
21  #include "gdk/gdk.h"
22  #include "gdk/gdkprivate.h" /* Used in gtk_reset_shapes_recurse to avoid copy */
23  #include <gobject/gvaluecollector.h>
24 @@ -53,11 +60,30 @@
25  #include "gtkaccessible.h"
26  #include "gtktooltips.h"
27  #include "gtkinvisible.h"
28 +#include "gtkscrollbar.h"   /* Following are needed for special focus changes */
29 +#include "gtktoolbar.h"
30 +#include "gtkmenu.h"
31 +#include "gtkmenuitem.h"
32 +#include "gtktogglebutton.h"
33 +#include "gtkcomboboxentry.h"
34 +#include "gtktogglebutton.h"
35 +#include "gtkcomboboxentry.h"
36  
37  #define WIDGET_CLASS(w)         GTK_WIDGET_GET_CLASS (w)
38  #define        INIT_PATH_SIZE  (512)
39  
40 +#define GTK_TAP_THRESHOLD 30
41 +#define GTK_TAP_MENU_THRESHOLD 20
42 +#define GTK_TAP_AND_HOLD_TIMER_COUNTER 11
43 +#define GTK_TAP_AND_HOLD_TIMER_INTERVAL 100
44  
45 +typedef struct _GtkWidgetPrivate GtkWidgetPrivate;
46 +
47 +#define GTK_WIDGET_GET_PRIVATE(obj) ( G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
48 +                                      GTK_TYPE_WIDGET, GtkWidgetPrivate) )
49 +
50 +#define TAP_AND_HOLD_ANIMATION 1
51 +                                      
52  enum {
53    SHOW,
54    HIDE,
55 @@ -120,6 +146,9 @@
56    ACCEL_CLOSURES_CHANGED,
57    SCREEN_CHANGED,
58    CAN_ACTIVATE_ACCEL,
59 +       INSENSITIVE_PRESS,
60 +  TAP_AND_HOLD,
61 +  TAP_AND_HOLD_SETUP,
62    LAST_SIGNAL
63  };
64  
65 @@ -142,7 +171,8 @@
66    PROP_STYLE,
67    PROP_EVENTS,
68    PROP_EXTENSION_EVENTS,
69 -  PROP_NO_SHOW_ALL
70 +  PROP_NO_SHOW_ALL,
71 +  PROP_TAP_AND_HOLD
72  };
73  
74  typedef        struct  _GtkStateData    GtkStateData;
75 @@ -155,7 +185,50 @@
76    guint                use_forall : 1;
77  };
78  
79 +struct _GtkWidgetPrivate
80 +{
81 +  GtkWidget *menu;
82 +  guint timer_id;
83 +
84 +  GtkStateType stype;
85 +  GtkStateType type_on_press;
86 +  GdkEvent *fake_event;
87 +  GtkMenuPositionFunc func;
88 +  gint x, y;
89 +  gint timer_counter;
90 +  gint run_press : 1;
91 +  gint button_pressed : 1;
92 +  gint signals_connected : 1;
93 +  GtkWidgetTapAndHoldFlags flags;
94 +  gboolean state_set;
95 +  guint interval;
96 +  
97 +#ifdef TAP_AND_HOLD_ANIMATION
98 +  GdkPixbufAnimation *anim;
99 +  GdkPixbufAnimationIter *iter;
100 +  guint width, height;
101 +#endif
102 +};
103 +
104  
105 +/* --- Tap And Hold --- */
106 +static gboolean gtk_widget_tap_and_hold_button_press_with_events( GtkWidget *widget,
107 +                                     GdkEvent *event, GtkWidgetPrivate *priv );
108 +static gboolean gtk_widget_tap_and_hold_button_release_with_events( GtkWidget *widget,
109 +                                     GdkEvent *event, GtkWidgetPrivate *priv );
110 +static gboolean gtk_widget_tap_and_hold_leave_notify_with_events( GtkWidget *widget,
111 +                                     GdkEvent *event, GtkWidgetPrivate *priv );
112 +static gboolean gtk_widget_tap_and_hold_timeout_with_events( GtkWidget *widget );
113 +static gboolean gtk_widget_tap_and_hold_timeout( GtkWidget *widget );
114 +static gboolean gtk_widget_tap_and_hold_button_press( GtkWidget *widget,
115 +                                     GdkEvent *event, GtkWidgetPrivate *priv );
116 +static gboolean gtk_widget_tap_and_hold_button_release( GtkWidget *widget,
117 +                                     GdkEvent *event, GtkWidgetPrivate *priv );
118 +static gboolean gtk_widget_tap_and_hold_leave_notify( GtkWidget *widget,
119 +                                     GdkEvent *event, GtkWidgetPrivate *priv );
120 +static void gtk_widget_tap_and_hold_setup_real( GtkWidget *widget,
121 +            GtkWidget *menu, GtkCallback func, GtkWidgetTapAndHoldFlags flags );
122 +static void gtk_widget_real_tap_and_hold(GtkWidget *widget);
123  /* --- prototypes --- */
124  static void    gtk_widget_class_init            (GtkWidgetClass    *klass);
125  static void    gtk_widget_init                  (GtkWidget         *widget);
126 @@ -228,6 +301,13 @@
127                                            gint       width,
128                                            gint       height);
129  
130 +/*Hildon focus handling*/
131 +static void gtk_widget_set_focus_handling( GtkWidget *widget, gboolean state );
132 +
133 +static gboolean gtk_widget_enter_notify_event( GtkWidget *widget, GdkEventCrossing *event );
134 +static gboolean gtk_widget_leave_notify_event( GtkWidget *widget, GdkEventCrossing *event );
135 +static gint gtk_widget_button_release_event( GtkWidget *widget, GdkEventButton *event );
136 +static gint gtk_widget_button_press_event( GtkWidget *widget, GdkEventButton *event );
137  
138  /* --- variables --- */
139  static gpointer         parent_class = NULL;
140 @@ -239,6 +319,9 @@
141  static GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR;
142  static GParamSpecPool  *style_property_spec_pool = NULL;
143  
144 +static gboolean on_same_widget = FALSE; /*Hildon focus handling*/
145 +static gboolean mouse_pressed = FALSE; /*Hildon focus handling*/
146 +
147  static GQuark          quark_property_parser = 0;
148  static GQuark          quark_aux_info = 0;
149  static GQuark          quark_accel_path = 0;
150 @@ -396,6 +479,9 @@
151    klass->drag_data_received = NULL;
152    klass->screen_changed = NULL;
153    klass->can_activate_accel = gtk_widget_real_can_activate_accel;
154 +  klass->tap_and_hold_setup = gtk_widget_tap_and_hold_setup_real;
155 +  klass->insensitive_press = NULL;
156 +  klass->tap_and_hold = gtk_widget_real_tap_and_hold;
157  
158    klass->show_help = gtk_widget_real_show_help;
159    
160 @@ -404,6 +490,18 @@
161  
162    klass->no_expose_event = NULL;
163  
164 +  g_type_class_add_private( klass, sizeof(GtkWidgetPrivate) );
165 +
166 +  g_object_class_install_property (gobject_class,
167 +                                  PROP_TAP_AND_HOLD,
168 +                                  g_param_spec_int ("tap_and_hold_state",
169 +                                                    P_("Tap and hold State type"),
170 +                                                    P_("Sets the state to be used to the tap and hold functionality. The default is GTK_STATE_NORMAL"),
171 +                                                    0,
172 +                                                    4, /*4 == Last state in GTK+-2.0*/
173 +                                                    GTK_STATE_NORMAL,
174 +                                                    G_PARAM_READWRITE));
175 +
176    g_object_class_install_property (gobject_class,
177                                    PROP_NAME,
178                                    g_param_spec_string ("name",
179 @@ -1389,6 +1487,31 @@
180                   _gtk_marshal_BOOLEAN__UINT,
181                    G_TYPE_BOOLEAN, 1, G_TYPE_UINT);
182  
183 +   widget_signals[INSENSITIVE_PRESS] =
184 +     g_signal_new ("insensitive_press",
185 +                  G_TYPE_FROM_CLASS (gobject_class),
186 +                  G_SIGNAL_RUN_FIRST,
187 +                  G_STRUCT_OFFSET (GtkWidgetClass, insensitive_press),
188 +                  NULL, NULL,
189 +                  _gtk_marshal_VOID__VOID,
190 +                  G_TYPE_NONE, 0);
191 +
192 +  widget_signals[TAP_AND_HOLD] =
193 +    g_signal_new("tap-and-hold", G_TYPE_FROM_CLASS(gobject_class),
194 +                  G_SIGNAL_RUN_LAST,
195 +                  G_STRUCT_OFFSET(GtkWidgetClass, tap_and_hold),
196 +                  NULL, NULL,
197 +                  _gtk_marshal_VOID__VOID,
198 +                  G_TYPE_NONE, 0);
199 +                  
200 +  widget_signals[TAP_AND_HOLD_SETUP] =  
201 +    g_signal_new("tap-and-hold-setup", G_TYPE_FROM_CLASS(gobject_class),
202 +                  G_SIGNAL_RUN_LAST,
203 +                  G_STRUCT_OFFSET(GtkWidgetClass, tap_and_hold_setup),
204 +                  NULL, NULL, /*FIXME -- OBJECT_POINTER_FLAGS*/
205 +                  _gtk_marshal_VOID__OBJECT_UINT_FLAGS,
206 +                  G_TYPE_NONE, 3, G_TYPE_OBJECT, G_TYPE_POINTER, G_TYPE_UINT);
207 +
208    binding_set = gtk_binding_set_by_class (klass);
209    gtk_binding_entry_add_signal (binding_set, GDK_F10, GDK_SHIFT_MASK,
210                                  "popup_menu", 0);
211 @@ -1418,7 +1541,12 @@
212                                                                  P_("Whether to draw the focus indicator inside widgets"),
213                                                                  TRUE,
214                                                                  G_PARAM_READABLE));
215 -
216 +  gtk_widget_class_install_style_property (klass,
217 +                                  g_param_spec_boolean ("hildon-focus-handling",
218 +                                                        P_("Hildon focus handling"),
219 +                                                        P_("Whether the widget is using the hildon like focus handling or not"),
220 +                                                        FALSE,
221 +                                                                G_PARAM_READABLE));
222    gtk_widget_class_install_style_property (klass,
223                                            g_param_spec_int ("focus-line-width",
224                                                              P_("Focus linewidth"),
225 @@ -1543,6 +1671,8 @@
226      case PROP_NO_SHOW_ALL:
227        gtk_widget_set_no_show_all (widget, g_value_get_boolean (value));
228        break;
229 +    case PROP_TAP_AND_HOLD:
230 +      GTK_WIDGET_GET_PRIVATE(widget)->type_on_press = g_value_get_int(value);
231      default:
232        break;
233      }
234 @@ -1637,16 +1767,45 @@
235      case PROP_NO_SHOW_ALL:
236        g_value_set_boolean (value, gtk_widget_get_no_show_all (widget));
237        break;
238 +    case PROP_TAP_AND_HOLD:
239 +      g_value_set_int (value,
240 +                       (int)GTK_WIDGET_GET_PRIVATE(widget)->type_on_press);
241      default:
242        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
243        break;
244      }
245  }
246  
247 +static void gtk_widget_set_focus_handling( GtkWidget *widget, gboolean state )
248 +{
249 +      GtkWidgetPrivate *priv;
250 +      priv = GTK_WIDGET_GET_PRIVATE (widget);
251 +
252 +      if( state && GTK_WIDGET_CAN_FOCUS(widget) )
253 +      {
254 +         if (!priv->state_set)
255 +            {  
256 +               g_signal_connect( G_OBJECT(widget), "button-press-event",
257 +                                      G_CALLBACK(gtk_widget_button_press_event), NULL );
258 +               g_signal_connect( G_OBJECT(widget), "button-release-event",
259 +                                      G_CALLBACK(gtk_widget_button_release_event), NULL );
260 +               g_signal_connect( G_OBJECT(widget), "enter-notify-event",
261 +                                      G_CALLBACK(gtk_widget_enter_notify_event), NULL );
262 +               g_signal_connect( G_OBJECT(widget), "leave-notify-event",
263 +                                      G_CALLBACK(gtk_widget_leave_notify_event), NULL );
264 +               priv->state_set = TRUE;
265 +            }
266 +      }
267 +}
268 +
269  static void
270  gtk_widget_init (GtkWidget *widget)
271  {
272 +  GtkWidgetPrivate *priv;
273    GTK_PRIVATE_FLAGS (widget) = PRIVATE_GTK_CHILD_VISIBLE;
274 +
275 +  priv = GTK_WIDGET_GET_PRIVATE(widget);
276 +
277    widget->state = GTK_STATE_NORMAL;
278    widget->saved_state = GTK_STATE_NORMAL;
279    widget->name = NULL;
280 @@ -1659,6 +1818,18 @@
281    widget->window = NULL;
282    widget->parent = NULL;
283  
284 +  priv->fake_event = NULL;
285 +  priv->timer_id = 0;
286 +  priv->menu = NULL;
287 +  priv->run_press = TRUE;
288 +  priv->signals_connected = FALSE;
289 +  priv->x = priv->y = 0;
290 +  priv->func = NULL;
291 +  priv->timer_counter = 0;
292 +  priv->flags = 0x0;
293 +  priv->state_set = FALSE;
294 +  priv->interval = GTK_TAP_AND_HOLD_TIMER_INTERVAL;
295 +  
296    GTK_WIDGET_SET_FLAGS (widget,
297                         GTK_SENSITIVE |
298                         GTK_PARENT_SENSITIVE |
299 @@ -1670,6 +1841,7 @@
300    GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
301  
302    widget->style = gtk_widget_get_default_style ();
303 +
304    g_object_ref (widget->style);
305  }
306  
307 @@ -2153,6 +2325,7 @@
308  
309    if ((GTK_WIDGET_FLAGS (widget) & GTK_NO_SHOW_ALL) != 0)
310      return;
311
312  
313    class = GTK_WIDGET_GET_CLASS (widget);
314  
315 @@ -3400,6 +3573,127 @@
316    return FALSE;
317  }
318  
319 +/**
320 + * gtk_widget_button_press_event
321 + * @widget: a #GtkWidget
322 + * @event: a #GtkEventKey
323 + *
324 +**/
325 +static gboolean gtk_widget_button_press_event(GtkWidget *widget, GdkEventButton *event )
326 +{
327 +  if( !mouse_pressed /*&& !GTK_IS_TREE_VIEW(widget) && !GTK_IS_ENTRY(widget)*/ )
328 +  {
329 +       GtkWidget *toplevel;
330 +       toplevel = gtk_widget_get_toplevel (widget);
331 +     if (GTK_IS_WINDOW (toplevel))
332 +       {
333 +         mouse_pressed = TRUE;
334 +
335 +         if( /*!gtk_window_get_prev_focus_widget(GTK_WINDOW(toplevel)) &&*/
336 +             GTK_IS_WIDGET(GTK_WINDOW(toplevel)->focus_widget) )
337 +           gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), 
338 +                                           GTK_WINDOW(toplevel)->focus_widget );
339 +     }
340 +  }
341 +  return FALSE;
342 +}
343 +
344 +/**
345 + * gtk_widget_button_release_event
346 + * @widget: a #GtkWidget
347 + * @event: a #GtkEventKey
348 + *
349 +**/
350 +static gboolean gtk_widget_button_release_event(GtkWidget   *widget, GdkEventButton *event )
351 +{
352 +  if( mouse_pressed /*&& !GTK_IS_ENTRY(widget)*/ )
353 +  {
354 +       GtkWidget *toplevel;
355 +       GtkWidget *event_widget;
356 +       event_widget = gtk_get_event_widget( (GdkEvent*) event );
357 +       toplevel = gtk_widget_get_toplevel (widget);
358 +
359 +       mouse_pressed = FALSE;
360 +    on_same_widget = TRUE;
361 +
362 +        if (GTK_IS_WINDOW (toplevel))
363 +          {
364 +           if( !on_same_widget && GTK_IS_WIDGET(GTK_WINDOW(toplevel)->focus_widget) )
365 +               gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), GTK_WINDOW(toplevel)->focus_widget );
366 +            else
367 +             gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), event_widget );
368 +          }
369 +  }
370 +       return FALSE;
371 +}
372 +
373 +/**
374 + * gtk_widget_enter_notify_event
375 + * @widget: a #GtkWidget
376 + * @event: a #GtkEventCrossing
377 + *
378 +**/
379 +static gboolean gtk_widget_enter_notify_event( GtkWidget *widget, GdkEventCrossing *event )
380 +{
381 +       GtkWidget *toplevel;
382 +       GtkWidget *event_widget;
383 +  /*if( GTK_IS_ENTRY(widget) )
384 +    return FALSE;*/
385 +
386 +       toplevel = gtk_widget_get_toplevel (widget);
387 +       event_widget = gtk_get_event_widget ( (GdkEvent*) event );
388 +
389 +  if(mouse_pressed && !on_same_widget && gtk_window_get_prev_focus_widget( GTK_WINDOW(toplevel) ) == event_widget)
390 +  {
391 +/*     GtkWidget *temp;*/
392 +       on_same_widget = TRUE;
393 +
394 +/*    temp = gtk_window_get_prev_focus_widget( GTK_WINDOW(toplevel) );*/
395 +    if( GTK_IS_WIDGET(GTK_WINDOW(toplevel)->focus_widget) )
396 +    {
397 +      gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), GTK_WINDOW(toplevel)->focus_widget );
398 +      if( GTK_WIDGET_CAN_FOCUS(event_widget) )
399 +        gtk_widget_grab_focus( event_widget );
400 +      else
401 +        gtk_widget_activate( event_widget );
402 +    }
403 +  }
404 +       return FALSE;
405 +}
406 +
407 +
408 +/**
409 + * gtk_widget_leave_notify_event
410 + * @widget: a #GtkWidget
411 + * @event: a #GtkEventCrossing
412 + * 
413 +**/
414 +static gboolean gtk_widget_leave_notify_event( GtkWidget *widget, GdkEventCrossing *event )
415 +{
416 +  if( mouse_pressed && on_same_widget /*&& !GTK_IS_ENTRY(widget)*/ )
417 +  {
418 +       GtkWidget *event_widget;
419 +       GtkWidget *toplevel;
420 +       GtkWidget *temp;
421 +       toplevel = gtk_widget_get_toplevel( widget );
422 +       event_widget = gtk_get_event_widget( (GdkEvent*) event );
423 +       on_same_widget = FALSE;
424 +
425 +    temp = gtk_window_get_prev_focus_widget( GTK_WINDOW(toplevel) );
426 +    if( GTK_IS_WIDGET(temp) &&
427 +        gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel)) )
428 +    {
429 +        gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), event_widget );
430 +      if( GTK_WIDGET_CAN_FOCUS(temp) )
431 +        gtk_widget_grab_focus( temp );
432 +      else
433 +        gtk_widget_activate( temp );
434 +    }
435 +  }
436 +       return FALSE;
437 +}
438 +
439 +
440  #define WIDGET_REALIZED_FOR_EVENT(widget, event) \
441       (event->type == GDK_FOCUS_CHANGE || GTK_WIDGET_REALIZED(widget))
442  
443 @@ -3947,11 +4241,14 @@
444  static void
445  gtk_widget_real_grab_focus (GtkWidget *focus_widget)
446  {
447 -  if (GTK_WIDGET_CAN_FOCUS (focus_widget))
448 +  if (GTK_WIDGET_CAN_FOCUS (focus_widget) &&
449 +      GTK_WIDGET_VISIBLE (focus_widget))
450      {
451 +      static GtkIMContext *last_context = NULL;
452        GtkWidget *toplevel;
453        GtkWidget *widget;
454 -      
455 +      GtkIMContext *context;
456 +
457        /* clear the current focus setting, break if the current widget
458         * is the focus widget's parent, since containers above that will
459         * be set by the next loop.
460 @@ -3972,6 +4269,53 @@
461  
462               return;
463             }
464 +
465 +          /* Focus change stuff (previously in modified im context) */
466 +          if (GTK_IS_ENTRY (widget))
467 +            context = GTK_ENTRY (widget)->im_context;
468 +          else if (GTK_IS_TEXT_VIEW (widget))
469 +            context = GTK_TEXT_VIEW (widget)->im_context;
470 +          else
471 +            context = NULL;
472 +
473 +          if (context || last_context)
474 +            {
475 +              gboolean is_combo, is_inside_toolbar;
476 +              GtkWidget *parent;
477 +
478 +              parent = gtk_widget_get_parent (focus_widget);
479 +              is_combo = GTK_IS_TOGGLE_BUTTON (focus_widget) &&
480 +                (GTK_IS_COMBO_BOX_ENTRY (parent) ||
481 +                 GTK_IS_COMBO_BOX (parent));
482 +              is_inside_toolbar =
483 +                gtk_widget_get_ancestor (focus_widget,
484 +                                         GTK_TYPE_TOOLBAR) != NULL;
485 +
486 +              if (focus_widget == NULL ||
487 +                  !GTK_IS_ENTRY (focus_widget) &&
488 +                  !GTK_IS_TEXT_VIEW (focus_widget) &&
489 +                  !GTK_IS_SCROLLBAR (focus_widget) &&
490 +                  !GTK_IS_MENU_ITEM (focus_widget) &&
491 +                  !GTK_IS_MENU (focus_widget) &&
492 +                  !is_inside_toolbar &&
493 +                  !is_combo)
494 +                {
495 +                  /* we can't hide IM without IM context. it's possible to move
496 +                   * focus to widget which doesn't have IM context, but which
497 +                   * doesn't want IM to be hidden either. So, we have this
498 +                   * static last_context variable which is used... */
499 +                  gtk_im_context_hide (context != NULL
500 +                                       ? context : last_context);
501 +                }
502 +
503 +              if (context)
504 +                {
505 +                  if (last_context != NULL)
506 +                    g_object_unref (last_context);
507 +                  last_context = context;
508 +                  g_object_ref (last_context);
509 +                }
510 +            }
511           
512           if (widget)
513             {
514 @@ -4462,9 +4806,13 @@
515  {
516    g_return_if_fail (GTK_IS_WIDGET (widget));
517  
518 -  if (!GTK_WIDGET_USER_STYLE (widget) &&
519 -      !GTK_WIDGET_RC_STYLE (widget))
520 +  if (!GTK_WIDGET_USER_STYLE (widget) && !GTK_WIDGET_RC_STYLE (widget))
521 +  {
522 +    gboolean hfh = FALSE;
523      gtk_widget_reset_rc_style (widget);
524 +    gtk_widget_style_get( widget, "hildon-focus-handling", &hfh, NULL );
525 +    gtk_widget_set_focus_handling( widget, hfh );
526 +  }
527  }
528  
529  /* Look up the RC style for this widget, unsetting any user style that
530 @@ -6396,7 +6744,7 @@
531    
532    if (!GTK_WIDGET_DIRECTION_SET (widget))
533      gtk_widget_emit_direction_changed (widget, old_dir);
534 -  
535 +
536    if (GTK_IS_CONTAINER (widget))
537      gtk_container_forall (GTK_CONTAINER (widget),
538                           gtk_widget_set_default_direction_recurse,
539 @@ -6405,6 +6753,13 @@
540    g_object_unref (widget);
541  }
542  
543 +/* Non static */
544 +void gtk_widget_set_direction_recursive(GtkWidget * widget,  GtkTextDirection dir )
545 +{
546 +  gtk_widget_set_default_direction_recurse( widget, GUINT_TO_POINTER(dir) );
547 +}
548 +               
549 +
550  /**
551   * gtk_widget_set_default_direction:
552   * @dir: the new default direction. This cannot be
553 @@ -6422,7 +6777,7 @@
554      {
555        GList *toplevels, *tmp_list;
556        GtkTextDirection old_dir = gtk_default_direction;
557 -      
558 +
559        gtk_default_direction = dir;
560  
561        tmp_list = toplevels = gtk_window_list_toplevels ();
562 @@ -6497,6 +6852,7 @@
563  gtk_widget_finalize (GObject *object)
564  {
565    GtkWidget *widget = GTK_WIDGET (object);
566 +  GtkWidgetPrivate *priv = GTK_WIDGET_GET_PRIVATE(object);
567    GtkWidgetAuxInfo *aux_info;
568    gint *events;
569    GdkExtensionMode *mode;
570 @@ -6507,6 +6863,12 @@
571    g_object_unref (widget->style);
572    widget->style = NULL;
573  
574 +  if (priv->timer_id)
575 +    {
576 +      g_source_remove (priv->timer_id);
577 +      priv->timer_id = 0;
578 +    }
579 +  
580    if (widget->name)
581      g_free (widget->name);
582    
583 @@ -6526,6 +6888,12 @@
584    if (accessible)
585      g_object_unref (accessible);
586  
587 +  if  (GTK_IS_MENU(priv->menu))
588 +    gtk_widget_destroy (priv->menu);
589 +
590 +  if (priv->fake_event)
591 +    gdk_event_free (priv->fake_event);
592 +
593    G_OBJECT_CLASS (parent_class)->finalize (object);
594  }
595  
596 @@ -7577,3 +7945,450 @@
597    
598    g_object_notify (G_OBJECT (widget), "no_show_all");
599  }
600 +
601 +void gtk_widget_insensitive_press ( GtkWidget *widget )
602 +{
603 +  g_return_if_fail (GTK_IS_WIDGET (widget));
604 +  
605 +  g_signal_emit(widget, widget_signals[INSENSITIVE_PRESS], 0);
606 +}
607 +
608 +/*Tap And Hold*/
609 +
610 +#ifdef TAP_AND_HOLD_ANIMATION
611 +static void
612 +init_tap_and_hold_animation( GtkWidgetPrivate *priv )
613 +{
614 +  GTimeVal time;
615 +  if( priv->anim )
616 +  {
617 +    g_get_current_time( &time );
618 +    priv->iter = gdk_pixbuf_animation_get_iter( priv->anim, &time );
619 +    priv->interval = gdk_pixbuf_animation_iter_get_delay_time( priv->iter );
620 +  }
621 +}
622 +
623 +static void
624 +timeout_tap_and_hold_animation( GtkWidgetPrivate *priv )
625 +{
626 +  GdkScreen *screen;
627 +  GdkPixbuf *pic;
628 +  GdkCursor *cursor;
629 +  GTimeVal time;
630 +
631 +  if( priv->anim )
632 +  {
633 +    screen = gdk_screen_get_default();
634 +    g_get_current_time( &time );
635 +       
636 +    pic = gdk_pixbuf_animation_iter_get_pixbuf( priv->iter );
637 +    cursor = gdk_cursor_new_from_pixbuf( gdk_display_get_default(), pic,
638 +                                         priv->width, priv->height );
639 +
640 +    gdk_window_set_cursor( priv->fake_event->button.window, cursor );
641 +       
642 +    gdk_pixbuf_animation_iter_advance( priv->iter, &time );
643 +  }
644 +}
645 +
646 +static void
647 +stop_tap_and_hold_animation( GtkWidgetPrivate *priv )
648 +{
649 +  if( priv->anim )
650 +  {
651 +    gdk_window_set_cursor( priv->fake_event->button.window, NULL );
652 +  }
653 +}
654 +
655 +
656 +#endif
657 +
658 +void tap_and_hold_remove_timer( GtkWidgetPrivate *priv )
659 +{
660 +    if (priv->timer_id)
661 +    {
662 +      g_source_remove (priv->timer_id);
663 +      priv->timer_id = 0;
664 +      #ifdef TAP_AND_HOLD_ANIMATION
665 +      stop_tap_and_hold_animation( priv );
666 +      #endif
667 +    }
668 +}
669 +
670 +/**
671 + * gtk_widget_tap_and_hold_setup:
672 + *
673 + * @widget : A @GtkWidget
674 + * @menu : A @GtkWidget
675 + * @func : A @GtkCallback
676 + * @flags : A @GtkWidgetTapAndHoldFlags
677 + *
678 + * Setups the tap and hold functionality to the @widget.
679 + * The @menu is shown when the functionality is activated.
680 + * If the @menu is wanted to be positioned in a different way than the
681 + * gtk+ default, the menuposition @func can be passed as a third parameter.
682 + * Fourth parameter, @flags are explaned with detail in the documentation.
683 + */
684 +void gtk_widget_tap_and_hold_setup (GtkWidget *widget, GtkWidget *menu,
685 +            GtkCallback func, GtkWidgetTapAndHoldFlags flags)
686 +{
687 +  /*GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS(widget);*/
688 +  g_return_if_fail( GTK_IS_WIDGET(widget));
689 +  g_return_if_fail(menu == NULL || GTK_IS_MENU(menu));
690 +  g_signal_emit( widget, widget_signals[TAP_AND_HOLD_SETUP], 0, menu, func,
691 +                 flags );
692 +}
693 +
694 +static void gtk_widget_tap_and_hold_setup_real (GtkWidget *widget,
695 +         GtkWidget *menu, GtkCallback func, GtkWidgetTapAndHoldFlags flags)
696 +{
697 +  #ifdef TAP_AND_HOLD_ANIMATION
698 +  GtkStyle *style = NULL;
699 +  GError *error = NULL;
700 +  #endif
701 +  GtkWidgetPrivate *priv;
702 +  g_return_if_fail (GTK_IS_WIDGET(widget));
703 +  g_return_if_fail (menu == NULL || GTK_IS_MENU(menu));
704 +  priv = GTK_WIDGET_GET_PRIVATE (widget);
705 +
706 +  if (priv->signals_connected)
707 +    return;
708 +
709 +  _gtk_menu_enable_context_menu_behavior (menu);
710 +
711 +  priv->menu = menu;
712 +  priv->func = (GtkMenuPositionFunc)func;
713 +  priv->signals_connected = TRUE;
714 +  priv->timer_counter = 0;
715 +  priv->flags = flags;
716 +
717 +  if (flags & GTK_TAP_AND_HOLD_PASS_PRESS)
718 +    {
719 +      g_signal_connect( widget, "button-press-event",
720 +        G_CALLBACK(gtk_widget_tap_and_hold_button_press_with_events), priv );
721 +      g_signal_connect( widget, "button-release-event",
722 +        G_CALLBACK(gtk_widget_tap_and_hold_button_release_with_events), priv );
723 +      g_signal_connect( widget, "leave-notify-event",
724 +        G_CALLBACK(gtk_widget_tap_and_hold_leave_notify_with_events), priv );
725 +    }
726 +  else
727 +    {
728 +      g_signal_connect( widget, "button-press-event",
729 +                    G_CALLBACK(gtk_widget_tap_and_hold_button_press), priv );
730 +      g_signal_connect( widget, "button-release-event",
731 +                    G_CALLBACK(gtk_widget_tap_and_hold_button_release), priv );
732 +      g_signal_connect( widget, "leave-notify-event",
733 +                    G_CALLBACK(gtk_widget_tap_and_hold_leave_notify), priv );
734 +    }
735 +    
736 +#ifdef TAP_AND_HOLD_ANIMATION
737 +  priv->anim = NULL;
738 +  style = gtk_rc_get_style_by_paths(gtk_settings_get_default(),
739 +                                      "gtk-tap-and-hold-animation",
740 +                                      NULL, G_TYPE_NONE);
741 +
742 +  if( style )
743 +  {
744 +
745 +    priv->anim = gdk_pixbuf_animation_new_from_file(
746 +                        (gchar*)style->rc_style->bg_pixmap_name[0], &error );
747 +
748 +    priv->width = gdk_pixbuf_animation_get_width( priv->anim )/2;
749 +    priv->height = gdk_pixbuf_animation_get_height( priv->anim )/2;
750 +  }
751 +#endif
752 +}
753 +
754 +static void gtk_widget_real_tap_and_hold(GtkWidget *widget)
755 +{
756 +  GtkWidgetPrivate *priv = GTK_WIDGET_GET_PRIVATE (widget);
757 +
758 +  if (GTK_IS_MENU(priv->menu))
759 +    gtk_menu_popup( GTK_MENU(priv->menu), NULL, NULL,
760 +        (GtkMenuPositionFunc)priv->func,
761 +        widget, 1, gdk_x11_get_server_time(widget->window) );
762 +}
763 +
764 +static gboolean gtk_widget_tap_and_hold_timeout (GtkWidget *widget)
765 +{
766 +  GtkWidgetPrivate *priv= GTK_WIDGET_GET_PRIVATE(widget);
767 +  gboolean return_value;
768 +  gint x = 0, y = 0;
769 +
770 +  #ifdef TAP_AND_HOLD_ANIMATION
771 +  timeout_tap_and_hold_animation( priv  );
772 +  #endif
773 +  
774 +  if( priv->timer_counter )
775 +    priv->timer_counter--;
776 +  else
777 +    priv->timer_id = 0;
778 +
779 +  gdk_display_get_pointer( gdk_x11_lookup_xdisplay(
780 +      GDK_WINDOW_XDISPLAY(priv->fake_event->button.window) ),
781 +      NULL, &x, &y, NULL );
782 +
783 +  if ((abs(x - priv->x) > GTK_TAP_THRESHOLD) ||
784 +      (abs(y - priv->y) > GTK_TAP_THRESHOLD))
785 +    {
786 +      if (priv->stype != priv->type_on_press)
787 +        gtk_widget_set_state( widget, priv->stype );
788 +      priv->timer_counter = 0;
789 +      priv->timer_id = 0;
790 +      priv->x = priv->y = 0;
791 +      priv->run_press = FALSE;
792 +      g_signal_emit_by_name (G_OBJECT(widget), "button-press-event",
793 +                             priv->fake_event, &return_value);
794 +      return FALSE;
795 +   }
796 +  if (!priv->timer_id)
797 +    {
798 +      if (priv->stype != priv->type_on_press)
799 +        gtk_widget_set_state( widget, priv->stype );
800 +      #ifdef TAP_AND_HOLD_ANIMATION
801 +      stop_tap_and_hold_animation( priv );
802 +      #endif
803 +      g_signal_emit(widget, widget_signals[TAP_AND_HOLD], 0);
804 +      priv->x = x;
805 +      priv->y = y;
806 +      return FALSE;
807 +    }
808 +  return TRUE;
809 +}
810 +
811 +static gboolean gtk_widget_tap_and_hold_button_press (GtkWidget *widget,
812 +                                      GdkEvent *event, GtkWidgetPrivate *priv)
813 +{
814 +  if (!priv->run_press || event->button.button != 1)
815 +    {
816 +      priv->run_press = TRUE;
817 +      return FALSE;
818 +    }
819 +  
820 +  if (event->button.type == GDK_2BUTTON_PRESS)
821 +    return FALSE;
822 +
823 +  if (priv->fake_event)
824 +    gdk_event_free (priv->fake_event);
825 +  priv->fake_event = gdk_event_copy(event);
826 +  
827 +  if (!priv->timer_id)
828 +    {
829 +      priv->stype = GTK_WIDGET_STATE(widget);
830 +      if (priv->stype != priv->type_on_press)
831 +        gtk_widget_set_state( widget, priv->type_on_press );
832 +      gdk_display_get_pointer(
833 +         gdk_x11_lookup_xdisplay( GDK_WINDOW_XDISPLAY(event->button.window) ),
834 +         NULL, &priv->x, &priv->y, NULL );
835 +      priv->timer_counter = GTK_TAP_AND_HOLD_TIMER_COUNTER;
836 +      
837 +      #ifdef TAP_AND_HOLD_ANIMATION
838 +      init_tap_and_hold_animation( priv );
839 +      #endif
840 +      priv->timer_id = g_timeout_add( priv->interval,
841 +                        (GSourceFunc)gtk_widget_tap_and_hold_timeout, widget );
842 +    }
843 +return TRUE;
844 +}
845 +
846 +static gboolean gtk_widget_tap_and_hold_button_release (GtkWidget *widget,
847 +                                      GdkEvent *event, GtkWidgetPrivate *priv)
848 +{
849 +  gboolean return_value;
850 +
851 +  if (!priv->run_press || event->button.button != 1 || !priv->timer_id ||
852 +     event->button.type == GDK_2BUTTON_PRESS)
853 +    return FALSE;
854 +
855 +  g_source_remove (priv->timer_id);
856 +  priv->timer_id = 0;
857 +  priv->x = priv->y = priv->timer_counter = 0;
858 +  if (priv->stype != priv->type_on_press)
859 +    gtk_widget_set_state (widget, priv->stype);
860 +
861 +  #ifdef TAP_AND_HOLD_ANIMATION
862 +  stop_tap_and_hold_animation( priv );
863 +  #endif
864 +  
865 +  if (priv->flags & GTK_TAP_AND_HOLD_NO_SIGNALS)
866 +      return FALSE;
867 +
868 +  priv->run_press = FALSE;
869 +  
870 +  g_signal_emit_by_name (G_OBJECT(widget), "button-press-event",
871 +                         priv->fake_event, &return_value);
872 +
873 +return FALSE;
874 +}
875 +
876 +static gboolean gtk_widget_tap_and_hold_leave_notify (GtkWidget *widget,
877 +                                      GdkEvent *event, GtkWidgetPrivate *priv)
878 +{
879 +  gboolean return_value;
880 +  if (!priv->timer_id)
881 +    return FALSE;
882 +
883 +  g_source_remove (priv->timer_id);
884 +  priv->timer_id = 0;
885 +  priv->x = priv->y = priv->timer_counter = 0;
886 +  if (priv->stype != priv->type_on_press)
887 +    gtk_widget_set_state (widget, priv->stype);
888 +
889 +  #ifdef TAP_AND_HOLD_ANIMATION
890 +  stop_tap_and_hold_animation( priv );
891 +  #endif
892 +  priv->run_press = FALSE;
893 +  g_signal_emit_by_name (G_OBJECT(widget), "button-press-event",
894 +                         priv->fake_event, &return_value);
895 +
896 +return FALSE;
897 +}
898 +
899 +static gboolean
900 +gtk_widget_tap_and_hold_timeout_with_events (GtkWidget *widget)
901 +{
902 +  gint x, y;
903 +  GtkWidgetPrivate *priv= GTK_WIDGET_GET_PRIVATE(widget);
904 +
905 +  g_return_val_if_fail (priv->fake_event, FALSE);
906 +
907 +  #ifdef TAP_AND_HOLD_ANIMATION
908 +  timeout_tap_and_hold_animation( priv  );
909 +  #endif
910 +  
911 +  gdk_display_get_pointer( gdk_x11_lookup_xdisplay(
912 +      GDK_WINDOW_XDISPLAY(priv->fake_event->button.window) ),
913 +      NULL, &x, &y, NULL );
914 +  
915 +  if( priv->timer_counter )
916 +  {
917 +    priv->timer_counter--;
918 +    if ((abs(x - priv->x) > GTK_TAP_THRESHOLD) ||
919 +        (abs(y - priv->y) > GTK_TAP_THRESHOLD))
920 +     {
921 +       #ifdef TAP_AND_HOLD_ANIMATION
922 +       stop_tap_and_hold_animation( priv );
923 +       #endif
924 +       tap_and_hold_remove_timer( priv );
925 +     }
926 +    return TRUE;
927 +  }
928 +
929 +  if (!((abs(x - priv->x) > GTK_TAP_THRESHOLD) ||
930 +     (abs(y - priv->y) > GTK_TAP_THRESHOLD)))
931 +    {
932 +      gboolean return_value;
933 +      priv->fake_event->button.type = GDK_BUTTON_RELEASE;
934 +      priv->fake_event->button.x = x;
935 +      priv->fake_event->button.y = y;
936 +      g_signal_emit_by_name (G_OBJECT(widget), "button-release-event",
937 +                             priv->fake_event, &return_value);
938 +      #ifdef TAP_AND_HOLD_ANIMATION
939 +      stop_tap_and_hold_animation( priv );
940 +      #endif
941 +      g_signal_emit(widget, widget_signals[TAP_AND_HOLD], 0);
942 +      priv->timer_id = 0;
943 +      priv->x = x;
944 +      priv->y = y;
945 +      gdk_event_free(priv->fake_event);
946 +      priv->fake_event = NULL;
947 +    }
948
949 +    
950 + if (priv->timer_id)
951 +    {
952 +      g_source_remove (priv->timer_id);
953 +      priv->timer_id = 0;
954 +    }
955 +
956 +  return FALSE;
957 +}
958 +
959 +static gboolean gtk_widget_tap_and_hold_button_press_with_events(
960 +                   GtkWidget *widget, GdkEvent *event, GtkWidgetPrivate *priv)
961 +{
962 +  if( priv->timer_id || event->button.type == GDK_2BUTTON_PRESS)
963 +    return FALSE;
964 +
965 +  if (priv->fake_event)
966 +    gdk_event_free (priv->fake_event);
967 +  priv->fake_event = gdk_event_copy (event);
968 +
969 +  gdk_display_get_pointer(
970 +         gdk_x11_lookup_xdisplay(GDK_WINDOW_XDISPLAY(event->button.window)),
971 +         NULL, &priv->x, &priv->y, NULL);
972 +  #ifdef TAP_AND_HOLD_ANIMATION
973 +  init_tap_and_hold_animation( priv );
974 +  #endif
975 +  priv->timer_counter = GTK_TAP_AND_HOLD_TIMER_COUNTER;
976 +  priv->timer_id = g_timeout_add(priv->interval,
977 +                    (GSourceFunc)gtk_widget_tap_and_hold_timeout_with_events, 
978 +                    widget);
979 +  return FALSE;
980 +}
981 +
982 +static gboolean gtk_widget_tap_and_hold_button_release_with_events(
983 +                   GtkWidget *widget, GdkEvent *event, GtkWidgetPrivate *priv)
984 +{
985 +  tap_and_hold_remove_timer( priv );
986 +  return FALSE;
987 +}
988 +
989 +static gboolean gtk_widget_tap_and_hold_leave_notify_with_events(
990 +                   GtkWidget *widget, GdkEvent *event, GtkWidgetPrivate *priv)
991 +{
992 +  tap_and_hold_remove_timer( priv );
993 +  return FALSE;
994 +}
995 +
996 +/**
997 + * gtk_widget_tap_and_hold_menu_position_top:
998 + * @menu: a #GtkMenu
999 + * @x: x cordinate to be returned
1000 + * @y: y cordinate to be returned
1001 + * @push_in: If going off screen, push it pack on the screen
1002 + * @widget: a #GtkWidget
1003 + *
1004 + * Pre-made menu positioning function.
1005 + * It positiones the @menu over the @widget.
1006 + * 
1007 + **/
1008 +void gtk_widget_tap_and_hold_menu_position_top( GtkWidget *menu,
1009 +                       gint *x, gint *y, gboolean *push_in, GtkWidget *widget )
1010 +{
1011 +  /* 
1012 +   * This function positiones the menu above widgets.
1013 +   * This is a modified version of the position function 
1014 +   * gtk_combo_box_position_over. 
1015 +   */
1016 +  GtkWidget *topw;
1017 +  GtkRequisition requisition;
1018 +  gint screen_width = 0;
1019 +  gint menu_xpos = 0;
1020 +  gint menu_ypos = 0;
1021 +  gint w_xpos = 0, w_ypos = 0;
1022 +
1023 +  gtk_widget_size_request( menu, &requisition );
1024 +
1025 +  topw = gtk_widget_get_toplevel(widget);
1026 +  gdk_window_get_origin( topw->window, &w_xpos, &w_ypos );
1027 +
1028 +  menu_xpos += widget->allocation.x + w_xpos;
1029 +  menu_ypos += widget->allocation.y + w_ypos - requisition.height;
1030 +
1031 +  if( gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL )
1032 +    menu_xpos = menu_xpos + widget->allocation.width - requisition.width;
1033 +
1034 +  screen_width = gdk_screen_get_width( gtk_widget_get_screen(widget) );
1035 +
1036 +  if( menu_xpos < w_xpos )
1037 +    menu_xpos = w_xpos;
1038 +  else if( (menu_xpos + requisition.width) > screen_width )
1039 +    menu_xpos -= ( (menu_xpos + requisition.width) - screen_width );
1040 +  if( menu_ypos < w_ypos )
1041 +    menu_ypos = w_ypos;
1042 +
1043 +  *x = menu_xpos;
1044 +  *y = menu_ypos;
1045 +  *push_in = TRUE;
1046 +}