gtktext: Claim gesture more selectively
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 18 Nov 2022 12:57:02 +0000 (13:57 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Fri, 18 Nov 2022 16:56:14 +0000 (17:56 +0100)
Even though button 1 (or touch down) presses do most often have
an effect in one way or another (starting drag, moving focus,
starting selection, ...), there is one situation that they do
immediately nothing: When clicking on the entry does not move
the text caret around. Dragging might start a selection, but
the entry did not do anything just yet, and an immediate
button/touch release should remain at "did nothing".

And that is precisely the hint that the Wayland IM context's click
gesture takes, clicks that do not scroll nor move the caret around,
having the GtkText not claim the gesture in that situation makes
the IM gesture able to do its thing without in-fighting.

This is typically not a problem when the GtkText is embedded in
another GtkEditable implementation (e.g. GtkEntry), since the
IM gesture is inactive and capturing from the parent widget, so
gets a pass that it otherwise doesn't get when both gestures are
in the same widget. This makes it work regardless of GtkText not
being a child of a composite widget, like NautilusQueryEditor
and AdwRowEntry.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5351
gtk/gtktext.c

index 39eda89baa431e69d98e2a227435fe757d9c67f2..89dda9782f89ce2e4c9cb479dd562879e97e6360 100644 (file)
@@ -2756,8 +2756,6 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
       GdkDevice *source;
       guint state;
 
-      gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
-
       sel_start = priv->selection_bound;
       sel_end = priv->current_pos;
       have_selection = sel_start != sel_end;
@@ -2792,6 +2790,8 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
                     gtk_text_selection_bubble_popup_unset (self);
                   else
                     gtk_text_selection_bubble_popup_set (self);
+
+                  gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
                 }
               else if (extend_selection)
                 {
@@ -2803,6 +2803,8 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
 
                   /* all done, so skip the extend_to_left stuff later */
                   extend_selection = FALSE;
+
+                  gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
                 }
               else
                 {
@@ -2810,6 +2812,7 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
                   priv->in_drag = TRUE;
                   priv->drag_start_x = x;
                   priv->drag_start_y = y;
+                  gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
                 }
             }
           else
@@ -2818,7 +2821,13 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
 
               if (!extend_selection)
                 {
-                  gtk_text_set_selection_bounds (self, tmp_pos, tmp_pos);
+                  if (priv->current_pos != tmp_pos ||
+                      priv->selection_bound != tmp_pos)
+                    {
+                      gtk_text_set_selection_bounds (self, tmp_pos, tmp_pos);
+                      gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+                    }
+
                   priv->handle_place_time = g_get_monotonic_time ();
                 }
               else
@@ -2828,6 +2837,7 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
                     sel_start = sel_end = priv->current_pos;
 
                   gtk_text_set_positions (self, tmp_pos, tmp_pos);
+                  gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
                 }
             }
 
@@ -2836,11 +2846,13 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
         case 2:
           priv->select_words = TRUE;
           gtk_text_select_word (self);
+          gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
           break;
 
         case 3:
           priv->select_lines = TRUE;
           gtk_text_select_line (self);
+          gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
           break;
 
         default: