diff options
Diffstat (limited to 'meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkwidget.c.diff')
-rw-r--r-- | meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkwidget.c.diff | 1046 |
1 files changed, 1046 insertions, 0 deletions
diff --git a/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkwidget.c.diff b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkwidget.c.diff new file mode 100644 index 0000000000..ecef0041eb --- /dev/null +++ b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtkwidget.c.diff @@ -0,0 +1,1046 @@ +--- gtk+-2.6.4/gtk/gtkwidget.c 2005-02-24 18:44:02.000000000 +0200 ++++ gtk+-2.6.4/gtk/gtkwidget.c 2005-04-06 16:19:38.386702696 +0300 +@@ -28,6 +28,8 @@ + #include <stdarg.h> + #include <string.h> + #include <locale.h> ++#include <stdlib.h> ++#include <x11/gdkx.h> + #include "gtkalias.h" + #include "gtkcontainer.h" + #include "gtkaccelmap.h" +@@ -44,6 +46,11 @@ + #include "gtkwindow.h" + #include "gtkbindings.h" + #include "gtkprivate.h" ++#include "gtktreeview.h" ++#include "gtkentry.h" ++#include "gtktextview.h" ++#include "gtkimcontext.h" ++#include "gtkmenu.h" + #include "gdk/gdk.h" + #include "gdk/gdkprivate.h" /* Used in gtk_reset_shapes_recurse to avoid copy */ + #include <gobject/gvaluecollector.h> +@@ -53,11 +60,30 @@ + #include "gtkaccessible.h" + #include "gtktooltips.h" + #include "gtkinvisible.h" ++#include "gtkscrollbar.h" /* Following are needed for special focus changes */ ++#include "gtktoolbar.h" ++#include "gtkmenu.h" ++#include "gtkmenuitem.h" ++#include "gtktogglebutton.h" ++#include "gtkcomboboxentry.h" ++#include "gtktogglebutton.h" ++#include "gtkcomboboxentry.h" + + #define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w) + #define INIT_PATH_SIZE (512) + ++#define GTK_TAP_THRESHOLD 30 ++#define GTK_TAP_MENU_THRESHOLD 20 ++#define GTK_TAP_AND_HOLD_TIMER_COUNTER 11 ++#define GTK_TAP_AND_HOLD_TIMER_INTERVAL 100 + ++typedef struct _GtkWidgetPrivate GtkWidgetPrivate; ++ ++#define GTK_WIDGET_GET_PRIVATE(obj) ( G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ ++ GTK_TYPE_WIDGET, GtkWidgetPrivate) ) ++ ++#define TAP_AND_HOLD_ANIMATION 1 ++ + enum { + SHOW, + HIDE, +@@ -120,6 +146,9 @@ + ACCEL_CLOSURES_CHANGED, + SCREEN_CHANGED, + CAN_ACTIVATE_ACCEL, ++ INSENSITIVE_PRESS, ++ TAP_AND_HOLD, ++ TAP_AND_HOLD_SETUP, + LAST_SIGNAL + }; + +@@ -142,7 +171,8 @@ + PROP_STYLE, + PROP_EVENTS, + PROP_EXTENSION_EVENTS, +- PROP_NO_SHOW_ALL ++ PROP_NO_SHOW_ALL, ++ PROP_TAP_AND_HOLD + }; + + typedef struct _GtkStateData GtkStateData; +@@ -155,7 +185,50 @@ + guint use_forall : 1; + }; + ++struct _GtkWidgetPrivate ++{ ++ GtkWidget *menu; ++ guint timer_id; ++ ++ GtkStateType stype; ++ GtkStateType type_on_press; ++ GdkEvent *fake_event; ++ GtkMenuPositionFunc func; ++ gint x, y; ++ gint timer_counter; ++ gint run_press : 1; ++ gint button_pressed : 1; ++ gint signals_connected : 1; ++ GtkWidgetTapAndHoldFlags flags; ++ gboolean state_set; ++ guint interval; ++ ++#ifdef TAP_AND_HOLD_ANIMATION ++ GdkPixbufAnimation *anim; ++ GdkPixbufAnimationIter *iter; ++ guint width, height; ++#endif ++}; ++ + ++/* --- Tap And Hold --- */ ++static gboolean gtk_widget_tap_and_hold_button_press_with_events( GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv ); ++static gboolean gtk_widget_tap_and_hold_button_release_with_events( GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv ); ++static gboolean gtk_widget_tap_and_hold_leave_notify_with_events( GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv ); ++static gboolean gtk_widget_tap_and_hold_timeout_with_events( GtkWidget *widget ); ++static gboolean gtk_widget_tap_and_hold_timeout( GtkWidget *widget ); ++static gboolean gtk_widget_tap_and_hold_button_press( GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv ); ++static gboolean gtk_widget_tap_and_hold_button_release( GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv ); ++static gboolean gtk_widget_tap_and_hold_leave_notify( GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv ); ++static void gtk_widget_tap_and_hold_setup_real( GtkWidget *widget, ++ GtkWidget *menu, GtkCallback func, GtkWidgetTapAndHoldFlags flags ); ++static void gtk_widget_real_tap_and_hold(GtkWidget *widget); + /* --- prototypes --- */ + static void gtk_widget_class_init (GtkWidgetClass *klass); + static void gtk_widget_init (GtkWidget *widget); +@@ -228,6 +301,13 @@ + gint width, + gint height); + ++/*Hildon focus handling*/ ++static void gtk_widget_set_focus_handling( GtkWidget *widget, gboolean state ); ++ ++static gboolean gtk_widget_enter_notify_event( GtkWidget *widget, GdkEventCrossing *event ); ++static gboolean gtk_widget_leave_notify_event( GtkWidget *widget, GdkEventCrossing *event ); ++static gint gtk_widget_button_release_event( GtkWidget *widget, GdkEventButton *event ); ++static gint gtk_widget_button_press_event( GtkWidget *widget, GdkEventButton *event ); + + /* --- variables --- */ + static gpointer parent_class = NULL; +@@ -239,6 +319,9 @@ + static GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR; + static GParamSpecPool *style_property_spec_pool = NULL; + ++static gboolean on_same_widget = FALSE; /*Hildon focus handling*/ ++static gboolean mouse_pressed = FALSE; /*Hildon focus handling*/ ++ + static GQuark quark_property_parser = 0; + static GQuark quark_aux_info = 0; + static GQuark quark_accel_path = 0; +@@ -396,6 +479,9 @@ + klass->drag_data_received = NULL; + klass->screen_changed = NULL; + klass->can_activate_accel = gtk_widget_real_can_activate_accel; ++ klass->tap_and_hold_setup = gtk_widget_tap_and_hold_setup_real; ++ klass->insensitive_press = NULL; ++ klass->tap_and_hold = gtk_widget_real_tap_and_hold; + + klass->show_help = gtk_widget_real_show_help; + +@@ -404,6 +490,18 @@ + + klass->no_expose_event = NULL; + ++ g_type_class_add_private( klass, sizeof(GtkWidgetPrivate) ); ++ ++ g_object_class_install_property (gobject_class, ++ PROP_TAP_AND_HOLD, ++ g_param_spec_int ("tap_and_hold_state", ++ P_("Tap and hold State type"), ++ P_("Sets the state to be used to the tap and hold functionality. The default is GTK_STATE_NORMAL"), ++ 0, ++ 4, /*4 == Last state in GTK+-2.0*/ ++ GTK_STATE_NORMAL, ++ G_PARAM_READWRITE)); ++ + g_object_class_install_property (gobject_class, + PROP_NAME, + g_param_spec_string ("name", +@@ -1389,6 +1487,31 @@ + _gtk_marshal_BOOLEAN__UINT, + G_TYPE_BOOLEAN, 1, G_TYPE_UINT); + ++ widget_signals[INSENSITIVE_PRESS] = ++ g_signal_new ("insensitive_press", ++ G_TYPE_FROM_CLASS (gobject_class), ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GtkWidgetClass, insensitive_press), ++ NULL, NULL, ++ _gtk_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); ++ ++ widget_signals[TAP_AND_HOLD] = ++ g_signal_new("tap-and-hold", G_TYPE_FROM_CLASS(gobject_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET(GtkWidgetClass, tap_and_hold), ++ NULL, NULL, ++ _gtk_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); ++ ++ widget_signals[TAP_AND_HOLD_SETUP] = ++ g_signal_new("tap-and-hold-setup", G_TYPE_FROM_CLASS(gobject_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET(GtkWidgetClass, tap_and_hold_setup), ++ NULL, NULL, /*FIXME -- OBJECT_POINTER_FLAGS*/ ++ _gtk_marshal_VOID__OBJECT_UINT_FLAGS, ++ G_TYPE_NONE, 3, G_TYPE_OBJECT, G_TYPE_POINTER, G_TYPE_UINT); ++ + binding_set = gtk_binding_set_by_class (klass); + gtk_binding_entry_add_signal (binding_set, GDK_F10, GDK_SHIFT_MASK, + "popup_menu", 0); +@@ -1418,7 +1541,12 @@ + P_("Whether to draw the focus indicator inside widgets"), + TRUE, + G_PARAM_READABLE)); +- ++ gtk_widget_class_install_style_property (klass, ++ g_param_spec_boolean ("hildon-focus-handling", ++ P_("Hildon focus handling"), ++ P_("Whether the widget is using the hildon like focus handling or not"), ++ FALSE, ++ G_PARAM_READABLE)); + gtk_widget_class_install_style_property (klass, + g_param_spec_int ("focus-line-width", + P_("Focus linewidth"), +@@ -1543,6 +1671,8 @@ + case PROP_NO_SHOW_ALL: + gtk_widget_set_no_show_all (widget, g_value_get_boolean (value)); + break; ++ case PROP_TAP_AND_HOLD: ++ GTK_WIDGET_GET_PRIVATE(widget)->type_on_press = g_value_get_int(value); + default: + break; + } +@@ -1637,16 +1767,45 @@ + case PROP_NO_SHOW_ALL: + g_value_set_boolean (value, gtk_widget_get_no_show_all (widget)); + break; ++ case PROP_TAP_AND_HOLD: ++ g_value_set_int (value, ++ (int)GTK_WIDGET_GET_PRIVATE(widget)->type_on_press); + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + ++static void gtk_widget_set_focus_handling( GtkWidget *widget, gboolean state ) ++{ ++ GtkWidgetPrivate *priv; ++ priv = GTK_WIDGET_GET_PRIVATE (widget); ++ ++ if( state && GTK_WIDGET_CAN_FOCUS(widget) ) ++ { ++ if (!priv->state_set) ++ { ++ g_signal_connect( G_OBJECT(widget), "button-press-event", ++ G_CALLBACK(gtk_widget_button_press_event), NULL ); ++ g_signal_connect( G_OBJECT(widget), "button-release-event", ++ G_CALLBACK(gtk_widget_button_release_event), NULL ); ++ g_signal_connect( G_OBJECT(widget), "enter-notify-event", ++ G_CALLBACK(gtk_widget_enter_notify_event), NULL ); ++ g_signal_connect( G_OBJECT(widget), "leave-notify-event", ++ G_CALLBACK(gtk_widget_leave_notify_event), NULL ); ++ priv->state_set = TRUE; ++ } ++ } ++} ++ + static void + gtk_widget_init (GtkWidget *widget) + { ++ GtkWidgetPrivate *priv; + GTK_PRIVATE_FLAGS (widget) = PRIVATE_GTK_CHILD_VISIBLE; ++ ++ priv = GTK_WIDGET_GET_PRIVATE(widget); ++ + widget->state = GTK_STATE_NORMAL; + widget->saved_state = GTK_STATE_NORMAL; + widget->name = NULL; +@@ -1659,6 +1818,18 @@ + widget->window = NULL; + widget->parent = NULL; + ++ priv->fake_event = NULL; ++ priv->timer_id = 0; ++ priv->menu = NULL; ++ priv->run_press = TRUE; ++ priv->signals_connected = FALSE; ++ priv->x = priv->y = 0; ++ priv->func = NULL; ++ priv->timer_counter = 0; ++ priv->flags = 0x0; ++ priv->state_set = FALSE; ++ priv->interval = GTK_TAP_AND_HOLD_TIMER_INTERVAL; ++ + GTK_WIDGET_SET_FLAGS (widget, + GTK_SENSITIVE | + GTK_PARENT_SENSITIVE | +@@ -1670,6 +1841,7 @@ + GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED); + + widget->style = gtk_widget_get_default_style (); ++ + g_object_ref (widget->style); + } + +@@ -2153,6 +2325,7 @@ + + if ((GTK_WIDGET_FLAGS (widget) & GTK_NO_SHOW_ALL) != 0) + return; ++ + + class = GTK_WIDGET_GET_CLASS (widget); + +@@ -3400,6 +3573,127 @@ + return FALSE; + } + ++/** ++ * gtk_widget_button_press_event ++ * @widget: a #GtkWidget ++ * @event: a #GtkEventKey ++ * ++**/ ++static gboolean gtk_widget_button_press_event(GtkWidget *widget, GdkEventButton *event ) ++{ ++ if( !mouse_pressed /*&& !GTK_IS_TREE_VIEW(widget) && !GTK_IS_ENTRY(widget)*/ ) ++ { ++ GtkWidget *toplevel; ++ toplevel = gtk_widget_get_toplevel (widget); ++ if (GTK_IS_WINDOW (toplevel)) ++ { ++ mouse_pressed = TRUE; ++ ++ if( /*!gtk_window_get_prev_focus_widget(GTK_WINDOW(toplevel)) &&*/ ++ GTK_IS_WIDGET(GTK_WINDOW(toplevel)->focus_widget) ) ++ gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), ++ GTK_WINDOW(toplevel)->focus_widget ); ++ } ++ } ++ return FALSE; ++} ++ ++/** ++ * gtk_widget_button_release_event ++ * @widget: a #GtkWidget ++ * @event: a #GtkEventKey ++ * ++**/ ++static gboolean gtk_widget_button_release_event(GtkWidget *widget, GdkEventButton *event ) ++{ ++ if( mouse_pressed /*&& !GTK_IS_ENTRY(widget)*/ ) ++ { ++ GtkWidget *toplevel; ++ GtkWidget *event_widget; ++ event_widget = gtk_get_event_widget( (GdkEvent*) event ); ++ toplevel = gtk_widget_get_toplevel (widget); ++ ++ mouse_pressed = FALSE; ++ on_same_widget = TRUE; ++ ++ if (GTK_IS_WINDOW (toplevel)) ++ { ++ if( !on_same_widget && GTK_IS_WIDGET(GTK_WINDOW(toplevel)->focus_widget) ) ++ gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), GTK_WINDOW(toplevel)->focus_widget ); ++ else ++ gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), event_widget ); ++ } ++ } ++ return FALSE; ++} ++ ++/** ++ * gtk_widget_enter_notify_event ++ * @widget: a #GtkWidget ++ * @event: a #GtkEventCrossing ++ * ++**/ ++static gboolean gtk_widget_enter_notify_event( GtkWidget *widget, GdkEventCrossing *event ) ++{ ++ GtkWidget *toplevel; ++ GtkWidget *event_widget; ++ /*if( GTK_IS_ENTRY(widget) ) ++ return FALSE;*/ ++ ++ toplevel = gtk_widget_get_toplevel (widget); ++ event_widget = gtk_get_event_widget ( (GdkEvent*) event ); ++ ++ if(mouse_pressed && !on_same_widget && gtk_window_get_prev_focus_widget( GTK_WINDOW(toplevel) ) == event_widget) ++ { ++/* GtkWidget *temp;*/ ++ on_same_widget = TRUE; ++ ++/* temp = gtk_window_get_prev_focus_widget( GTK_WINDOW(toplevel) );*/ ++ if( GTK_IS_WIDGET(GTK_WINDOW(toplevel)->focus_widget) ) ++ { ++ gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), GTK_WINDOW(toplevel)->focus_widget ); ++ if( GTK_WIDGET_CAN_FOCUS(event_widget) ) ++ gtk_widget_grab_focus( event_widget ); ++ else ++ gtk_widget_activate( event_widget ); ++ } ++ } ++ return FALSE; ++} ++ ++ ++/** ++ * gtk_widget_leave_notify_event ++ * @widget: a #GtkWidget ++ * @event: a #GtkEventCrossing ++ * ++**/ ++static gboolean gtk_widget_leave_notify_event( GtkWidget *widget, GdkEventCrossing *event ) ++{ ++ if( mouse_pressed && on_same_widget /*&& !GTK_IS_ENTRY(widget)*/ ) ++ { ++ GtkWidget *event_widget; ++ GtkWidget *toplevel; ++ GtkWidget *temp; ++ toplevel = gtk_widget_get_toplevel( widget ); ++ event_widget = gtk_get_event_widget( (GdkEvent*) event ); ++ on_same_widget = FALSE; ++ ++ temp = gtk_window_get_prev_focus_widget( GTK_WINDOW(toplevel) ); ++ if( GTK_IS_WIDGET(temp) && ++ gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel)) ) ++ { ++ gtk_window_set_prev_focus_widget( GTK_WINDOW(toplevel), event_widget ); ++ if( GTK_WIDGET_CAN_FOCUS(temp) ) ++ gtk_widget_grab_focus( temp ); ++ else ++ gtk_widget_activate( temp ); ++ } ++ } ++ return FALSE; ++} ++ ++ + #define WIDGET_REALIZED_FOR_EVENT(widget, event) \ + (event->type == GDK_FOCUS_CHANGE || GTK_WIDGET_REALIZED(widget)) + +@@ -3947,11 +4241,14 @@ + static void + gtk_widget_real_grab_focus (GtkWidget *focus_widget) + { +- if (GTK_WIDGET_CAN_FOCUS (focus_widget)) ++ if (GTK_WIDGET_CAN_FOCUS (focus_widget) && ++ GTK_WIDGET_VISIBLE (focus_widget)) + { ++ static GtkIMContext *last_context = NULL; + GtkWidget *toplevel; + GtkWidget *widget; +- ++ GtkIMContext *context; ++ + /* clear the current focus setting, break if the current widget + * is the focus widget's parent, since containers above that will + * be set by the next loop. +@@ -3972,6 +4269,53 @@ + + return; + } ++ ++ /* Focus change stuff (previously in modified im context) */ ++ if (GTK_IS_ENTRY (widget)) ++ context = GTK_ENTRY (widget)->im_context; ++ else if (GTK_IS_TEXT_VIEW (widget)) ++ context = GTK_TEXT_VIEW (widget)->im_context; ++ else ++ context = NULL; ++ ++ if (context || last_context) ++ { ++ gboolean is_combo, is_inside_toolbar; ++ GtkWidget *parent; ++ ++ parent = gtk_widget_get_parent (focus_widget); ++ is_combo = GTK_IS_TOGGLE_BUTTON (focus_widget) && ++ (GTK_IS_COMBO_BOX_ENTRY (parent) || ++ GTK_IS_COMBO_BOX (parent)); ++ is_inside_toolbar = ++ gtk_widget_get_ancestor (focus_widget, ++ GTK_TYPE_TOOLBAR) != NULL; ++ ++ if (focus_widget == NULL || ++ !GTK_IS_ENTRY (focus_widget) && ++ !GTK_IS_TEXT_VIEW (focus_widget) && ++ !GTK_IS_SCROLLBAR (focus_widget) && ++ !GTK_IS_MENU_ITEM (focus_widget) && ++ !GTK_IS_MENU (focus_widget) && ++ !is_inside_toolbar && ++ !is_combo) ++ { ++ /* we can't hide IM without IM context. it's possible to move ++ * focus to widget which doesn't have IM context, but which ++ * doesn't want IM to be hidden either. So, we have this ++ * static last_context variable which is used... */ ++ gtk_im_context_hide (context != NULL ++ ? context : last_context); ++ } ++ ++ if (context) ++ { ++ if (last_context != NULL) ++ g_object_unref (last_context); ++ last_context = context; ++ g_object_ref (last_context); ++ } ++ } + + if (widget) + { +@@ -4462,9 +4806,13 @@ + { + g_return_if_fail (GTK_IS_WIDGET (widget)); + +- if (!GTK_WIDGET_USER_STYLE (widget) && +- !GTK_WIDGET_RC_STYLE (widget)) ++ if (!GTK_WIDGET_USER_STYLE (widget) && !GTK_WIDGET_RC_STYLE (widget)) ++ { ++ gboolean hfh = FALSE; + gtk_widget_reset_rc_style (widget); ++ gtk_widget_style_get( widget, "hildon-focus-handling", &hfh, NULL ); ++ gtk_widget_set_focus_handling( widget, hfh ); ++ } + } + + /* Look up the RC style for this widget, unsetting any user style that +@@ -6396,7 +6744,7 @@ + + if (!GTK_WIDGET_DIRECTION_SET (widget)) + gtk_widget_emit_direction_changed (widget, old_dir); +- ++ + if (GTK_IS_CONTAINER (widget)) + gtk_container_forall (GTK_CONTAINER (widget), + gtk_widget_set_default_direction_recurse, +@@ -6405,6 +6753,13 @@ + g_object_unref (widget); + } + ++/* Non static */ ++void gtk_widget_set_direction_recursive(GtkWidget * widget, GtkTextDirection dir ) ++{ ++ gtk_widget_set_default_direction_recurse( widget, GUINT_TO_POINTER(dir) ); ++} ++ ++ + /** + * gtk_widget_set_default_direction: + * @dir: the new default direction. This cannot be +@@ -6422,7 +6777,7 @@ + { + GList *toplevels, *tmp_list; + GtkTextDirection old_dir = gtk_default_direction; +- ++ + gtk_default_direction = dir; + + tmp_list = toplevels = gtk_window_list_toplevels (); +@@ -6497,6 +6852,7 @@ + gtk_widget_finalize (GObject *object) + { + GtkWidget *widget = GTK_WIDGET (object); ++ GtkWidgetPrivate *priv = GTK_WIDGET_GET_PRIVATE(object); + GtkWidgetAuxInfo *aux_info; + gint *events; + GdkExtensionMode *mode; +@@ -6507,6 +6863,12 @@ + g_object_unref (widget->style); + widget->style = NULL; + ++ if (priv->timer_id) ++ { ++ g_source_remove (priv->timer_id); ++ priv->timer_id = 0; ++ } ++ + if (widget->name) + g_free (widget->name); + +@@ -6526,6 +6888,12 @@ + if (accessible) + g_object_unref (accessible); + ++ if (GTK_IS_MENU(priv->menu)) ++ gtk_widget_destroy (priv->menu); ++ ++ if (priv->fake_event) ++ gdk_event_free (priv->fake_event); ++ + G_OBJECT_CLASS (parent_class)->finalize (object); + } + +@@ -7577,3 +7945,450 @@ + + g_object_notify (G_OBJECT (widget), "no_show_all"); + } ++ ++void gtk_widget_insensitive_press ( GtkWidget *widget ) ++{ ++ g_return_if_fail (GTK_IS_WIDGET (widget)); ++ ++ g_signal_emit(widget, widget_signals[INSENSITIVE_PRESS], 0); ++} ++ ++/*Tap And Hold*/ ++ ++#ifdef TAP_AND_HOLD_ANIMATION ++static void ++init_tap_and_hold_animation( GtkWidgetPrivate *priv ) ++{ ++ GTimeVal time; ++ if( priv->anim ) ++ { ++ g_get_current_time( &time ); ++ priv->iter = gdk_pixbuf_animation_get_iter( priv->anim, &time ); ++ priv->interval = gdk_pixbuf_animation_iter_get_delay_time( priv->iter ); ++ } ++} ++ ++static void ++timeout_tap_and_hold_animation( GtkWidgetPrivate *priv ) ++{ ++ GdkScreen *screen; ++ GdkPixbuf *pic; ++ GdkCursor *cursor; ++ GTimeVal time; ++ ++ if( priv->anim ) ++ { ++ screen = gdk_screen_get_default(); ++ g_get_current_time( &time ); ++ ++ pic = gdk_pixbuf_animation_iter_get_pixbuf( priv->iter ); ++ cursor = gdk_cursor_new_from_pixbuf( gdk_display_get_default(), pic, ++ priv->width, priv->height ); ++ ++ gdk_window_set_cursor( priv->fake_event->button.window, cursor ); ++ ++ gdk_pixbuf_animation_iter_advance( priv->iter, &time ); ++ } ++} ++ ++static void ++stop_tap_and_hold_animation( GtkWidgetPrivate *priv ) ++{ ++ if( priv->anim ) ++ { ++ gdk_window_set_cursor( priv->fake_event->button.window, NULL ); ++ } ++} ++ ++ ++#endif ++ ++void tap_and_hold_remove_timer( GtkWidgetPrivate *priv ) ++{ ++ if (priv->timer_id) ++ { ++ g_source_remove (priv->timer_id); ++ priv->timer_id = 0; ++ #ifdef TAP_AND_HOLD_ANIMATION ++ stop_tap_and_hold_animation( priv ); ++ #endif ++ } ++} ++ ++/** ++ * gtk_widget_tap_and_hold_setup: ++ * ++ * @widget : A @GtkWidget ++ * @menu : A @GtkWidget ++ * @func : A @GtkCallback ++ * @flags : A @GtkWidgetTapAndHoldFlags ++ * ++ * Setups the tap and hold functionality to the @widget. ++ * The @menu is shown when the functionality is activated. ++ * If the @menu is wanted to be positioned in a different way than the ++ * gtk+ default, the menuposition @func can be passed as a third parameter. ++ * Fourth parameter, @flags are explaned with detail in the documentation. ++ */ ++void gtk_widget_tap_and_hold_setup (GtkWidget *widget, GtkWidget *menu, ++ GtkCallback func, GtkWidgetTapAndHoldFlags flags) ++{ ++ /*GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS(widget);*/ ++ g_return_if_fail( GTK_IS_WIDGET(widget)); ++ g_return_if_fail(menu == NULL || GTK_IS_MENU(menu)); ++ g_signal_emit( widget, widget_signals[TAP_AND_HOLD_SETUP], 0, menu, func, ++ flags ); ++} ++ ++static void gtk_widget_tap_and_hold_setup_real (GtkWidget *widget, ++ GtkWidget *menu, GtkCallback func, GtkWidgetTapAndHoldFlags flags) ++{ ++ #ifdef TAP_AND_HOLD_ANIMATION ++ GtkStyle *style = NULL; ++ GError *error = NULL; ++ #endif ++ GtkWidgetPrivate *priv; ++ g_return_if_fail (GTK_IS_WIDGET(widget)); ++ g_return_if_fail (menu == NULL || GTK_IS_MENU(menu)); ++ priv = GTK_WIDGET_GET_PRIVATE (widget); ++ ++ if (priv->signals_connected) ++ return; ++ ++ _gtk_menu_enable_context_menu_behavior (menu); ++ ++ priv->menu = menu; ++ priv->func = (GtkMenuPositionFunc)func; ++ priv->signals_connected = TRUE; ++ priv->timer_counter = 0; ++ priv->flags = flags; ++ ++ if (flags & GTK_TAP_AND_HOLD_PASS_PRESS) ++ { ++ g_signal_connect( widget, "button-press-event", ++ G_CALLBACK(gtk_widget_tap_and_hold_button_press_with_events), priv ); ++ g_signal_connect( widget, "button-release-event", ++ G_CALLBACK(gtk_widget_tap_and_hold_button_release_with_events), priv ); ++ g_signal_connect( widget, "leave-notify-event", ++ G_CALLBACK(gtk_widget_tap_and_hold_leave_notify_with_events), priv ); ++ } ++ else ++ { ++ g_signal_connect( widget, "button-press-event", ++ G_CALLBACK(gtk_widget_tap_and_hold_button_press), priv ); ++ g_signal_connect( widget, "button-release-event", ++ G_CALLBACK(gtk_widget_tap_and_hold_button_release), priv ); ++ g_signal_connect( widget, "leave-notify-event", ++ G_CALLBACK(gtk_widget_tap_and_hold_leave_notify), priv ); ++ } ++ ++#ifdef TAP_AND_HOLD_ANIMATION ++ priv->anim = NULL; ++ style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), ++ "gtk-tap-and-hold-animation", ++ NULL, G_TYPE_NONE); ++ ++ if( style ) ++ { ++ ++ priv->anim = gdk_pixbuf_animation_new_from_file( ++ (gchar*)style->rc_style->bg_pixmap_name[0], &error ); ++ ++ priv->width = gdk_pixbuf_animation_get_width( priv->anim )/2; ++ priv->height = gdk_pixbuf_animation_get_height( priv->anim )/2; ++ } ++#endif ++} ++ ++static void gtk_widget_real_tap_and_hold(GtkWidget *widget) ++{ ++ GtkWidgetPrivate *priv = GTK_WIDGET_GET_PRIVATE (widget); ++ ++ if (GTK_IS_MENU(priv->menu)) ++ gtk_menu_popup( GTK_MENU(priv->menu), NULL, NULL, ++ (GtkMenuPositionFunc)priv->func, ++ widget, 1, gdk_x11_get_server_time(widget->window) ); ++} ++ ++static gboolean gtk_widget_tap_and_hold_timeout (GtkWidget *widget) ++{ ++ GtkWidgetPrivate *priv= GTK_WIDGET_GET_PRIVATE(widget); ++ gboolean return_value; ++ gint x = 0, y = 0; ++ ++ #ifdef TAP_AND_HOLD_ANIMATION ++ timeout_tap_and_hold_animation( priv ); ++ #endif ++ ++ if( priv->timer_counter ) ++ priv->timer_counter--; ++ else ++ priv->timer_id = 0; ++ ++ gdk_display_get_pointer( gdk_x11_lookup_xdisplay( ++ GDK_WINDOW_XDISPLAY(priv->fake_event->button.window) ), ++ NULL, &x, &y, NULL ); ++ ++ if ((abs(x - priv->x) > GTK_TAP_THRESHOLD) || ++ (abs(y - priv->y) > GTK_TAP_THRESHOLD)) ++ { ++ if (priv->stype != priv->type_on_press) ++ gtk_widget_set_state( widget, priv->stype ); ++ priv->timer_counter = 0; ++ priv->timer_id = 0; ++ priv->x = priv->y = 0; ++ priv->run_press = FALSE; ++ g_signal_emit_by_name (G_OBJECT(widget), "button-press-event", ++ priv->fake_event, &return_value); ++ return FALSE; ++ } ++ if (!priv->timer_id) ++ { ++ if (priv->stype != priv->type_on_press) ++ gtk_widget_set_state( widget, priv->stype ); ++ #ifdef TAP_AND_HOLD_ANIMATION ++ stop_tap_and_hold_animation( priv ); ++ #endif ++ g_signal_emit(widget, widget_signals[TAP_AND_HOLD], 0); ++ priv->x = x; ++ priv->y = y; ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++static gboolean gtk_widget_tap_and_hold_button_press (GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv) ++{ ++ if (!priv->run_press || event->button.button != 1) ++ { ++ priv->run_press = TRUE; ++ return FALSE; ++ } ++ ++ if (event->button.type == GDK_2BUTTON_PRESS) ++ return FALSE; ++ ++ if (priv->fake_event) ++ gdk_event_free (priv->fake_event); ++ priv->fake_event = gdk_event_copy(event); ++ ++ if (!priv->timer_id) ++ { ++ priv->stype = GTK_WIDGET_STATE(widget); ++ if (priv->stype != priv->type_on_press) ++ gtk_widget_set_state( widget, priv->type_on_press ); ++ gdk_display_get_pointer( ++ gdk_x11_lookup_xdisplay( GDK_WINDOW_XDISPLAY(event->button.window) ), ++ NULL, &priv->x, &priv->y, NULL ); ++ priv->timer_counter = GTK_TAP_AND_HOLD_TIMER_COUNTER; ++ ++ #ifdef TAP_AND_HOLD_ANIMATION ++ init_tap_and_hold_animation( priv ); ++ #endif ++ priv->timer_id = g_timeout_add( priv->interval, ++ (GSourceFunc)gtk_widget_tap_and_hold_timeout, widget ); ++ } ++return TRUE; ++} ++ ++static gboolean gtk_widget_tap_and_hold_button_release (GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv) ++{ ++ gboolean return_value; ++ ++ if (!priv->run_press || event->button.button != 1 || !priv->timer_id || ++ event->button.type == GDK_2BUTTON_PRESS) ++ return FALSE; ++ ++ g_source_remove (priv->timer_id); ++ priv->timer_id = 0; ++ priv->x = priv->y = priv->timer_counter = 0; ++ if (priv->stype != priv->type_on_press) ++ gtk_widget_set_state (widget, priv->stype); ++ ++ #ifdef TAP_AND_HOLD_ANIMATION ++ stop_tap_and_hold_animation( priv ); ++ #endif ++ ++ if (priv->flags & GTK_TAP_AND_HOLD_NO_SIGNALS) ++ return FALSE; ++ ++ priv->run_press = FALSE; ++ ++ g_signal_emit_by_name (G_OBJECT(widget), "button-press-event", ++ priv->fake_event, &return_value); ++ ++return FALSE; ++} ++ ++static gboolean gtk_widget_tap_and_hold_leave_notify (GtkWidget *widget, ++ GdkEvent *event, GtkWidgetPrivate *priv) ++{ ++ gboolean return_value; ++ if (!priv->timer_id) ++ return FALSE; ++ ++ g_source_remove (priv->timer_id); ++ priv->timer_id = 0; ++ priv->x = priv->y = priv->timer_counter = 0; ++ if (priv->stype != priv->type_on_press) ++ gtk_widget_set_state (widget, priv->stype); ++ ++ #ifdef TAP_AND_HOLD_ANIMATION ++ stop_tap_and_hold_animation( priv ); ++ #endif ++ priv->run_press = FALSE; ++ g_signal_emit_by_name (G_OBJECT(widget), "button-press-event", ++ priv->fake_event, &return_value); ++ ++return FALSE; ++} ++ ++static gboolean ++gtk_widget_tap_and_hold_timeout_with_events (GtkWidget *widget) ++{ ++ gint x, y; ++ GtkWidgetPrivate *priv= GTK_WIDGET_GET_PRIVATE(widget); ++ ++ g_return_val_if_fail (priv->fake_event, FALSE); ++ ++ #ifdef TAP_AND_HOLD_ANIMATION ++ timeout_tap_and_hold_animation( priv ); ++ #endif ++ ++ gdk_display_get_pointer( gdk_x11_lookup_xdisplay( ++ GDK_WINDOW_XDISPLAY(priv->fake_event->button.window) ), ++ NULL, &x, &y, NULL ); ++ ++ if( priv->timer_counter ) ++ { ++ priv->timer_counter--; ++ if ((abs(x - priv->x) > GTK_TAP_THRESHOLD) || ++ (abs(y - priv->y) > GTK_TAP_THRESHOLD)) ++ { ++ #ifdef TAP_AND_HOLD_ANIMATION ++ stop_tap_and_hold_animation( priv ); ++ #endif ++ tap_and_hold_remove_timer( priv ); ++ } ++ return TRUE; ++ } ++ ++ if (!((abs(x - priv->x) > GTK_TAP_THRESHOLD) || ++ (abs(y - priv->y) > GTK_TAP_THRESHOLD))) ++ { ++ gboolean return_value; ++ priv->fake_event->button.type = GDK_BUTTON_RELEASE; ++ priv->fake_event->button.x = x; ++ priv->fake_event->button.y = y; ++ g_signal_emit_by_name (G_OBJECT(widget), "button-release-event", ++ priv->fake_event, &return_value); ++ #ifdef TAP_AND_HOLD_ANIMATION ++ stop_tap_and_hold_animation( priv ); ++ #endif ++ g_signal_emit(widget, widget_signals[TAP_AND_HOLD], 0); ++ priv->timer_id = 0; ++ priv->x = x; ++ priv->y = y; ++ gdk_event_free(priv->fake_event); ++ priv->fake_event = NULL; ++ } ++ ++ ++ if (priv->timer_id) ++ { ++ g_source_remove (priv->timer_id); ++ priv->timer_id = 0; ++ } ++ ++ return FALSE; ++} ++ ++static gboolean gtk_widget_tap_and_hold_button_press_with_events( ++ GtkWidget *widget, GdkEvent *event, GtkWidgetPrivate *priv) ++{ ++ if( priv->timer_id || event->button.type == GDK_2BUTTON_PRESS) ++ return FALSE; ++ ++ if (priv->fake_event) ++ gdk_event_free (priv->fake_event); ++ priv->fake_event = gdk_event_copy (event); ++ ++ gdk_display_get_pointer( ++ gdk_x11_lookup_xdisplay(GDK_WINDOW_XDISPLAY(event->button.window)), ++ NULL, &priv->x, &priv->y, NULL); ++ #ifdef TAP_AND_HOLD_ANIMATION ++ init_tap_and_hold_animation( priv ); ++ #endif ++ priv->timer_counter = GTK_TAP_AND_HOLD_TIMER_COUNTER; ++ priv->timer_id = g_timeout_add(priv->interval, ++ (GSourceFunc)gtk_widget_tap_and_hold_timeout_with_events, ++ widget); ++ return FALSE; ++} ++ ++static gboolean gtk_widget_tap_and_hold_button_release_with_events( ++ GtkWidget *widget, GdkEvent *event, GtkWidgetPrivate *priv) ++{ ++ tap_and_hold_remove_timer( priv ); ++ return FALSE; ++} ++ ++static gboolean gtk_widget_tap_and_hold_leave_notify_with_events( ++ GtkWidget *widget, GdkEvent *event, GtkWidgetPrivate *priv) ++{ ++ tap_and_hold_remove_timer( priv ); ++ return FALSE; ++} ++ ++/** ++ * gtk_widget_tap_and_hold_menu_position_top: ++ * @menu: a #GtkMenu ++ * @x: x cordinate to be returned ++ * @y: y cordinate to be returned ++ * @push_in: If going off screen, push it pack on the screen ++ * @widget: a #GtkWidget ++ * ++ * Pre-made menu positioning function. ++ * It positiones the @menu over the @widget. ++ * ++ **/ ++void gtk_widget_tap_and_hold_menu_position_top( GtkWidget *menu, ++ gint *x, gint *y, gboolean *push_in, GtkWidget *widget ) ++{ ++ /* ++ * This function positiones the menu above widgets. ++ * This is a modified version of the position function ++ * gtk_combo_box_position_over. ++ */ ++ GtkWidget *topw; ++ GtkRequisition requisition; ++ gint screen_width = 0; ++ gint menu_xpos = 0; ++ gint menu_ypos = 0; ++ gint w_xpos = 0, w_ypos = 0; ++ ++ gtk_widget_size_request( menu, &requisition ); ++ ++ topw = gtk_widget_get_toplevel(widget); ++ gdk_window_get_origin( topw->window, &w_xpos, &w_ypos ); ++ ++ menu_xpos += widget->allocation.x + w_xpos; ++ menu_ypos += widget->allocation.y + w_ypos - requisition.height; ++ ++ if( gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL ) ++ menu_xpos = menu_xpos + widget->allocation.width - requisition.width; ++ ++ screen_width = gdk_screen_get_width( gtk_widget_get_screen(widget) ); ++ ++ if( menu_xpos < w_xpos ) ++ menu_xpos = w_xpos; ++ else if( (menu_xpos + requisition.width) > screen_width ) ++ menu_xpos -= ( (menu_xpos + requisition.width) - screen_width ); ++ if( menu_ypos < w_ypos ) ++ menu_ypos = w_ypos; ++ ++ *x = menu_xpos; ++ *y = menu_ypos; ++ *push_in = TRUE; ++} |