From 2ccf29f6b3c68e910912badea97329c2c4602cb7 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 5 Jan 2012 00:35:04 +0100 Subject: [PATCH] button: Handle touch events Touch events don't generate crossing events themselves, so do not rely on these to determine whether the button release happened within the event window. --- gtk/gtkbutton.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c index f28a79ceb4..6a6d7c3147 100644 --- a/gtk/gtkbutton.c +++ b/gtk/gtkbutton.c @@ -122,6 +122,8 @@ static gint gtk_button_button_press (GtkWidget * widget, GdkEventButton * event); static gint gtk_button_button_release (GtkWidget * widget, GdkEventButton * event); +static gboolean gtk_button_touch (GtkWidget *widget, + GdkEventTouch *event); static gint gtk_button_grab_broken (GtkWidget * widget, GdkEventGrabBroken * event); static gint gtk_button_key_release (GtkWidget * widget, GdkEventKey * event); @@ -207,6 +209,7 @@ gtk_button_class_init (GtkButtonClass *klass) widget_class->draw = gtk_button_draw; widget_class->button_press_event = gtk_button_button_press; widget_class->button_release_event = gtk_button_button_release; + widget_class->touch_event = gtk_button_touch; widget_class->grab_broken_event = gtk_button_grab_broken; widget_class->key_release_event = gtk_button_key_release; widget_class->enter_notify_event = gtk_button_enter_notify; @@ -1429,9 +1432,10 @@ gtk_button_realize (GtkWidget *widget) attributes.wclass = GDK_INPUT_ONLY; attributes.event_mask = gtk_widget_get_events (widget); attributes.event_mask |= (GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | - GDK_LEAVE_NOTIFY_MASK); + GDK_BUTTON_RELEASE_MASK | + GDK_TOUCH_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK); attributes_mask = GDK_WA_X | GDK_WA_Y; @@ -1841,6 +1845,28 @@ gtk_button_button_release (GtkWidget *widget, return TRUE; } +static gboolean +gtk_button_touch (GtkWidget *widget, + GdkEventTouch *event) +{ + GtkButton *button = GTK_BUTTON (widget); + GtkButtonPrivate *priv = button->priv; + + if (event->type == GDK_TOUCH_BEGIN) + { + if (priv->focus_on_click && !gtk_widget_has_focus (widget)) + gtk_widget_grab_focus (widget); + + g_signal_emit (button, button_signals[PRESSED], 0); + } + else if (event->type == GDK_TOUCH_END) + { + g_signal_emit (button, button_signals[RELEASED], 0); + } + + return TRUE; +} + static gboolean gtk_button_grab_broken (GtkWidget *widget, GdkEventGrabBroken *event) @@ -1930,6 +1956,40 @@ gtk_real_button_pressed (GtkButton *button) gtk_button_update_state (button); } +static gboolean +touch_release_in_button (GtkButton *button) +{ + GtkButtonPrivate *priv; + gint width, height; + GdkEvent *event; + gdouble x, y; + + priv = button->priv; + event = gtk_get_current_event (); + + if (!event) + return FALSE; + + if (event->type != GDK_TOUCH_END || + event->touch.window != priv->event_window) + { + gdk_event_free (event); + return FALSE; + } + + gdk_event_get_coords (event, &x, &y); + width = gdk_window_get_width (priv->event_window); + height = gdk_window_get_height (priv->event_window); + + gdk_event_free (event); + + if (x >= 0 && x <= width && + y >= 0 && y <= height) + return TRUE; + + return FALSE; +} + static void gtk_real_button_released (GtkButton *button) { @@ -1942,7 +2002,8 @@ gtk_real_button_released (GtkButton *button) if (priv->activate_timeout) return; - if (priv->in_button) + if (priv->in_button || + touch_release_in_button (button)) gtk_button_clicked (button); gtk_button_update_state (button);