[gtk+/touchscreens: 19/65] gtk: Clean up press-and-hold code
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/touchscreens: 19/65] gtk: Clean up press-and-hold code
- Date: Tue, 13 Dec 2011 18:57:41 +0000 (UTC)
commit 78a2a7a2cd5c0229b29806e8e5b2aa97566aa42e
Author: Carlos Garnacho <carlosg gnome org>
Date: Tue Nov 1 12:19:19 2011 +0100
gtk: Clean up press-and-hold code
The press and hold animation now fully relies on style context
transitions, finishing the p-a-h operation right after it
finishes. There's also no need to connect to ::drag-begin as
::grab-notify will also tell when a grab begins.
gtk/gtkwidget.c | 223 ++++++++++++++++++++++++++-----------------------------
1 files changed, 104 insertions(+), 119 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 4d2aba8..9071596 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -539,17 +539,16 @@ struct _GtkStateData
typedef struct
{
- /* timeout */
- guint press_and_hold_id;
+ /* The widget */
+ GtkWidget *widget;
/* animation */
GtkWidget *popup;
- guint animation_id;
+ guint delay_animation_id;
/* signal handlers */
guint motion_id;
guint button_release_id;
- guint drag_begin_id;
guint grab_notify_id;
gint start_x;
@@ -667,12 +666,8 @@ static gboolean gtk_widget_real_can_activate_accel (GtkWidget *widg
static void gtk_widget_real_set_has_tooltip (GtkWidget *widget,
gboolean has_tooltip,
gboolean force);
-static gboolean gtk_widget_press_and_hold_cancel (GtkWidget *widget,
- gpointer unused,
- PressAndHoldData *data);
-static gboolean gtk_widget_press_and_hold_button_press_event (GtkWidget *widget,
- GdkEventButton *button,
- gpointer user_data);
+static gboolean gtk_widget_press_and_hold_start (GtkWidget *widget,
+ GdkEventButton *button);
static void gtk_widget_buildable_interface_init (GtkBuildableIface *iface);
static void gtk_widget_buildable_set_name (GtkBuildable *buildable,
const gchar *name);
@@ -6003,9 +5998,12 @@ _gtk_widget_captured_event (GtkWidget *widget,
g_object_ref (widget);
- /* Make sure we always handle press and hold */
if (event->type == GDK_BUTTON_PRESS)
- gtk_widget_press_and_hold_button_press_event (widget, (GdkEventButton *)event, NULL);
+ {
+ /* Handle press and hold */
+ gtk_widget_press_and_hold_start (widget,
+ (GdkEventButton *)event);
+ }
g_signal_emit (widget, widget_signals[CAPTURED_EVENT], 0, event, &return_val);
return_val |= !WIDGET_REALIZED_FOR_EVENT (widget, event);
@@ -6875,11 +6873,17 @@ press_and_hold_data_free (PressAndHoldData *data)
if (data->popup)
gtk_widget_destroy (data->popup);
- if (data->press_and_hold_id)
- g_source_remove (data->press_and_hold_id);
+ if (data->delay_animation_id)
+ g_source_remove (data->delay_animation_id);
+
+ if (data->motion_id)
+ g_signal_handler_disconnect (data->widget, data->motion_id);
+
+ if (data->button_release_id)
+ g_signal_handler_disconnect (data->widget, data->button_release_id);
- if (data->animation_id)
- g_source_remove (data->animation_id);
+ if (data->grab_notify_id)
+ g_signal_handler_disconnect (data->widget, data->grab_notify_id);
g_slice_free (PressAndHoldData, data);
}
@@ -6903,39 +6907,31 @@ gtk_widget_get_press_and_hold_data (GtkWidget *widget)
if (!data)
{
data = g_slice_new0 (PressAndHoldData);
+ data->widget = widget;
gtk_widget_set_press_and_hold_data (widget, data);
}
return data;
}
-static inline void
-gtk_widget_press_and_hold_finish (GtkWidget *widget,
- PressAndHoldData *data)
+static gboolean
+gtk_widget_press_and_hold_cancel (GtkWidget *widget)
{
- if (data->popup)
- gtk_widget_destroy (data->popup);
- data->popup = NULL;
-
- if (data->motion_id)
- g_signal_handler_disconnect (widget, data->motion_id);
- data->motion_id = 0;
+ PressAndHoldData *data;
+ gboolean return_value;
- if (data->button_release_id)
- g_signal_handler_disconnect (widget, data->button_release_id);
- data->button_release_id = 0;
+ data = gtk_widget_peek_press_and_hold_data (widget);
+ g_assert (data != NULL);
- if (data->drag_begin_id)
- g_signal_handler_disconnect (widget, data->drag_begin_id);
- data->drag_begin_id = 0;
+ g_signal_emit (widget, widget_signals[PRESS_AND_HOLD],
+ 0,
+ GTK_PRESS_AND_HOLD_CANCEL,
+ -1, -1,
+ &return_value);
- if (data->press_and_hold_id)
- g_source_remove (data->press_and_hold_id);
- data->press_and_hold_id = 0;
+ gtk_widget_set_press_and_hold_data (widget, NULL);
- if (data->animation_id)
- g_source_remove (data->animation_id);
- data->animation_id = 0;
+ return FALSE;
}
static gboolean
@@ -6946,7 +6942,8 @@ gtk_widget_press_and_hold_button_release (GtkWidget *widget,
if (_event->type != GDK_BUTTON_RELEASE)
return FALSE;
- gtk_widget_press_and_hold_cancel (widget, NULL, data);
+ if (data->device == gdk_event_get_device (_event))
+ gtk_widget_press_and_hold_cancel (widget);
return FALSE;
}
@@ -6958,7 +6955,7 @@ gtk_widget_press_and_hold_grab_notify (GtkWidget *widget,
{
if (data->device &&
gtk_widget_device_is_shadowed (widget, data->device))
- gtk_widget_press_and_hold_cancel (widget, NULL, data);
+ gtk_widget_press_and_hold_cancel (widget);
}
static gboolean
@@ -6967,18 +6964,16 @@ gtk_widget_press_and_hold_motion_notify (GtkWidget *widget,
PressAndHoldData *data)
{
GdkEventMotion *event;
+ GdkDevice *device;
if (_event->type != GDK_MOTION_NOTIFY)
return FALSE;
event = (GdkEventMotion *)_event;
+ device = gdk_event_get_device (_event);
- if (!data->press_and_hold_id)
- {
- gtk_widget_press_and_hold_finish (widget, data);
-
- return FALSE;
- }
+ if (data->device != device)
+ return FALSE;
_gtk_widget_find_at_coords (event->window, event->x, event->y,
&data->current_x, &data->current_y);
@@ -6987,22 +6982,19 @@ gtk_widget_press_and_hold_motion_notify (GtkWidget *widget,
if (gtk_drag_check_threshold (widget, data->start_x, data->start_y,
data->current_x, data->current_y))
{
- gtk_widget_press_and_hold_cancel (widget, NULL, data);
+ gtk_widget_press_and_hold_cancel (widget);
return FALSE;
}
if (data->popup)
{
- gint x, y;
guint cursor_size;
- gdk_window_get_device_position (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
- data->device, &x, &y, NULL);
cursor_size = gdk_display_get_default_cursor_size (gtk_widget_get_display (widget));
gtk_window_move (GTK_WINDOW (data->popup),
- x - cursor_size / 2,
- y - cursor_size / 2);
+ event->x_root - cursor_size / 2,
+ event->y_root - cursor_size / 2);
}
return FALSE;
@@ -7013,30 +7005,36 @@ gtk_widget_press_and_hold_timeout (gpointer user_data)
{
gboolean return_value;
GtkWidget *widget = GTK_WIDGET (user_data);
- PressAndHoldData *data = gtk_widget_peek_press_and_hold_data (widget);
+ PressAndHoldData *data;
- /* Done, clean up and emit the trigger signal */
- gtk_widget_press_and_hold_finish (widget, data);
- _gtk_widget_grab_notify (widget, FALSE);
+ data = gtk_widget_peek_press_and_hold_data (widget);
+ g_assert (data != NULL);
+ /* Done, clean up and emit the trigger signal */
g_signal_emit (widget, widget_signals[PRESS_AND_HOLD],
0,
GTK_PRESS_AND_HOLD_TRIGGER,
data->current_x, data->current_y,
&return_value);
+ gtk_widget_set_press_and_hold_data (widget, NULL);
+
return FALSE;
}
static gboolean
-press_and_hold_animation_draw (GtkWidget *widget,
- cairo_t *cr,
- PressAndHoldData *data)
+press_and_hold_animation_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer user_data)
{
+ PressAndHoldData *data;
GtkStyleContext *context;
GtkStateFlags state;
gint width, height;
+ data = gtk_widget_peek_press_and_hold_data (GTK_WIDGET (user_data));
+ g_assert (data != NULL);
+
width = gtk_widget_get_allocated_width (widget);
height = gtk_widget_get_allocated_height (widget);
@@ -7044,6 +7042,17 @@ press_and_hold_animation_draw (GtkWidget *widget,
state = gtk_widget_get_state_flags (widget);
gtk_style_context_set_state (context, state);
+ if (!gtk_style_context_state_is_running (context, GTK_STATE_FLAG_ACTIVE, NULL))
+ {
+ /* The animation just finished, so hide the widget
+ * and finish the press and hold operation.
+ */
+ gdk_threads_add_idle (gtk_widget_press_and_hold_timeout,
+ user_data);
+ gtk_widget_hide (widget);
+ return FALSE;
+ }
+
if (!gtk_widget_is_composited (widget))
{
cairo_t *mask_cr;
@@ -7062,9 +7071,13 @@ press_and_hold_animation_draw (GtkWidget *widget,
cairo_surface_destroy (mask);
}
-
- cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
- cairo_paint (cr);
+ else
+ {
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ }
gtk_render_activity (context, cr, 0, 0, width, height);
@@ -7075,22 +7088,23 @@ static gboolean
gtk_widget_press_and_hold_begin_animation_timeout (gpointer user_data)
{
GtkWidget *widget = GTK_WIDGET (user_data);
- PressAndHoldData *data = gtk_widget_peek_press_and_hold_data (widget);
+ PressAndHoldData *data;
gint x, y;
guint cursor_size;
- if (data->popup)
- {
- gtk_widget_set_state_flags (GTK_WIDGET (data->popup),
- GTK_STATE_FLAG_ACTIVE, FALSE);
- gdk_window_get_device_position (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
- data->device, &x, &y, NULL);
- cursor_size = gdk_display_get_default_cursor_size (gtk_widget_get_display (widget));
- gtk_window_move (GTK_WINDOW (data->popup),
- x - cursor_size / 2,
- y - cursor_size / 2);
- gtk_widget_show (data->popup);
- }
+ data = gtk_widget_peek_press_and_hold_data (widget);
+ g_assert (data != NULL);
+
+ gdk_window_get_device_position (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+ data->device, &x, &y, NULL);
+ cursor_size = gdk_display_get_default_cursor_size (gtk_widget_get_display (widget));
+ gtk_window_move (GTK_WINDOW (data->popup),
+ x - cursor_size / 2,
+ y - cursor_size / 2);
+ gtk_widget_show (data->popup);
+
+ gtk_widget_set_state_flags (GTK_WIDGET (data->popup),
+ GTK_STATE_FLAG_ACTIVE, FALSE);
return FALSE;
}
@@ -7112,38 +7126,18 @@ gtk_widget_press_and_hold_query (GtkWidget *widget,
}
static gboolean
-gtk_widget_press_and_hold_cancel (GtkWidget *widget,
- gpointer unused,
- PressAndHoldData *data)
+gtk_widget_press_and_hold_start (GtkWidget *widget,
+ GdkEventButton *event)
{
- gboolean return_value;
+ PressAndHoldData *data = gtk_widget_peek_press_and_hold_data (widget);
- if (!data->press_and_hold_id)
+ /* Press and hold already in process? */
+ if (data)
return FALSE;
- gtk_widget_press_and_hold_finish (widget, data);
-
- g_signal_emit (widget, widget_signals[PRESS_AND_HOLD],
- 0,
- GTK_PRESS_AND_HOLD_CANCEL,
- -1, -1,
- &return_value);
-
- return FALSE;
-}
+ data = gtk_widget_get_press_and_hold_data (widget);
-static gboolean
-gtk_widget_press_and_hold_button_press_event (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data)
-{
- PressAndHoldData *data = gtk_widget_get_press_and_hold_data (widget);
-
- if (!data)
- return FALSE;
-
- if (gtk_widget_press_and_hold_query (widget, event->x, event->y)
- && !data->press_and_hold_id)
+ if (gtk_widget_press_and_hold_query (widget, event->x, event->y))
{
gint timeout, begin_ani_timeout;
GdkScreen *screen;
@@ -7178,7 +7172,7 @@ gtk_widget_press_and_hold_button_press_event (GtkWidget *widget,
g_signal_connect (data->popup, "draw",
G_CALLBACK (press_and_hold_animation_draw),
- data);
+ widget);
cursor_size = gdk_display_get_default_cursor_size (gtk_widget_get_display (widget));
gtk_window_resize (GTK_WINDOW (data->popup), cursor_size, cursor_size);
@@ -7188,33 +7182,24 @@ gtk_widget_press_and_hold_button_press_event (GtkWidget *widget,
cairo_region_destroy (region);
/* delay loading the animation by the double click timeout */
- data->animation_id =
+ data->delay_animation_id =
gdk_threads_add_timeout (begin_ani_timeout,
gtk_widget_press_and_hold_begin_animation_timeout,
widget);
data->motion_id =
- g_signal_connect (widget, "captured-event",
- G_CALLBACK (gtk_widget_press_and_hold_motion_notify),
- data);
+ g_signal_connect (widget, "captured-event",
+ G_CALLBACK (gtk_widget_press_and_hold_motion_notify),
+ data);
data->button_release_id =
- g_signal_connect (widget, "captured-event",
- G_CALLBACK (gtk_widget_press_and_hold_button_release),
- data);
- data->drag_begin_id =
- g_signal_connect (widget, "drag-begin",
- G_CALLBACK (gtk_widget_press_and_hold_cancel),
- data);
-
+ g_signal_connect (widget, "captured-event",
+ G_CALLBACK (gtk_widget_press_and_hold_button_release),
+ data);
data->grab_notify_id =
g_signal_connect (widget, "grab-notify",
G_CALLBACK (gtk_widget_press_and_hold_grab_notify),
data);
- data->press_and_hold_id =
- gdk_threads_add_timeout (timeout,
- gtk_widget_press_and_hold_timeout,
- widget);
data->device = gdk_event_get_device ((GdkEvent *) event);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]