[gtk+/gestures] textview: Use GtkGestureMultiPress for click handling
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gestures] textview: Use GtkGestureMultiPress for click handling
- Date: Thu, 8 May 2014 14:32:27 +0000 (UTC)
commit d86cfdc5df7234c0dd5bc099c7cbe21c27336f05
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed May 7 13:15:30 2014 +0200
textview: Use GtkGestureMultiPress for click handling
The button press handler is no longer necessary, and most of its
code has been shuffled into the GtkGestureMultiPress::pressed
handler.
gtk/gtktextview.c | 252 +++++++++++++++++++++++++++++------------------------
1 files changed, 138 insertions(+), 114 deletions(-)
---
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index ffc1f50..08d8fa4 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -208,6 +208,8 @@ struct _GtkTextViewPrivate
GtkPixelCache *pixel_cache;
+ GtkGesture *multipress_gesture;
+
/* Default style settings */
gint pixels_above_lines;
gint pixels_below_lines;
@@ -259,6 +261,13 @@ struct _GtkTextPendingScroll
gdouble yalign;
};
+typedef enum
+{
+ SELECT_CHARACTERS,
+ SELECT_WORDS,
+ SELECT_LINES
+} SelectionGranularity;
+
enum
{
POPULATE_POPUP,
@@ -338,14 +347,18 @@ static void gtk_text_view_grab_notify (GtkWidget *widget,
static void gtk_text_view_state_flags_changed (GtkWidget *widget,
GtkStateFlags previous_state);
+static void gtk_text_view_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GtkTextView *text_view);
+
static gint gtk_text_view_event (GtkWidget *widget,
GdkEvent *event);
static gint gtk_text_view_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static gint gtk_text_view_key_release_event (GtkWidget *widget,
GdkEventKey *event);
-static gint gtk_text_view_button_press_event (GtkWidget *widget,
- GdkEventButton *event);
static gint gtk_text_view_button_release_event (GtkWidget *widget,
GdkEventButton *event);
static gint gtk_text_view_focus_in_event (GtkWidget *widget,
@@ -440,9 +453,10 @@ static void gtk_text_view_set_attributes_from_style (GtkTextView *tex
static void gtk_text_view_ensure_layout (GtkTextView *text_view);
static void gtk_text_view_destroy_layout (GtkTextView *text_view);
static void gtk_text_view_check_keymap_direction (GtkTextView *text_view);
-static void gtk_text_view_start_selection_drag (GtkTextView *text_view,
- const GtkTextIter *iter,
- GdkEventButton *event);
+static void gtk_text_view_start_selection_drag (GtkTextView *text_view,
+ const GtkTextIter *iter,
+ SelectionGranularity granularity,
+ const GdkEvent *event);
static gboolean gtk_text_view_end_selection_drag (GtkTextView *text_view);
static void gtk_text_view_start_selection_dnd (GtkTextView *text_view,
const GtkTextIter *iter,
@@ -489,7 +503,7 @@ static void gtk_text_view_set_virtual_cursor_pos (GtkTextView *text_view,
gint y);
static void gtk_text_view_do_popup (GtkTextView *text_view,
- GdkEventButton *event);
+ const GdkEvent *event);
static void cancel_pending_scroll (GtkTextView *text_view);
static void gtk_text_view_queue_scroll (GtkTextView *text_view,
@@ -665,7 +679,6 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
widget_class->event = gtk_text_view_event;
widget_class->key_press_event = gtk_text_view_key_press_event;
widget_class->key_release_event = gtk_text_view_key_release_event;
- widget_class->button_press_event = gtk_text_view_button_press_event;
widget_class->button_release_event = gtk_text_view_button_release_event;
widget_class->focus_in_event = gtk_text_view_focus_in_event;
widget_class->focus_out_event = gtk_text_view_focus_out_event;
@@ -1543,6 +1556,14 @@ gtk_text_view_init (GtkTextView *text_view)
/* We handle all our own redrawing */
gtk_widget_set_redraw_on_allocate (widget, FALSE);
+
+ priv->multipress_gesture = gtk_gesture_multi_press_new (widget);
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->multipress_gesture),
+ FALSE);
+ gtk_gesture_attach (priv->multipress_gesture, GTK_PHASE_BUBBLE);
+ g_signal_connect (priv->multipress_gesture, "pressed",
+ G_CALLBACK (gtk_text_view_multipress_gesture_pressed),
+ widget);
}
static void
@@ -3231,6 +3252,9 @@ gtk_text_view_finalize (GObject *object)
cancel_pending_scroll (text_view);
+ gtk_gesture_detach (priv->multipress_gesture);
+ g_object_unref (priv->multipress_gesture);
+
if (priv->tabs)
pango_tab_array_free (priv->tabs);
@@ -5028,26 +5052,37 @@ gtk_text_view_key_release_event (GtkWidget *widget, GdkEventKey *event)
return GTK_WIDGET_CLASS (gtk_text_view_parent_class)->key_release_event (widget, event);
}
-static gint
-gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
+static void
+gtk_text_view_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ GtkTextView *text_view)
{
- GtkTextView *text_view;
+ GdkEventSequence *sequence;
GtkTextViewPrivate *priv;
- GdkDevice *device;
+ const GdkEvent *event;
gboolean is_touchscreen;
+ GdkDevice *device;
+ GtkTextIter iter;
+ guint button;
- text_view = GTK_TEXT_VIEW (widget);
priv = text_view->priv;
+ sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+ event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
- gtk_widget_grab_focus (widget);
+ gtk_widget_grab_focus (GTK_WIDGET (text_view));
- if (event->window != priv->text_window->bin_window)
+ if (gdk_event_get_window (event) != priv->text_window->bin_window)
{
/* Remove selection if any. */
gtk_text_view_unselect (text_view);
- return FALSE;
+ return;
}
+ gtk_gesture_set_sequence_state (GTK_GESTURE (gesture), sequence,
+ GTK_EVENT_SEQUENCE_CLAIMED);
gtk_text_view_reset_blink_time (text_view);
gtk_text_view_selection_bubble_popup_unset (text_view);
@@ -5063,98 +5098,97 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
is_touchscreen = test_touchscreen ||
gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN;
- if (event->type == GDK_BUTTON_PRESS)
- {
- gtk_text_view_reset_im_context (text_view);
+ if (n_press == 1)
+ gtk_text_view_reset_im_context (text_view);
- if (gdk_event_triggers_context_menu ((GdkEvent *) event))
- {
- gtk_text_view_do_popup (text_view, event);
- return TRUE;
- }
- else if (event->button == GDK_BUTTON_PRIMARY)
- {
- /* If we're in the selection, start a drag copy/move of the
- * selection; otherwise, start creating a new selection.
- */
- GtkTextIter iter;
- GtkTextIter start, end;
+ if (n_press == 1 &&
+ gdk_event_triggers_context_menu (event))
+ {
+ gtk_text_view_do_popup (text_view, event);
+ }
+ else if (button == GDK_BUTTON_MIDDLE &&
+ get_middle_click_paste (text_view))
+ {
+ /* We do not want to scroll back to the insert iter when we paste
+ with the middle button */
+ priv->scroll_after_paste = FALSE;
- gtk_text_layout_get_iter_at_pixel (priv->layout,
- &iter,
- event->x + priv->xoffset,
- event->y + priv->yoffset);
-
- if (gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
- &start, &end) &&
- gtk_text_iter_in_range (&iter, &start, &end) &&
- !(event->state &
- gtk_widget_get_modifier_mask (widget,
- GDK_MODIFIER_INTENT_EXTEND_SELECTION)))
- {
- priv->grab_device = event->device;
- priv->drag_start_x = event->x;
- priv->drag_start_y = event->y;
- priv->pending_place_cursor_button = event->button;
- }
- else
- {
- gtk_text_view_start_selection_drag (text_view, &iter, event);
+ gtk_text_layout_get_iter_at_pixel (priv->layout,
+ &iter,
+ x + priv->xoffset,
+ y + priv->yoffset);
- if (is_touchscreen)
- {
- _gtk_text_view_ensure_text_handles (text_view);
- gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_CURSOR);
- }
- }
+ gtk_text_buffer_paste_clipboard (get_buffer (text_view),
+ gtk_widget_get_clipboard (GTK_WIDGET (text_view),
+ GDK_SELECTION_PRIMARY),
+ &iter,
+ priv->editable);
+ }
+ else if (button == GDK_BUTTON_PRIMARY)
+ {
+ GtkTextHandleMode handle_mode = GTK_TEXT_HANDLE_MODE_NONE;
- return TRUE;
- }
- else if (event->button == GDK_BUTTON_MIDDLE &&
- get_middle_click_paste (text_view))
+ switch (n_press)
{
- GtkTextIter iter;
-
- /* We do not want to scroll back to the insert iter when we paste
- with the middle button */
- priv->scroll_after_paste = FALSE;
+ case 1:
+ {
+ /* If we're in the selection, start a drag copy/move of the
+ * selection; otherwise, start creating a new selection.
+ */
+ GtkTextIter start, end;
+
+ handle_mode = GTK_TEXT_HANDLE_MODE_CURSOR;
+ gtk_text_layout_get_iter_at_pixel (priv->layout,
+ &iter,
+ x + priv->xoffset,
+ y + priv->yoffset);
+
+ if (gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
+ &start, &end) &&
+ gtk_text_iter_in_range (&iter, &start, &end) &&
+ !(event->button.state &
+ gtk_widget_get_modifier_mask (GTK_WIDGET (text_view),
+ GDK_MODIFIER_INTENT_EXTEND_SELECTION)))
+ {
+ priv->grab_device = gdk_event_get_device (event);
+ priv->drag_start_x = x;
+ priv->drag_start_y = y;
+ priv->pending_place_cursor_button = button;
+ }
+ else
+ {
+ gtk_text_view_start_selection_drag (text_view, &iter,
+ SELECT_CHARACTERS, event);
+ }
+ break;
+ }
+ case 2:
+ case 3:
+ handle_mode = GTK_TEXT_HANDLE_MODE_SELECTION;
+ gtk_text_view_end_selection_drag (text_view);
gtk_text_layout_get_iter_at_pixel (priv->layout,
&iter,
- event->x + priv->xoffset,
- event->y + priv->yoffset);
+ x + priv->xoffset,
+ y + priv->yoffset);
- gtk_text_buffer_paste_clipboard (get_buffer (text_view),
- gtk_widget_get_clipboard (widget, GDK_SELECTION_PRIMARY),
- &iter,
- priv->editable);
- return TRUE;
+ gtk_text_view_start_selection_drag (text_view, &iter,
+ n_press == 2 ? SELECT_WORDS : SELECT_LINES,
+ event);
+ break;
+ default:
+ break;
}
- }
- else if ((event->type == GDK_2BUTTON_PRESS ||
- event->type == GDK_3BUTTON_PRESS) &&
- event->button == GDK_BUTTON_PRIMARY)
- {
- GtkTextIter iter;
-
- gtk_text_view_end_selection_drag (text_view);
-
- gtk_text_layout_get_iter_at_pixel (priv->layout,
- &iter,
- event->x + priv->xoffset,
- event->y + priv->yoffset);
-
- gtk_text_view_start_selection_drag (text_view, &iter, event);
if (is_touchscreen)
{
_gtk_text_view_ensure_text_handles (text_view);
- gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_SELECTION);
+ gtk_text_view_update_handles (text_view, handle_mode);
}
- return TRUE;
}
- return FALSE;
+ if (n_press >= 3)
+ gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture));
}
static gint
@@ -6904,13 +6938,6 @@ drag_scan_timeout (gpointer data)
return TRUE;
}
-typedef enum
-{
- SELECT_CHARACTERS,
- SELECT_WORDS,
- SELECT_LINES
-} SelectionGranularity;
-
/*
* Move @start and @end to the boundaries of the selection unit (indicated by
* @granularity) which contained @start initially.
@@ -7080,30 +7107,26 @@ selection_motion_event_handler (GtkTextView *text_view,
}
static void
-gtk_text_view_start_selection_drag (GtkTextView *text_view,
- const GtkTextIter *iter,
- GdkEventButton *button)
+gtk_text_view_start_selection_drag (GtkTextView *text_view,
+ const GtkTextIter *iter,
+ SelectionGranularity granularity,
+ const GdkEvent *event)
{
GtkTextViewPrivate *priv;
GtkTextIter cursor, ins, bound;
GtkTextIter orig_start, orig_end;
GtkTextBuffer *buffer;
SelectionData *data;
+ GdkModifierType state;
if (text_view->priv->selection_drag_handler != 0)
return;
priv = text_view->priv;
data = g_new0 (SelectionData, 1);
+ data->granularity = granularity;
- if (button->type == GDK_2BUTTON_PRESS)
- data->granularity = SELECT_WORDS;
- else if (button->type == GDK_3BUTTON_PRESS)
- data->granularity = SELECT_LINES;
- else
- data->granularity = SELECT_CHARACTERS;
-
- priv->grab_device = button->device;
+ priv->grab_device = gdk_event_get_device (event);
buffer = get_buffer (text_view);
cursor = *iter;
@@ -7112,8 +7135,9 @@ gtk_text_view_start_selection_drag (GtkTextView *text_view,
extend_selection (text_view, data->granularity, &ins, &bound);
orig_start = ins;
orig_end = bound;
+ gdk_event_get_state (event, &state);
- if (button->state &
+ if (state &
gtk_widget_get_modifier_mask (GTK_WIDGET (text_view),
GDK_MODIFIER_INTENT_EXTEND_SELECTION))
{
@@ -8788,7 +8812,7 @@ popup_position_func (GtkMenu *menu,
typedef struct
{
GtkTextView *text_view;
- gint button;
+ guint button;
guint time;
GdkDevice *device;
} PopupInfo;
@@ -8910,7 +8934,7 @@ popup_targets_received (GtkClipboard *clipboard,
static void
gtk_text_view_do_popup (GtkTextView *text_view,
- GdkEventButton *event)
+ const GdkEvent *event)
{
PopupInfo *info = g_new (PopupInfo, 1);
@@ -8922,9 +8946,9 @@ gtk_text_view_do_popup (GtkTextView *text_view,
if (event)
{
- info->button = event->button;
- info->time = event->time;
- info->device = event->device;
+ gdk_event_get_button (event, &info->button);
+ info->time = gdk_event_get_time (event);
+ info->device = gdk_event_get_device (event);
}
else
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]