diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2018-06-06 13:52:08 +0200 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2018-06-21 12:50:57 +0200 |
commit | e08e15ba51c660c53e5658fce9a5d117668af4b4 (patch) | |
tree | dfc116d432ca65324a6edb6c1dd34c12fd5cd408 | |
parent | 7048362e6e0bdda3b7925d3b4eeb01c85870f4bc (diff) | |
download | gtk+-e08e15ba51c660c53e5658fce9a5d117668af4b4.tar.gz |
gtkentry: Use gestures for entry icons
Instead of doing all handling manually in the ::event vfunc,
set up drag/multipress gestures on icon images, and implement
emission of ::icon-press/release and DnD there.
As a side effect, the GdkEvent field in ::icon-press/release
signals has been dropped. Callers that might be interested on it
may still use gtk_get_current_event*().
-rw-r--r-- | demos/gtk-demo/popover.c | 1 | ||||
-rw-r--r-- | demos/gtk-demo/search_entry.c | 3 | ||||
-rw-r--r-- | demos/widget-factory/widget-factory.c | 1 | ||||
-rw-r--r-- | gtk/a11y/gtkentryaccessible.c | 15 | ||||
-rw-r--r-- | gtk/gtkentry.c | 260 | ||||
-rw-r--r-- | gtk/gtkplacesview.c | 1 | ||||
-rw-r--r-- | tests/testentryicons.c | 2 |
7 files changed, 110 insertions, 173 deletions
diff --git a/demos/gtk-demo/popover.c b/demos/gtk-demo/popover.c index f49949adf0..2feb48ac70 100644 --- a/demos/gtk-demo/popover.c +++ b/demos/gtk-demo/popover.c @@ -77,7 +77,6 @@ entry_size_allocate_cb (GtkEntry *entry, static void entry_icon_press_cb (GtkEntry *entry, GtkEntryIconPosition icon_pos, - GdkEvent *event, gpointer user_data) { GtkWidget *popover = user_data; diff --git a/demos/gtk-demo/search_entry.c b/demos/gtk-demo/search_entry.c index 6d6f1ec143..d45afa290b 100644 --- a/demos/gtk-demo/search_entry.c +++ b/demos/gtk-demo/search_entry.c @@ -151,11 +151,10 @@ create_search_menu (GtkWidget *entry) static void icon_press_cb (GtkEntry *entry, gint position, - GdkEventButton *event, gpointer data) { if (position == GTK_ENTRY_ICON_PRIMARY) - gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *) event); + gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL); } static void diff --git a/demos/widget-factory/widget-factory.c b/demos/widget-factory/widget-factory.c index 8b8e852dd5..836eae77af 100644 --- a/demos/widget-factory/widget-factory.c +++ b/demos/widget-factory/widget-factory.c @@ -353,7 +353,6 @@ update_pulse_time (GtkAdjustment *adjustment, GtkWidget *widget) static void on_entry_icon_release (GtkEntry *entry, GtkEntryIconPosition icon_pos, - GdkEvent *event, gpointer user_data) { if (icon_pos != GTK_ENTRY_ICON_SECONDARY) diff --git a/gtk/a11y/gtkentryaccessible.c b/gtk/a11y/gtkentryaccessible.c index de106c3cf0..f8aaabad87 100644 --- a/gtk/a11y/gtkentryaccessible.c +++ b/gtk/a11y/gtkentryaccessible.c @@ -221,8 +221,6 @@ gtk_entry_icon_accessible_do_action (AtkAction *action, GtkEntryIconAccessible *icon = (GtkEntryIconAccessible *)action; GtkWidget *widget; GtkEntry *gtk_entry; - GdkEvent *event; - GdkRectangle icon_area; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (icon->entry)); if (widget == NULL) @@ -240,18 +238,7 @@ gtk_entry_icon_accessible_do_action (AtkAction *action, !gtk_entry_get_icon_activatable (gtk_entry, icon->pos)) return FALSE; - gtk_entry_get_icon_area (gtk_entry, icon->pos, &icon_area); - - event = gdk_event_new (GDK_BUTTON_PRESS); - event->any.surface = g_object_ref (gtk_widget_get_surface (widget)); - event->button.button = 1; - event->any.send_event = TRUE; - event->button.time = GDK_CURRENT_TIME; - event->button.x = icon_area.x; - event->button.y = icon_area.y; - - g_signal_emit_by_name (widget, "icon-press", 0, icon->pos, event); - g_object_unref (event); + g_signal_emit_by_name (widget, "icon-press", 0, icon->pos); return TRUE; } diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 75de722cbb..d9863310ff 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -284,12 +284,9 @@ struct _EntryIconInfo gchar *tooltip; guint nonactivatable : 1; guint in_drag : 1; - guint pressed : 1; GdkDragAction actions; GdkContentFormats *target_list; - GdkEventSequence *current_sequence; - GdkDevice *device; }; struct _GtkEntryPasswordHint @@ -418,8 +415,6 @@ static void gtk_entry_size_allocate (GtkWidget *widget, int baseline); static void gtk_entry_snapshot (GtkWidget *widget, GtkSnapshot *snapshot); -static gboolean gtk_entry_event (GtkWidget *widget, - GdkEvent *event); static void gtk_entry_focus_in (GtkWidget *widget); static void gtk_entry_focus_out (GtkWidget *widget); static void gtk_entry_grab_focus (GtkWidget *widget); @@ -594,8 +589,6 @@ static void gtk_entry_do_popup (GtkEntry *entry, const GdkEvent *event); static gboolean gtk_entry_mnemonic_activate (GtkWidget *widget, gboolean group_cycling); -static void gtk_entry_grab_notify (GtkWidget *widget, - gboolean was_grabbed); static void gtk_entry_check_cursor_blink (GtkEntry *entry); static void gtk_entry_pend_cursor_blink (GtkEntry *entry); static void gtk_entry_reset_blink_time (GtkEntry *entry); @@ -790,7 +783,6 @@ gtk_entry_class_init (GtkEntryClass *class) widget_class->measure = gtk_entry_measure; widget_class->size_allocate = gtk_entry_size_allocate; widget_class->snapshot = gtk_entry_snapshot; - widget_class->event = gtk_entry_event; widget_class->grab_focus = gtk_entry_grab_focus; widget_class->style_updated = gtk_entry_style_updated; widget_class->query_tooltip = gtk_entry_query_tooltip; @@ -800,7 +792,6 @@ gtk_entry_class_init (GtkEntryClass *class) widget_class->state_flags_changed = gtk_entry_state_flags_changed; widget_class->display_changed = gtk_entry_display_changed; widget_class->mnemonic_activate = gtk_entry_mnemonic_activate; - widget_class->grab_notify = gtk_entry_grab_notify; widget_class->drag_drop = gtk_entry_drag_drop; widget_class->drag_motion = gtk_entry_drag_motion; @@ -1651,7 +1642,6 @@ gtk_entry_class_init (GtkEntryClass *class) * GtkEntry::icon-press: * @entry: The entry on which the signal is emitted * @icon_pos: The position of the clicked icon - * @event: (type Gdk.EventButton): the button press event * * The ::icon-press signal is emitted when an activatable icon * is clicked. @@ -1662,16 +1652,14 @@ gtk_entry_class_init (GtkEntryClass *class) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _gtk_marshal_VOID__ENUM_OBJECT, - G_TYPE_NONE, 2, - GTK_TYPE_ENTRY_ICON_POSITION, - GDK_TYPE_EVENT); - + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_ENTRY_ICON_POSITION); + /** * GtkEntry::icon-release: * @entry: The entry on which the signal is emitted * @icon_pos: The position of the clicked icon - * @event: (type Gdk.EventButton): the button release event * * The ::icon-release signal is emitted on the button release from a * mouse click over an activatable icon. @@ -1682,10 +1670,9 @@ gtk_entry_class_init (GtkEntryClass *class) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _gtk_marshal_VOID__ENUM_OBJECT, - G_TYPE_NONE, 2, - GTK_TYPE_ENTRY_ICON_POSITION, - GDK_TYPE_EVENT); + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_ENTRY_ICON_POSITION); /** * GtkEntry::preedit-changed: @@ -2965,6 +2952,91 @@ update_node_ordering (GtkEntry *entry) gtk_css_node_insert_before (parent, gtk_widget_get_css_node (icon_info->widget), NULL); } +static GtkEntryIconPosition +get_icon_position_from_controller (GtkEntry *entry, + GtkEventController *controller) +{ + GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry); + GtkWidget *widget = gtk_event_controller_get_widget (controller); + + if (priv->icons[GTK_ENTRY_ICON_PRIMARY] && + priv->icons[GTK_ENTRY_ICON_PRIMARY]->widget == widget) + return GTK_ENTRY_ICON_PRIMARY; + else if (priv->icons[GTK_ENTRY_ICON_SECONDARY] && + priv->icons[GTK_ENTRY_ICON_SECONDARY]->widget == widget) + return GTK_ENTRY_ICON_SECONDARY; + + g_assert_not_reached (); + return -1; +} + +static void +icon_pressed_cb (GtkGestureMultiPress *gesture, + gint n_press, + gdouble x, + gdouble y, + GtkEntry *entry) +{ + GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry); + GtkEntryIconPosition pos; + EntryIconInfo *icon_info; + + pos = get_icon_position_from_controller (entry, GTK_EVENT_CONTROLLER (gesture)); + icon_info = priv->icons[pos]; + + if (!icon_info->nonactivatable) + g_signal_emit (entry, signals[ICON_PRESS], 0, pos); + + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); +} + +static void +icon_released_cb (GtkGestureMultiPress *gesture, + gint n_press, + gdouble x, + gdouble y, + GtkEntry *entry) +{ + GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry); + GtkEntryIconPosition pos; + EntryIconInfo *icon_info; + + pos = get_icon_position_from_controller (entry, GTK_EVENT_CONTROLLER (gesture)); + icon_info = priv->icons[pos]; + + if (!icon_info->nonactivatable) + g_signal_emit (entry, signals[ICON_RELEASE], 0, pos); +} + +static void +icon_drag_update_cb (GtkGestureDrag *gesture, + gdouble x, + gdouble y, + GtkEntry *entry) +{ + GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry); + gdouble start_x, start_y; + GtkEntryIconPosition pos; + EntryIconInfo *icon_info; + + gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y); + pos = get_icon_position_from_controller (entry, GTK_EVENT_CONTROLLER (gesture)); + icon_info = priv->icons[pos]; + + if (icon_info->target_list != NULL && + gtk_drag_check_threshold (icon_info->widget, + start_x, start_y, + x, y)) + { + icon_info->in_drag = TRUE; + gtk_drag_begin_with_coordinates (GTK_WIDGET (entry), + gtk_gesture_get_device (GTK_GESTURE (gesture)), + icon_info->target_list, + icon_info->actions, + start_x, start_y); + } +} + static EntryIconInfo* construct_icon_info (GtkWidget *widget, GtkEntryIconPosition icon_pos) @@ -2972,6 +3044,7 @@ construct_icon_info (GtkWidget *widget, GtkEntry *entry = GTK_ENTRY (widget); GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry); EntryIconInfo *icon_info; + GtkGesture *drag, *press; g_return_val_if_fail (priv->icons[icon_pos] == NULL, NULL); @@ -2985,6 +3058,20 @@ construct_icon_info (GtkWidget *widget, update_icon_style (widget, icon_pos); update_node_ordering (entry); + press = gtk_gesture_multi_press_new (); + g_signal_connect (press, "pressed", + G_CALLBACK (icon_pressed_cb), entry); + g_signal_connect (press, "released", + G_CALLBACK (icon_released_cb), entry); + gtk_widget_add_controller (icon_info->widget, GTK_EVENT_CONTROLLER (press)); + + drag = gtk_gesture_drag_new (); + g_signal_connect (drag, "drag-update", + G_CALLBACK (icon_drag_update_cb), entry); + gtk_widget_add_controller (icon_info->widget, GTK_EVENT_CONTROLLER (drag)); + + gtk_gesture_group (press, drag); + return icon_info; } @@ -3511,108 +3598,6 @@ gtk_entry_update_handles (GtkEntry *entry, cursor, 0, text_allocation.height); } -static gboolean -gtk_entry_event (GtkWidget *widget, - GdkEvent *event) -{ - GtkEntryPrivate *priv = gtk_entry_get_instance_private (GTK_ENTRY (widget)); - EntryIconInfo *icon_info = NULL; - GdkEventSequence *sequence; - GdkDevice *device; - gdouble x, y; - gint i = 0; - - if (!gdk_event_get_coords (event, &x, &y)) - return GDK_EVENT_PROPAGATE; - - for (i = 0; i < MAX_ICONS; i++) - { - if (priv->icons[i]) - { - int icon_x, icon_y; - gtk_widget_translate_coordinates (widget, priv->icons[i]->widget, - x, y, &icon_x, &icon_y); - if (gtk_widget_contains (priv->icons[i]->widget, icon_x, icon_y)) - { - icon_info = priv->icons[i]; - break; - } - } - } - - if (!icon_info) - return GDK_EVENT_PROPAGATE; - - if (!gtk_widget_get_sensitive (icon_info->widget)) - return GDK_EVENT_STOP; - - sequence = gdk_event_get_event_sequence (event); - device = gdk_event_get_device (event); - - switch ((guint) gdk_event_get_event_type (event)) - { - case GDK_TOUCH_BEGIN: - if (icon_info->current_sequence) - break; - - icon_info->current_sequence = sequence; - /* Fall through */ - case GDK_BUTTON_PRESS: - priv->start_x = x; - priv->start_y = y; - icon_info->pressed = TRUE; - icon_info->device = device; - - if (!icon_info->nonactivatable) { - g_signal_emit (widget, signals[ICON_PRESS], 0, i, event); - } - - break; - case GDK_TOUCH_UPDATE: - if (icon_info->device != device || - icon_info->current_sequence != sequence) - break; - /* Fall through */ - case GDK_MOTION_NOTIFY: - if (icon_info->pressed && - icon_info->target_list != NULL && - gtk_drag_check_threshold (widget, - priv->start_x, - priv->start_y, - x, y)) - { - icon_info->in_drag = TRUE; - gtk_drag_begin_with_coordinates (widget, - device, - icon_info->target_list, - icon_info->actions, - priv->start_x, - priv->start_y); - } - - break; - case GDK_TOUCH_END: - if (icon_info->device != device || - icon_info->current_sequence != sequence) - break; - - icon_info->current_sequence = NULL; - /* Fall through */ - case GDK_BUTTON_RELEASE: - icon_info->pressed = FALSE; - icon_info->device = NULL; - - if (!icon_info->nonactivatable) - g_signal_emit (widget, signals[ICON_RELEASE], 0, i, event); - - break; - default: - return GDK_EVENT_PROPAGATE; - } - - return GDK_EVENT_STOP; -} - static void gesture_get_current_point_in_layout (GtkGestureSingle *gesture, GtkEntry *entry, @@ -7683,8 +7668,6 @@ gtk_entry_set_icon_sensitive (GtkEntry *entry, { gtk_widget_set_sensitive (icon_info->widget, sensitive); - icon_info->pressed = FALSE; - g_object_notify_by_pspec (G_OBJECT (entry), entry_props[icon_pos == GTK_ENTRY_ICON_PRIMARY ? PROP_SENSITIVE_PRIMARY @@ -8169,35 +8152,6 @@ gtk_entry_mnemonic_activate (GtkWidget *widget, } static void -check_undo_icon_grab (GtkEntry *entry, - EntryIconInfo *info) -{ - if (!info->device || - !gtk_widget_device_is_shadowed (GTK_WIDGET (entry), info->device)) - return; - - info->pressed = FALSE; - info->current_sequence = NULL; - info->device = NULL; -} - -static void -gtk_entry_grab_notify (GtkWidget *widget, - gboolean was_grabbed) -{ - GtkEntryPrivate *priv = gtk_entry_get_instance_private (GTK_ENTRY (widget)); - gint i; - - GTK_WIDGET_CLASS (gtk_entry_parent_class)->grab_notify (widget, was_grabbed); - - for (i = 0; i < MAX_ICONS; i++) - { - if (priv->icons[i]) - check_undo_icon_grab (GTK_ENTRY (widget), priv->icons[i]); - } -} - -static void append_action_signal (GtkEntry *entry, GtkWidget *menu, const gchar *label, diff --git a/gtk/gtkplacesview.c b/gtk/gtkplacesview.c index fd5968dff0..693a28e3b3 100644 --- a/gtk/gtkplacesview.c +++ b/gtk/gtkplacesview.c @@ -1816,7 +1816,6 @@ out: static void on_address_entry_show_help_pressed (GtkPlacesView *view, GtkEntryIconPosition icon_pos, - GdkEvent *event, GtkEntry *entry) { GtkPlacesViewPrivate *priv; diff --git a/tests/testentryicons.c b/tests/testentryicons.c index 245ab1da2c..3395c879ae 100644 --- a/tests/testentryicons.c +++ b/tests/testentryicons.c @@ -2,7 +2,7 @@ #include <stdio.h> static void -clear_pressed (GtkEntry *entry, gint icon, GdkEvent *event, gpointer data) +clear_pressed (GtkEntry *entry, gint icon, gpointer data) { if (icon == GTK_ENTRY_ICON_SECONDARY) gtk_entry_set_text (entry, ""); |