forked from AuroraMiddleware/gtk
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.
This commit is contained in:
parent
fe9685bca1
commit
a4da4f8dfa
@ -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,7 +453,8 @@ static void gtk_text_view_destroy_layout (GtkTextView *text_v
|
||||
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);
|
||||
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,
|
||||
@ -487,7 +501,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,
|
||||
@ -663,7 +677,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);
|
||||
|
||||
@ -5001,26 +5025,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);
|
||||
|
||||
@ -5036,98 +5071,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)
|
||||
{
|
||||
if (n_press == 1)
|
||||
gtk_text_view_reset_im_context (text_view);
|
||||
|
||||
if (gdk_event_triggers_context_menu ((GdkEvent *) event))
|
||||
if (n_press == 1 &&
|
||||
gdk_event_triggers_context_menu (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;
|
||||
|
||||
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);
|
||||
|
||||
if (is_touchscreen)
|
||||
{
|
||||
_gtk_text_view_ensure_text_handles (text_view);
|
||||
gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_CURSOR);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->button == GDK_BUTTON_MIDDLE &&
|
||||
else if (button == GDK_BUTTON_MIDDLE &&
|
||||
get_middle_click_paste (text_view))
|
||||
{
|
||||
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;
|
||||
|
||||
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),
|
||||
gtk_widget_get_clipboard (GTK_WIDGET (text_view),
|
||||
GDK_SELECTION_PRIMARY),
|
||||
&iter,
|
||||
priv->editable);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if ((event->type == GDK_2BUTTON_PRESS ||
|
||||
event->type == GDK_3BUTTON_PRESS) &&
|
||||
event->button == GDK_BUTTON_PRIMARY)
|
||||
else if (button == GDK_BUTTON_PRIMARY)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextHandleMode handle_mode = GTK_TEXT_HANDLE_MODE_NONE;
|
||||
|
||||
switch (n_press)
|
||||
{
|
||||
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_view_start_selection_drag (text_view, &iter, event);
|
||||
gtk_text_view_start_selection_drag (text_view, &iter,
|
||||
n_press == 2 ? SELECT_WORDS : SELECT_LINES,
|
||||
event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
@ -6852,13 +6886,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.
|
||||
@ -7030,28 +7057,24 @@ selection_motion_event_handler (GtkTextView *text_view,
|
||||
static void
|
||||
gtk_text_view_start_selection_drag (GtkTextView *text_view,
|
||||
const GtkTextIter *iter,
|
||||
GdkEventButton *button)
|
||||
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;
|
||||
@ -7060,8 +7083,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))
|
||||
{
|
||||
@ -8736,7 +8760,7 @@ popup_position_func (GtkMenu *menu,
|
||||
typedef struct
|
||||
{
|
||||
GtkTextView *text_view;
|
||||
gint button;
|
||||
guint button;
|
||||
guint time;
|
||||
GdkDevice *device;
|
||||
} PopupInfo;
|
||||
@ -8858,7 +8882,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);
|
||||
|
||||
@ -8870,9 +8894,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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user