[gtk/wip/carlosg/text-handle-natives: 33/36] gtktexthandle: Refactor and use native surfaces
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/carlosg/text-handle-natives: 33/36] gtktexthandle: Refactor and use native surfaces
- Date: Thu, 27 Feb 2020 18:27:46 +0000 (UTC)
commit fa1699b3855a38035b56ce2b96c6094d25d235fb
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon Feb 3 15:59:49 2020 +0100
gtktexthandle: Refactor and use native surfaces
Instead of being a GObject managing two GtkWidgets, make GtkTextHandle
a GtkWidget subclass, representing a single handle.
From the perspective of users (GtkText and GtkTextView), this is not a
big leap since they have to be aware of a great deal of text handles'
state. It actually makes things more direct and simple.
With text handles being widgets, those can be actual children of the
widget, and may have their own GdkSurface that we move around at will.
This is the second major aspect of this refactor.
gtk/gtktext.c | 367 ++++++++----------
gtk/gtktexthandle.c | 906 ++++++++++++++++-----------------------------
gtk/gtktexthandleprivate.h | 69 +---
gtk/gtktextview.c | 332 ++++++++---------
4 files changed, 625 insertions(+), 1049 deletions(-)
---
diff --git a/gtk/gtktext.c b/gtk/gtktext.c
index 56f748d312..220327c6d5 100644
--- a/gtk/gtktext.c
+++ b/gtk/gtktext.c
@@ -140,6 +140,13 @@
static GQuark quark_password_hint = 0;
+enum
+{
+ TEXT_HANDLE_CURSOR,
+ TEXT_HANDLE_SELECTION_BOUND,
+ TEXT_HANDLE_N_HANDLES
+};
+
typedef struct _GtkTextPasswordHint GtkTextPasswordHint;
typedef struct _GtkTextPrivate GtkTextPrivate;
@@ -159,7 +166,7 @@ struct _GtkTextPrivate
char *im_module;
GtkWidget *emoji_completion;
- GtkTextHandle *text_handle;
+ GtkTextHandle *text_handles[TEXT_HANDLE_N_HANDLES];
GtkWidget *selection_bubble;
guint selection_bubble_timeout_id;
@@ -230,6 +237,7 @@ struct _GtkTextPrivate
guint selection_handle_dragged : 1;
guint populate_all : 1;
guint propagate_text_width : 1;
+ guint text_handles_enabled : 1;
};
struct _GtkTextPasswordHint
@@ -467,15 +475,12 @@ static gboolean gtk_text_key_controller_key_pressed (GtkEventControllerKey *c
/* GtkTextHandle handlers */
static void gtk_text_handle_drag_started (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
GtkText *self);
static void gtk_text_handle_dragged (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
int x,
int y,
GtkText *self);
static void gtk_text_handle_drag_finished (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
GtkText *self);
/* Internal routines
@@ -542,6 +547,7 @@ static void emit_changed (GtkText *self);
static void gtk_text_update_clipboard_actions (GtkText *self);
static void gtk_text_update_emoji_action (GtkText *self);
+static void gtk_text_update_handles (GtkText *self);
static void gtk_text_activate_clipboard_cut (GtkWidget *widget,
const char *action_name,
@@ -1704,6 +1710,24 @@ gtk_text_get_property (GObject *object,
}
}
+static void
+gtk_text_create_text_handles (GtkText *self)
+{
+ GtkTextPrivate *priv = gtk_text_get_instance_private (self);
+ int i;
+
+ for (i = 0; i < TEXT_HANDLE_N_HANDLES; i++)
+ {
+ priv->text_handles[i] = gtk_text_handle_new (GTK_WIDGET (self));
+ g_signal_connect (priv->text_handles[i], "drag-started",
+ G_CALLBACK (gtk_text_handle_drag_started), self);
+ g_signal_connect (priv->text_handles[i], "handle-dragged",
+ G_CALLBACK (gtk_text_handle_dragged), self);
+ g_signal_connect (priv->text_handles[i], "drag-finished",
+ G_CALLBACK (gtk_text_handle_drag_finished), self);
+ }
+}
+
static void
gtk_text_init (GtkText *self)
{
@@ -1804,6 +1828,8 @@ gtk_text_init (GtkText *self)
}
set_text_cursor (GTK_WIDGET (self));
+
+ gtk_text_create_text_handles (self);
}
static void
@@ -1872,7 +1898,8 @@ gtk_text_finalize (GObject *object)
g_clear_object (&priv->cached_layout);
g_clear_object (&priv->im_context);
g_clear_pointer (&priv->magnifier_popover, gtk_widget_destroy);
- g_clear_object (&priv->text_handle);
+ g_clear_object (&priv->text_handles[TEXT_HANDLE_CURSOR]);
+ g_clear_object (&priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]);
g_free (priv->im_module);
g_clear_pointer (&priv->placeholder, gtk_widget_unparent);
@@ -1907,23 +1934,6 @@ gtk_text_ensure_magnifier (GtkText *self)
gtk_widget_show (priv->magnifier);
}
-static void
-gtk_text_ensure_text_handles (GtkText *self)
-{
- GtkTextPrivate *priv = gtk_text_get_instance_private (self);
-
- if (priv->text_handle)
- return;
-
- priv->text_handle = _gtk_text_handle_new (GTK_WIDGET (self));
- g_signal_connect (priv->text_handle, "drag-started",
- G_CALLBACK (gtk_text_handle_drag_started), self);
- g_signal_connect (priv->text_handle, "handle-dragged",
- G_CALLBACK (gtk_text_handle_dragged), self);
- g_signal_connect (priv->text_handle, "drag-finished",
- G_CALLBACK (gtk_text_handle_drag_finished), self);
-}
-
static void
begin_change (GtkText *self)
{
@@ -2054,10 +2064,8 @@ gtk_text_unmap (GtkWidget *widget)
GtkText *self = GTK_TEXT (widget);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- if (priv->text_handle)
- _gtk_text_handle_set_mode (priv->text_handle,
- GTK_TEXT_HANDLE_MODE_NONE);
-
+ priv->text_handles_enabled = FALSE;
+ gtk_text_update_handles (self);
priv->cursor_alpha = 1.0;
GTK_WIDGET_CLASS (gtk_text_parent_class)->unmap (widget);
@@ -2121,21 +2129,21 @@ update_im_cursor_location (GtkText *self)
}
static void
-gtk_text_move_handle (GtkText *self,
- GtkTextHandlePosition pos,
- int x,
- int y,
- int height)
+gtk_text_move_handle (GtkText *self,
+ GtkTextHandle *handle,
+ int x,
+ int y,
+ int height)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- if (!_gtk_text_handle_get_is_dragged (priv->text_handle, pos) &&
+ if (!gtk_text_handle_get_is_dragged (handle) &&
(x < 0 || x > gtk_widget_get_width (GTK_WIDGET (self))))
{
/* Hide the handle if it's not being manipulated
* and fell outside of the visible text area.
*/
- _gtk_text_handle_set_visible (priv->text_handle, pos, FALSE);
+ gtk_widget_hide (GTK_WIDGET (handle));
}
else
{
@@ -2146,9 +2154,9 @@ gtk_text_move_handle (GtkText *self,
rect.width = 1;
rect.height = height;
- _gtk_text_handle_set_visible (priv->text_handle, pos, TRUE);
- _gtk_text_handle_set_position (priv->text_handle, pos, &rect);
- _gtk_text_handle_set_direction (priv->text_handle, pos, priv->resolved_dir);
+ gtk_text_handle_set_position (handle, &rect);
+ gtk_widget_set_direction (GTK_WIDGET (handle), priv->resolved_dir);
+ gtk_widget_show (GTK_WIDGET (handle));
}
}
@@ -2176,45 +2184,62 @@ gtk_text_get_selection_bound_location (GtkText *self)
}
static void
-gtk_text_update_handles (GtkText *self,
- GtkTextHandleMode mode)
+gtk_text_update_handles (GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
const int text_height = gtk_widget_get_height (GTK_WIDGET (self));
int strong_x;
int cursor, bound;
- _gtk_text_handle_set_mode (priv->text_handle, mode);
+ if (!priv->text_handles_enabled)
+ {
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_CURSOR]));
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
+ }
+ else
+ {
+ gtk_text_get_cursor_locations (self, &strong_x, NULL);
+ cursor = strong_x - priv->scroll_offset;
- gtk_text_get_cursor_locations (self, &strong_x, NULL);
- cursor = strong_x - priv->scroll_offset;
+ if (priv->selection_bound != priv->current_pos)
+ {
+ int start, end;
- if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
- {
- int start, end;
+ bound = gtk_text_get_selection_bound_location (self) - priv->scroll_offset;
- bound = gtk_text_get_selection_bound_location (self) - priv->scroll_offset;
+ if (priv->selection_bound > priv->current_pos)
+ {
+ start = cursor;
+ end = bound;
+ }
+ else
+ {
+ start = bound;
+ end = cursor;
+ }
- if (priv->selection_bound > priv->current_pos)
- {
- start = cursor;
- end = bound;
+ /* Update start selection bound */
+ gtk_text_handle_set_role (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND],
+ GTK_TEXT_HANDLE_ROLE_SELECTION_END);
+ gtk_text_move_handle (self,
+ priv->text_handles[TEXT_HANDLE_SELECTION_BOUND],
+ end, 0, text_height);
+ gtk_text_handle_set_role (priv->text_handles[TEXT_HANDLE_CURSOR],
+ GTK_TEXT_HANDLE_ROLE_SELECTION_START);
+ gtk_text_move_handle (self,
+ priv->text_handles[TEXT_HANDLE_CURSOR],
+ start, 0, text_height);
}
else
{
- start = bound;
- end = cursor;
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
+ gtk_text_handle_set_role (priv->text_handles[TEXT_HANDLE_CURSOR],
+ GTK_TEXT_HANDLE_ROLE_CURSOR);
+ gtk_text_move_handle (self,
+ priv->text_handles[TEXT_HANDLE_CURSOR],
+ cursor, 0, text_height);
}
-
- /* Update start selection bound */
- gtk_text_move_handle (self, GTK_TEXT_HANDLE_POSITION_SELECTION_START,
- start, 0, text_height);
- gtk_text_move_handle (self, GTK_TEXT_HANDLE_POSITION_SELECTION_END,
- end, 0, text_height);
}
- else
- gtk_text_move_handle (self, GTK_TEXT_HANDLE_POSITION_CURSOR,
- cursor, 0, text_height);
}
static void
@@ -2345,13 +2370,7 @@ gtk_text_size_allocate (GtkWidget *widget,
if (chooser)
gtk_native_check_resize (GTK_NATIVE (chooser));
- if (priv->text_handle)
- {
- GtkTextHandleMode handle_mode = _gtk_text_handle_get_mode (priv->text_handle);
-
- if (handle_mode != GTK_TEXT_HANDLE_MODE_NONE)
- gtk_text_update_handles (self, handle_mode);
- }
+ gtk_text_update_handles (self);
if (priv->emoji_completion)
gtk_native_check_resize (GTK_NATIVE (priv->emoji_completion));
@@ -2364,6 +2383,12 @@ gtk_text_size_allocate (GtkWidget *widget,
if (priv->selection_bubble)
gtk_native_check_resize (GTK_NATIVE (priv->selection_bubble));
+
+ if (priv->text_handles[TEXT_HANDLE_CURSOR])
+ gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_CURSOR]));
+
+ if (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])
+ gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
}
static void
@@ -2602,7 +2627,6 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
else if (button == GDK_BUTTON_PRIMARY)
{
gboolean have_selection;
- GtkTextHandleMode mode;
gboolean is_touchscreen, extend_selection;
GdkDevice *source;
guint state;
@@ -2615,15 +2639,7 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
is_touchscreen = gtk_simulate_touchscreen () ||
gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN;
- if (!is_touchscreen)
- mode = GTK_TEXT_HANDLE_MODE_NONE;
- else if (have_selection)
- mode = GTK_TEXT_HANDLE_MODE_SELECTION;
- else
- mode = GTK_TEXT_HANDLE_MODE_CURSOR;
-
- if (is_touchscreen)
- gtk_text_ensure_text_handles (self);
+ priv->text_handles_enabled = is_touchscreen;
priv->in_drag = FALSE;
priv->select_words = FALSE;
@@ -2696,15 +2712,11 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
case 2:
priv->select_words = TRUE;
gtk_text_select_word (self);
- if (is_touchscreen)
- mode = GTK_TEXT_HANDLE_MODE_SELECTION;
break;
case 3:
priv->select_lines = TRUE;
gtk_text_select_line (self);
- if (is_touchscreen)
- mode = GTK_TEXT_HANDLE_MODE_SELECTION;
break;
default:
@@ -2736,8 +2748,7 @@ gtk_text_click_gesture_pressed (GtkGestureClick *gesture,
gtk_gesture_set_state (priv->drag_gesture,
GTK_EVENT_SEQUENCE_CLAIMED);
- if (priv->text_handle)
- gtk_text_update_handles (self, mode);
+ gtk_text_update_handles (self);
}
if (n_press >= 3)
@@ -2953,11 +2964,8 @@ gtk_text_drag_gesture_update (GtkGestureDrag *gesture,
if (gtk_simulate_touchscreen () ||
input_source == GDK_SOURCE_TOUCHSCREEN)
{
- gtk_text_ensure_text_handles (self);
- gtk_text_update_handles (self,
- (priv->current_pos == priv->selection_bound) ?
- GTK_TEXT_HANDLE_MODE_CURSOR :
- GTK_TEXT_HANDLE_MODE_SELECTION);
+ priv->text_handles_enabled = TRUE;
+ gtk_text_update_handles (self);
gtk_text_show_magnifier (self, x - priv->scroll_offset, y);
}
}
@@ -2970,10 +2978,8 @@ gtk_text_drag_gesture_end (GtkGestureDrag *gesture,
GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- gboolean in_drag, is_touchscreen;
+ gboolean in_drag;
GdkEventSequence *sequence;
- GdkEvent *event;
- GdkDevice *source;
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
in_drag = priv->in_drag;
@@ -2986,11 +2992,6 @@ gtk_text_drag_gesture_end (GtkGestureDrag *gesture,
if (!gtk_gesture_handles_sequence (GTK_GESTURE (gesture), sequence))
return;
- event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
- source = gdk_event_get_source_device (event);
- is_touchscreen = gtk_simulate_touchscreen () ||
- gdk_device_get_source (source) == GDK_SOURCE_TOUCHSCREEN;
-
if (in_drag)
{
int tmp_pos = gtk_text_find_position (self, priv->drag_start_x);
@@ -2998,8 +2999,7 @@ gtk_text_drag_gesture_end (GtkGestureDrag *gesture,
gtk_text_set_selection_bounds (self, tmp_pos, tmp_pos);
}
- if (is_touchscreen && priv->selection_bound != priv->current_pos)
- gtk_text_update_handles (self, GTK_TEXT_HANDLE_MODE_CURSOR);
+ gtk_text_update_handles (self);
gtk_text_update_primary_selection (self);
}
@@ -3032,9 +3032,8 @@ gtk_text_key_controller_key_pressed (GtkEventControllerKey *controller,
gtk_text_selection_bubble_popup_unset (self);
- if (priv->text_handle)
- _gtk_text_handle_set_mode (priv->text_handle,
- GTK_TEXT_HANDLE_MODE_NONE);
+ priv->text_handles_enabled = FALSE;
+ gtk_text_update_handles (self);
if (keyval == GDK_KEY_Return ||
keyval == GDK_KEY_KP_Enter ||
@@ -3085,9 +3084,8 @@ gtk_text_focus_out (GtkWidget *widget)
gtk_text_selection_bubble_popup_unset (self);
- if (priv->text_handle)
- _gtk_text_handle_set_mode (priv->text_handle,
- GTK_TEXT_HANDLE_MODE_NONE);
+ priv->text_handles_enabled = FALSE;
+ gtk_text_update_handles (self);
gtk_widget_queue_draw (widget);
@@ -3961,15 +3959,7 @@ gtk_text_cut_clipboard (GtkText *self)
gtk_text_selection_bubble_popup_unset (self);
- if (priv->text_handle)
- {
- GtkTextHandleMode handle_mode;
-
- handle_mode = _gtk_text_handle_get_mode (priv->text_handle);
-
- if (handle_mode != GTK_TEXT_HANDLE_MODE_NONE)
- gtk_text_update_handles (self, GTK_TEXT_HANDLE_MODE_CURSOR);
- }
+ gtk_text_update_handles (self);
}
static void
@@ -3982,15 +3972,7 @@ gtk_text_paste_clipboard (GtkText *self)
else
gtk_widget_error_bell (GTK_WIDGET (self));
- if (priv->text_handle)
- {
- GtkTextHandleMode handle_mode;
-
- handle_mode = _gtk_text_handle_get_mode (priv->text_handle);
-
- if (handle_mode != GTK_TEXT_HANDLE_MODE_NONE)
- gtk_text_update_handles (self, GTK_TEXT_HANDLE_MODE_CURSOR);
- }
+ gtk_text_update_handles (self);
}
static void
@@ -4247,9 +4229,6 @@ gtk_text_reset_layout (GtkText *self)
static void
gtk_text_recompute (GtkText *self)
{
- GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- GtkTextHandleMode handle_mode;
-
gtk_text_reset_layout (self);
gtk_text_check_cursor_blink (self);
@@ -4257,13 +4236,7 @@ gtk_text_recompute (GtkText *self)
update_im_cursor_location (self);
- if (priv->text_handle)
- {
- handle_mode = _gtk_text_handle_get_mode (priv->text_handle);
-
- if (handle_mode != GTK_TEXT_HANDLE_MODE_NONE)
- gtk_text_update_handles (self, handle_mode);
- }
+ gtk_text_update_handles (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
@@ -4546,84 +4519,67 @@ gtk_text_draw_cursor (GtkText *self,
}
static void
-gtk_text_handle_dragged (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- int x,
- int y,
- GtkText *self)
+gtk_text_handle_dragged (GtkTextHandle *handle,
+ int x,
+ int y,
+ GtkText *self)
{
- int cursor_pos, selection_bound_pos, tmp_pos;
+ int cursor_pos, selection_bound_pos, tmp_pos, *old_pos;
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- GtkTextHandleMode mode;
- int *min, *max;
gtk_text_selection_bubble_popup_unset (self);
cursor_pos = priv->current_pos;
selection_bound_pos = priv->selection_bound;
- mode = _gtk_text_handle_get_mode (handle);
tmp_pos = gtk_text_find_position (self, x + priv->scroll_offset);
- if (mode == GTK_TEXT_HANDLE_MODE_CURSOR ||
- cursor_pos >= selection_bound_pos)
- {
- max = &cursor_pos;
- min = &selection_bound_pos;
- }
- else
- {
- max = &selection_bound_pos;
- min = &cursor_pos;
- }
-
- if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
+ if (handle == priv->text_handles[TEXT_HANDLE_CURSOR])
{
- if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
+ /* Avoid running past the other handle in selection mode */
+ if (tmp_pos >= selection_bound_pos &&
+ gtk_widget_is_visible (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])))
{
- int min_pos;
-
- min_pos = MAX (*min + 1, 0);
- tmp_pos = MAX (tmp_pos, min_pos);
+ tmp_pos = selection_bound_pos - 1;
}
- *max = tmp_pos;
+ old_pos = &cursor_pos;
}
- else
+ else if (handle == priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])
{
- if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
- {
- int max_pos;
+ /* Avoid running past the other handle */
+ if (tmp_pos <= cursor_pos)
+ tmp_pos = cursor_pos + 1;
- max_pos = *max - 1;
- *min = MIN (tmp_pos, max_pos);
- }
+ old_pos = &selection_bound_pos;
}
+ else
+ g_assert_not_reached ();
- if (cursor_pos != priv->current_pos ||
- selection_bound_pos != priv->selection_bound)
+ if (tmp_pos != *old_pos)
{
- if (mode == GTK_TEXT_HANDLE_MODE_CURSOR)
- {
- priv->cursor_handle_dragged = TRUE;
- gtk_text_set_positions (self, cursor_pos, cursor_pos);
- }
+ *old_pos = tmp_pos;
+
+ if (handle == priv->text_handles[TEXT_HANDLE_CURSOR] &&
+ !gtk_widget_is_visible (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])))
+ gtk_text_set_positions (self, cursor_pos, cursor_pos);
else
- {
- priv->selection_handle_dragged = TRUE;
- gtk_text_set_positions (self, cursor_pos, selection_bound_pos);
- }
+ gtk_text_set_positions (self, cursor_pos, selection_bound_pos);
+
+ if (handle == priv->text_handles[TEXT_HANDLE_CURSOR])
+ priv->cursor_handle_dragged = TRUE;
+ else if (handle == priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])
+ priv->selection_handle_dragged = TRUE;
- gtk_text_update_handles (self, mode);
+ gtk_text_update_handles (self);
}
gtk_text_show_magnifier (self, x, y);
}
static void
-gtk_text_handle_drag_started (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GtkText *self)
+gtk_text_handle_drag_started (GtkTextHandle *handle,
+ GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
@@ -4632,9 +4588,8 @@ gtk_text_handle_drag_started (GtkTextHandle *handle,
}
static void
-gtk_text_handle_drag_finished (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GtkText *self)
+gtk_text_handle_drag_finished (GtkTextHandle *handle,
+ GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
@@ -4648,7 +4603,7 @@ gtk_text_handle_drag_finished (GtkTextHandle *handle,
if (g_get_monotonic_time() - priv->handle_place_time < double_click_time * 1000)
{
gtk_text_select_word (self);
- gtk_text_update_handles (self, GTK_TEXT_HANDLE_MODE_SELECTION);
+ gtk_text_update_handles (self);
}
else
gtk_text_selection_bubble_popup_set (self);
@@ -4759,20 +4714,14 @@ static gboolean
gtk_text_get_is_selection_handle_dragged (GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- GtkTextHandlePosition pos;
-
- if (!priv->text_handle)
- return FALSE;
-
- if (_gtk_text_handle_get_mode (priv->text_handle) != GTK_TEXT_HANDLE_MODE_SELECTION)
- return FALSE;
+ GtkTextHandle *handle;
if (priv->current_pos >= priv->selection_bound)
- pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
+ handle = priv->text_handles[TEXT_HANDLE_CURSOR];
else
- pos = GTK_TEXT_HANDLE_POSITION_SELECTION_END;
+ handle = priv->text_handles[TEXT_HANDLE_SELECTION_BOUND];
- return _gtk_text_handle_get_is_dragged (priv->text_handle, pos);
+ return gtk_text_handle_get_is_dragged (handle);
}
static void
@@ -4822,7 +4771,6 @@ gtk_text_adjust_scroll (GtkText *self)
int min_offset, max_offset;
int strong_x, weak_x;
int strong_xoffset, weak_xoffset;
- GtkTextHandleMode handle_mode;
if (!gtk_widget_get_realized (GTK_WIDGET (self)))
return;
@@ -4885,13 +4833,7 @@ gtk_text_adjust_scroll (GtkText *self)
g_object_notify_by_pspec (G_OBJECT (self), text_props[PROP_SCROLL_OFFSET]);
- if (priv->text_handle)
- {
- handle_mode = _gtk_text_handle_get_mode (priv->text_handle);
-
- if (handle_mode != GTK_TEXT_HANDLE_MODE_NONE)
- gtk_text_update_handles (self, handle_mode);
- }
+ gtk_text_update_handles (self);
}
static int
@@ -5930,23 +5872,10 @@ show_or_hide_handles (GtkWidget *popover,
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
gboolean visible;
- GtkTextHandle *handle;
- GtkTextHandleMode mode;
visible = gtk_widget_get_visible (popover);
-
- handle = priv->text_handle;
- mode = _gtk_text_handle_get_mode (handle);
-
- if (mode == GTK_TEXT_HANDLE_MODE_CURSOR)
- {
- _gtk_text_handle_set_visible (handle, GTK_TEXT_HANDLE_POSITION_CURSOR, !visible);
- }
- else if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
- {
- _gtk_text_handle_set_visible (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, !visible);
- _gtk_text_handle_set_visible (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, !visible);
- }
+ priv->text_handles_enabled = !visible;
+ gtk_text_update_handles (self);
}
static void
diff --git a/gtk/gtktexthandle.c b/gtk/gtktexthandle.c
index c22a928731..a79df5442a 100644
--- a/gtk/gtktexthandle.c
+++ b/gtk/gtktexthandle.c
@@ -25,7 +25,6 @@
#include "gtkwindowprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkwidgetprivate.h"
-#include "gtkgizmoprivate.h"
#include "gtkrendericonprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkintl.h"
@@ -33,7 +32,6 @@
#include <gtk/gtk.h>
typedef struct _GtkTextHandlePrivate GtkTextHandlePrivate;
-typedef struct _HandleWindow HandleWindow;
enum {
DRAG_STARTED,
@@ -42,571 +40,279 @@ enum {
LAST_SIGNAL
};
-enum {
- PROP_0,
- PROP_PARENT
-};
-
-struct _HandleWindow
+struct _GtkTextHandlePrivate
{
- GtkWidget *widget;
+ GtkWidget *parent;
+ GdkSurface *surface;
+ GskRenderer *renderer;
+
GdkRectangle pointing_to;
GtkBorder border;
gint dx;
gint dy;
- GtkTextDirection dir;
+ guint role : 2;
guint dragged : 1;
guint mode_visible : 1;
guint user_visible : 1;
guint has_point : 1;
};
-struct _GtkTextHandlePrivate
+struct _GtkTextHandle
{
- HandleWindow windows[2];
- GtkWidget *toplevel;
- GtkWidget *parent;
- GtkScrollable *parent_scrollable;
- GtkAdjustment *vadj;
- GtkAdjustment *hadj;
- guint hierarchy_changed_id;
- guint scrollable_notify_id;
- guint mode : 2;
+ GtkWidget parent_instance;
};
-G_DEFINE_TYPE_WITH_PRIVATE (GtkTextHandle, _gtk_text_handle, G_TYPE_OBJECT)
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void _gtk_text_handle_update (GtkTextHandle *handle,
- GtkTextHandlePosition pos);
+static void gtk_text_handle_native_interface_init (GtkNativeInterface *iface);
-static void
-_gtk_text_handle_get_size (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- gint *width,
- gint *height)
-{
- GtkTextHandlePrivate *priv = handle->priv;
- GtkWidget *widget = priv->windows[pos].widget;
- GtkStyleContext *context;
-
- context = gtk_widget_get_style_context (widget);
-
- *width = _gtk_css_number_value_get (_gtk_style_context_peek_property (context,
GTK_CSS_PROPERTY_MIN_WIDTH), 100);
- *height = _gtk_css_number_value_get (_gtk_style_context_peek_property (context,
GTK_CSS_PROPERTY_MIN_HEIGHT), 100);
-}
+G_DEFINE_TYPE_WITH_CODE (GtkTextHandle, gtk_text_handle, GTK_TYPE_WIDGET,
+ G_ADD_PRIVATE (GtkTextHandle)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
+ gtk_text_handle_native_interface_init))
-static gint
-_text_handle_pos_from_widget (GtkTextHandle *handle,
- GtkWidget *widget)
-{
- GtkTextHandlePrivate *priv = handle->priv;
-
- if (widget == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget)
- return GTK_TEXT_HANDLE_POSITION_SELECTION_START;
- else if (widget == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget)
- return GTK_TEXT_HANDLE_POSITION_SELECTION_END;
- else
- return -1;
-}
+static guint signals[LAST_SIGNAL] = { 0 };
-static void
-handle_drag_begin (GtkGestureDrag *gesture,
- gdouble x,
- gdouble y,
- GtkTextHandle *handle)
+static GdkSurface *
+gtk_text_handle_native_get_surface (GtkNative *native)
{
- GtkTextHandlePrivate *priv = handle->priv;
- GtkWidget *widget;
- gint pos;
-
- widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
- pos = _text_handle_pos_from_widget (handle, widget);
-
- if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR &&
- priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR)
- x -= gtk_widget_get_width (widget) / 2;
- else if ((pos == GTK_TEXT_HANDLE_POSITION_CURSOR &&
- priv->windows[pos].dir == GTK_TEXT_DIR_RTL) ||
- (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_START &&
- priv->windows[pos].dir != GTK_TEXT_DIR_RTL))
- x -= gtk_widget_get_width (widget);
-
- y += priv->windows[pos].border.top / 2;
+ GtkTextHandle *handle = GTK_TEXT_HANDLE (native);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- priv->windows[pos].dx = x;
- priv->windows[pos].dy = y;
- priv->windows[pos].dragged = TRUE;
- g_signal_emit (handle, signals[DRAG_STARTED], 0, pos);
+ return priv->surface;
}
-static void
-handle_drag_update (GtkGestureDrag *gesture,
- gdouble offset_x,
- gdouble offset_y,
- GtkTextHandle *handle)
+static GskRenderer *
+gtk_text_handle_native_get_renderer (GtkNative *native)
{
- GtkTextHandlePrivate *priv = handle->priv;
- gdouble start_x, start_y;
- gint pos, x, y;
-
- pos = _text_handle_pos_from_widget (handle,
- gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)));
- gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
+ GtkTextHandle *handle = GTK_TEXT_HANDLE (native);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- gtk_widget_translate_coordinates (priv->windows[pos].widget, priv->parent,
- start_x + offset_x - priv->windows[pos].dx,
- start_y + offset_y - priv->windows[pos].dy,
- &x, &y);
- g_signal_emit (handle, signals[HANDLE_DRAGGED], 0, pos, x, y);
+ return priv->renderer;
}
static void
-handle_drag_end (GtkGestureDrag *gesture,
- gdouble offset_x,
- gdouble offset_y,
- GtkTextHandle *handle)
+gtk_text_handle_native_get_surface_transform (GtkNative *native,
+ int *x,
+ int *y)
{
- GtkTextHandlePrivate *priv = handle->priv;
- gint pos;
-
- pos = _text_handle_pos_from_widget (handle,
- gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)));
- g_signal_emit (handle, signals[DRAG_FINISHED], 0, pos);
- priv->windows[pos].dragged = FALSE;
+ GtkCssStyle *style;
+
+ style = gtk_css_node_get_style (gtk_widget_get_css_node (GTK_WIDGET (native)));
+ *x = _gtk_css_number_value_get (style->size->margin_left, 100) +
+ _gtk_css_number_value_get (style->border->border_left_width, 100) +
+ _gtk_css_number_value_get (style->size->padding_left, 100);
+ *y = _gtk_css_number_value_get (style->size->margin_top, 100) +
+ _gtk_css_number_value_get (style->border->border_top_width, 100) +
+ _gtk_css_number_value_get (style->size->padding_top, 100);
}
static void
-snapshot_func (GtkGizmo *gizmo,
- GtkSnapshot *snapshot)
+gtk_text_handle_native_check_resize (GtkNative *native)
{
- GtkCssStyle *style = gtk_css_node_get_style (gtk_widget_get_css_node (GTK_WIDGET (gizmo)));
+ GtkTextHandle *handle = GTK_TEXT_HANDLE (native);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
+ GtkWidget *widget = GTK_WIDGET (native);
- gtk_css_style_snapshot_icon (style,
- snapshot,
- gtk_widget_get_width (GTK_WIDGET (gizmo)),
- gtk_widget_get_height (GTK_WIDGET (gizmo)));
-}
-
-static GtkWidget *
-_gtk_text_handle_ensure_widget (GtkTextHandle *handle,
- GtkTextHandlePosition pos)
-{
- GtkTextHandlePrivate *priv;
-
- priv = handle->priv;
-
- if (!priv->windows[pos].widget)
+ if (!_gtk_widget_get_alloc_needed (widget))
+ gtk_widget_ensure_allocate (widget);
+ else if (gtk_widget_get_visible (widget) && priv->surface)
{
- GtkWidget *widget, *window;
- GtkEventController *controller;
-
- widget = gtk_gizmo_new (I_("cursor-handle"), NULL, NULL, snapshot_func, NULL);
-
- gtk_widget_set_direction (widget, priv->windows[pos].dir);
-
- controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
- g_signal_connect (controller, "drag-begin",
- G_CALLBACK (handle_drag_begin), handle);
- g_signal_connect (controller, "drag-update",
- G_CALLBACK (handle_drag_update), handle);
- g_signal_connect (controller, "drag-end",
- G_CALLBACK (handle_drag_end), handle);
- gtk_widget_add_controller (widget, controller);
-
- priv->windows[pos].widget = g_object_ref_sink (widget);
- priv->toplevel = window = gtk_widget_get_ancestor (priv->parent, GTK_TYPE_WINDOW);
- _gtk_window_add_popover (GTK_WINDOW (window), widget, priv->parent, FALSE);
-
- if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
- {
- gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_BOTTOM);
- if (priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR)
- gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_INSERTION_CURSOR);
- }
- else
- gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_TOP);
- }
-
- return priv->windows[pos].widget;
-}
-
-static void
-_handle_update_child_visible (GtkTextHandle *handle,
- GtkTextHandlePosition pos)
-{
- HandleWindow *handle_window;
- GtkTextHandlePrivate *priv;
- cairo_rectangle_int_t rect;
- GtkAllocation allocation;
- GtkWidget *parent;
+ GtkRequisition req;
- priv = handle->priv;
- handle_window = &priv->windows[pos];
+ gtk_widget_get_preferred_size (GTK_WIDGET (handle), NULL, &req);
+ gdk_surface_resize (priv->surface, req.width, req.height);
- if (!priv->parent_scrollable)
- {
- gtk_widget_set_child_visible (handle_window->widget, TRUE);
- return;
+ gtk_widget_allocate (widget,
+ req.width, req.height,
+ -1, NULL);
}
-
- parent = gtk_widget_get_parent (GTK_WIDGET (priv->parent_scrollable));
- rect = handle_window->pointing_to;
-
- gtk_widget_translate_coordinates (priv->parent, parent,
- rect.x, rect.y, &rect.x, &rect.y);
-
- gtk_widget_get_allocation (GTK_WIDGET (parent), &allocation);
-
- if (rect.x < 0 || rect.x + rect.width > allocation.width ||
- rect.y < 0 || rect.y + rect.height > allocation.height)
- gtk_widget_set_child_visible (handle_window->widget, FALSE);
- else
- gtk_widget_set_child_visible (handle_window->widget, TRUE);
}
static void
-_gtk_text_handle_update (GtkTextHandle *handle,
- GtkTextHandlePosition pos)
+gtk_text_handle_native_interface_init (GtkNativeInterface *iface)
{
- GtkTextHandlePrivate *priv;
- HandleWindow *handle_window;
- GtkBorder *border;
-
- priv = handle->priv;
- handle_window = &priv->windows[pos];
- border = &handle_window->border;
-
- if (!priv->parent || !gtk_widget_is_drawable (priv->parent))
- return;
-
- if (handle_window->has_point &&
- handle_window->mode_visible && handle_window->user_visible)
- {
- cairo_rectangle_int_t rect;
- gint width, height;
- GtkWidget *window;
- GtkAllocation alloc;
- gint w, h;
-
- _gtk_text_handle_ensure_widget (handle, pos);
- _gtk_text_handle_get_size (handle, pos, &width, &height);
-
- border->top = height;
- border->bottom = height;
- border->left = width;
- border->right = width;
-
- rect.x = handle_window->pointing_to.x;
- rect.y = handle_window->pointing_to.y + handle_window->pointing_to.height - handle_window->border.top;
- rect.width = width;
- rect.height = 0;
-
- _handle_update_child_visible (handle, pos);
-
- window = gtk_widget_get_parent (handle_window->widget);
- gtk_widget_translate_coordinates (priv->parent, window,
- rect.x, rect.y, &rect.x, &rect.y);
-
- if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR &&
- priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR)
- rect.x -= rect.width / 2;
- else if ((pos == GTK_TEXT_HANDLE_POSITION_CURSOR &&
- handle_window->dir == GTK_TEXT_DIR_RTL) ||
- (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_START &&
- handle_window->dir != GTK_TEXT_DIR_RTL))
- rect.x -= rect.width;
-
- /* The goal is to make the window 3 times as wide and high. The handle
- * will be rendered in the center, making the rest an invisible border.
- * If we hit the edge of the toplevel, we shrink the border to avoid
- * mispositioning the handle, if at all possible. This calculation uses
- * knowledge about how popover_get_rect() works.
- */
-
- gtk_widget_get_allocation (window, &alloc);
-
- w = width + border->left + border->right;
- h = height + border->top + border->bottom;
-
- if (rect.x + rect.width/2 - w/2 < alloc.x)
- border->left = MAX (0, border->left - (alloc.x - (rect.x + rect.width/2 - w/2)));
- if (rect.y + rect.height/2 - h/2 < alloc.y)
- border->top = MAX (0, border->top - (alloc.y - (rect.y + rect.height/2 - h/2)));
- if (rect.x + rect.width/2 + w/2 > alloc.x + alloc.width)
- border->right = MAX (0, border->right - (rect.x + rect.width/2 + w/2 - (alloc.x + alloc.width)));
- if (rect.y + rect.height/2 + h/2 > alloc.y + alloc.height)
- border->bottom = MAX (0, border->bottom - (rect.y + rect.height/2 + h/2 - (alloc.y + alloc.height)));
-
- width += border->left + border->right;
- height += border->top + border->bottom;
-
- gtk_widget_set_size_request (handle_window->widget, width, height);
- gtk_widget_show (handle_window->widget);
- _gtk_window_raise_popover (GTK_WINDOW (window), handle_window->widget);
- _gtk_window_set_popover_position (GTK_WINDOW (window),
- handle_window->widget,
- GTK_POS_BOTTOM, &rect);
- }
- else if (handle_window->widget)
- gtk_widget_hide (handle_window->widget);
+ iface->get_surface = gtk_text_handle_native_get_surface;
+ iface->get_renderer = gtk_text_handle_native_get_renderer;
+ iface->get_surface_transform = gtk_text_handle_native_get_surface_transform;
+ iface->check_resize = gtk_text_handle_native_check_resize;
}
-static void
-adjustment_changed_cb (GtkAdjustment *adjustment,
- GtkTextHandle *handle)
+static gboolean
+surface_render (GdkSurface *surface,
+ cairo_region_t *region,
+ GtkTextHandle *handle)
{
- _gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
- _gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
+ gtk_widget_render (GTK_WIDGET (handle), surface, region);
+ return TRUE;
}
-static void
-_gtk_text_handle_set_scrollable (GtkTextHandle *handle,
- GtkScrollable *scrollable)
+static gboolean
+surface_event (GdkSurface *surface,
+ GdkEvent *event,
+ GtkTextHandle *handle)
{
- GtkTextHandlePrivate *priv;
-
- priv = handle->priv;
-
- if (priv->vadj)
- {
- g_signal_handlers_disconnect_by_data (priv->vadj, handle);
- g_clear_object (&priv->vadj);
- }
-
- if (priv->hadj)
- {
- g_signal_handlers_disconnect_by_data (priv->hadj, handle);
- g_clear_object (&priv->hadj);
- }
-
- if (priv->parent_scrollable)
- g_object_remove_weak_pointer (G_OBJECT (priv->parent_scrollable), (gpointer *) &priv->parent_scrollable);
-
- priv->parent_scrollable = scrollable;
-
- if (scrollable)
- {
- g_object_add_weak_pointer (G_OBJECT (priv->parent_scrollable), (gpointer *) &priv->parent_scrollable);
-
- priv->vadj = gtk_scrollable_get_vadjustment (scrollable);
- priv->hadj = gtk_scrollable_get_hadjustment (scrollable);
-
- if (priv->vadj)
- {
- g_object_ref (priv->vadj);
- g_signal_connect (priv->vadj, "changed",
- G_CALLBACK (adjustment_changed_cb), handle);
- g_signal_connect (priv->vadj, "value-changed",
- G_CALLBACK (adjustment_changed_cb), handle);
- }
-
- if (priv->hadj)
- {
- g_object_ref (priv->hadj);
- g_signal_connect (priv->hadj, "changed",
- G_CALLBACK (adjustment_changed_cb), handle);
- g_signal_connect (priv->hadj, "value-changed",
- G_CALLBACK (adjustment_changed_cb), handle);
- }
- }
+ gtk_main_do_event (event);
+ return TRUE;
}
static void
-_gtk_text_handle_scrollable_notify (GObject *object,
- GParamSpec *pspec,
- GtkTextHandle *handle)
+gtk_text_handle_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
{
- if (pspec->value_type == GTK_TYPE_ADJUSTMENT)
- _gtk_text_handle_set_scrollable (handle, GTK_SCROLLABLE (object));
+ GtkCssStyle *style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
+
+ gtk_css_style_snapshot_icon (style,
+ snapshot,
+ gtk_widget_get_width (widget),
+ gtk_widget_get_height (widget));
}
static void
-_gtk_text_handle_update_scrollable (GtkTextHandle *handle,
- GtkScrollable *scrollable)
+gtk_text_handle_get_size (GtkTextHandle *handle,
+ gint *width,
+ gint *height)
{
- GtkTextHandlePrivate *priv;
-
- priv = handle->priv;
-
- if (priv->parent_scrollable == scrollable)
- return;
-
- if (priv->parent_scrollable && priv->scrollable_notify_id &&
- g_signal_handler_is_connected (priv->parent_scrollable,
- priv->scrollable_notify_id))
- g_signal_handler_disconnect (priv->parent_scrollable,
- priv->scrollable_notify_id);
+ GtkWidget *widget = GTK_WIDGET (handle);
+ GtkStyleContext *context;
- _gtk_text_handle_set_scrollable (handle, scrollable);
+ context = gtk_widget_get_style_context (widget);
- if (priv->parent_scrollable)
- priv->scrollable_notify_id =
- g_signal_connect (priv->parent_scrollable, "notify",
- G_CALLBACK (_gtk_text_handle_scrollable_notify),
- handle);
+ *width = _gtk_css_number_value_get (_gtk_style_context_peek_property (context,
GTK_CSS_PROPERTY_MIN_WIDTH), 100);
+ *height = _gtk_css_number_value_get (_gtk_style_context_peek_property (context,
GTK_CSS_PROPERTY_MIN_HEIGHT), 100);
}
-static GtkWidget *
-gtk_text_handle_lookup_scrollable (GtkTextHandle *handle)
+static void
+gtk_text_handle_realize (GtkWidget *widget)
{
- GtkTextHandlePrivate *priv;
- GtkWidget *scrolled_window;
-
- priv = handle->priv;
- scrolled_window = gtk_widget_get_ancestor (priv->parent,
- GTK_TYPE_SCROLLED_WINDOW);
- if (!scrolled_window)
- return NULL;
+ GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
+ GdkSurface *parent_surface;
+ GtkWidget *parent;
- return gtk_bin_get_child (GTK_BIN (scrolled_window));
-}
+ parent = gtk_widget_get_parent (widget);
+ parent_surface = gtk_native_get_surface (gtk_widget_get_native (parent));
-static void
-_gtk_text_handle_parent_hierarchy_changed (GtkWidget *widget,
- GParamSpec *pspec,
- GtkTextHandle *handle)
-{
- GtkWidget *toplevel, *scrollable;
- GtkTextHandlePrivate *priv;
+ priv->surface = gdk_surface_new_popup (parent_surface, FALSE);
+ gdk_surface_set_widget (priv->surface, widget);
- priv = handle->priv;
- toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+ g_signal_connect (priv->surface, "render", G_CALLBACK (surface_render), widget);
+ g_signal_connect (priv->surface, "event", G_CALLBACK (surface_event), widget);
- if (priv->toplevel && !toplevel)
- {
- if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget)
- {
- _gtk_window_remove_popover (GTK_WINDOW (priv->toplevel),
- priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
- g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
- priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget = NULL;
- }
-
- if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget)
- {
- _gtk_window_remove_popover (GTK_WINDOW (priv->toplevel),
- priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
- g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
- priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget = NULL;
- }
-
- priv->toplevel = NULL;
- }
+ GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->realize (widget);
- scrollable = gtk_text_handle_lookup_scrollable (handle);
- _gtk_text_handle_update_scrollable (handle, GTK_SCROLLABLE (scrollable));
+ priv->renderer = gsk_renderer_new_for_surface (priv->surface);
}
static void
-_gtk_text_handle_set_parent (GtkTextHandle *handle,
- GtkWidget *parent)
+gtk_text_handle_unrealize (GtkWidget *widget)
{
- GtkTextHandlePrivate *priv;
- GtkWidget *scrollable = NULL;
-
- priv = handle->priv;
+ GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- if (priv->parent == parent)
- return;
-
- if (priv->parent && priv->hierarchy_changed_id &&
- g_signal_handler_is_connected (priv->parent, priv->hierarchy_changed_id))
- g_signal_handler_disconnect (priv->parent, priv->hierarchy_changed_id);
-
- priv->parent = parent;
+ GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->unrealize (widget);
- if (parent)
- {
- priv->hierarchy_changed_id =
- g_signal_connect (parent, "notify::root",
- G_CALLBACK (_gtk_text_handle_parent_hierarchy_changed),
- handle);
+ gsk_renderer_unrealize (priv->renderer);
+ g_clear_object (&priv->renderer);
- scrollable = gtk_text_handle_lookup_scrollable (handle);
- }
+ g_signal_handlers_disconnect_by_func (priv->surface, surface_render, widget);
+ g_signal_handlers_disconnect_by_func (priv->surface, surface_event, widget);
- _gtk_text_handle_update_scrollable (handle, GTK_SCROLLABLE (scrollable));
+ gdk_surface_set_widget (priv->surface, NULL);
+ gdk_surface_destroy (priv->surface);
+ g_clear_object (&priv->surface);
}
static void
-gtk_text_handle_finalize (GObject *object)
+gtk_text_handle_present_surface (GtkTextHandle *handle)
{
- GtkTextHandlePrivate *priv;
-
- priv = GTK_TEXT_HANDLE (object)->priv;
-
- _gtk_text_handle_set_parent (GTK_TEXT_HANDLE (object), NULL);
-
- /* We sank the references, unref here */
- if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget)
- g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
-
- if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget)
- g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
+ GtkWidget *widget = GTK_WIDGET (handle);
+ GdkPopupLayout *layout;
+ GdkRectangle rect;
+ gint width, height;
+
+ gtk_text_handle_get_size (handle, &width, &height);
+ priv->border.left = priv->border.right = width;
+ priv->border.top = priv->border.bottom = height;
+
+ rect.x = priv->pointing_to.x;
+ rect.y = priv->pointing_to.y + priv->pointing_to.height - priv->border.top;
+ rect.width = width;
+ rect.height = 1;
+
+ gtk_widget_translate_coordinates (gtk_widget_get_parent (widget),
+ gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW),
+ rect.x, rect.y, &rect.x, &rect.y);
- G_OBJECT_CLASS (_gtk_text_handle_parent_class)->finalize (object);
+ if (priv->role == GTK_TEXT_HANDLE_ROLE_CURSOR)
+ rect.x -= rect.width / 2;
+ else if ((priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_END &&
+ gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ||
+ (priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_START &&
+ gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL))
+ rect.x -= rect.width;
+
+ /* The goal is to make the window 3 times as wide and high. The handle
+ * will be rendered in the center, making the rest an invisible border.
+ */
+ width += priv->border.left + priv->border.right;
+ height += priv->border.top + priv->border.bottom;
+ gtk_widget_set_size_request (widget, width, height);
+ gtk_widget_queue_allocate (widget);
+
+ layout = gdk_popup_layout_new (&rect,
+ GDK_GRAVITY_SOUTH,
+ GDK_GRAVITY_NORTH);
+ gdk_popup_layout_set_anchor_hints (layout,
+ GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X);
+
+ gdk_surface_present_popup (priv->surface,
+ MAX (width, 1),
+ MAX (height, 1),
+ layout);
+ gdk_popup_layout_unref (layout);
}
static void
-gtk_text_handle_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gtk_text_handle_map (GtkWidget *widget)
{
- GtkTextHandle *handle;
+ GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- handle = GTK_TEXT_HANDLE (object);
+ GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->map (widget);
- switch (prop_id)
- {
- case PROP_PARENT:
- _gtk_text_handle_set_parent (handle, g_value_get_object (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
+ if (priv->has_point)
+ gtk_text_handle_present_surface (handle);
}
static void
-gtk_text_handle_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+gtk_text_handle_unmap (GtkWidget *widget)
{
- GtkTextHandlePrivate *priv;
+ GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- priv = GTK_TEXT_HANDLE (object)->priv;
-
- switch (prop_id)
- {
- case PROP_PARENT:
- g_value_set_object (value, priv->parent);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
+ GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->unmap (widget);
+ gdk_surface_hide (priv->surface);
}
static void
-_gtk_text_handle_class_init (GtkTextHandleClass *klass)
+gtk_text_handle_class_init (GtkTextHandleClass *klass)
{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = gtk_text_handle_finalize;
- object_class->set_property = gtk_text_handle_set_property;
- object_class->get_property = gtk_text_handle_get_property;
+ widget_class->snapshot = gtk_text_handle_snapshot;
+ widget_class->realize = gtk_text_handle_realize;
+ widget_class->unrealize = gtk_text_handle_unrealize;
+ widget_class->map = gtk_text_handle_map;
+ widget_class->unmap = gtk_text_handle_unmap;
signals[HANDLE_DRAGGED] =
g_signal_new (I_("handle-dragged"),
G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkTextHandleClass, handle_dragged),
+ G_SIGNAL_RUN_LAST, 0,
NULL, NULL,
- _gtk_marshal_VOID__ENUM_INT_INT,
- G_TYPE_NONE, 3,
- GTK_TYPE_TEXT_HANDLE_POSITION,
+ _gtk_marshal_VOID__INT_INT,
+ G_TYPE_NONE, 2,
G_TYPE_INT, G_TYPE_INT);
signals[DRAG_STARTED] =
g_signal_new (I_("drag-started"),
@@ -614,183 +320,199 @@ _gtk_text_handle_class_init (GtkTextHandleClass *klass)
G_SIGNAL_RUN_LAST, 0,
NULL, NULL,
NULL,
- G_TYPE_NONE, 1,
- GTK_TYPE_TEXT_HANDLE_POSITION);
+ G_TYPE_NONE, 0, G_TYPE_NONE);
signals[DRAG_FINISHED] =
g_signal_new (I_("drag-finished"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST, 0,
NULL, NULL,
NULL,
- G_TYPE_NONE, 1,
- GTK_TYPE_TEXT_HANDLE_POSITION);
-
- g_object_class_install_property (object_class,
- PROP_PARENT,
- g_param_spec_object ("parent",
- P_("Parent widget"),
- P_("Parent widget"),
- GTK_TYPE_WIDGET,
- GTK_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
+ G_TYPE_NONE, 0, G_TYPE_NONE);
}
static void
-_gtk_text_handle_init (GtkTextHandle *handle)
+handle_drag_begin (GtkGestureDrag *gesture,
+ gdouble x,
+ gdouble y,
+ GtkTextHandle *handle)
{
- handle->priv = _gtk_text_handle_get_instance_private (handle);
-}
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
+ GtkWidget *widget;
-GtkTextHandle *
-_gtk_text_handle_new (GtkWidget *parent)
-{
- return g_object_new (GTK_TYPE_TEXT_HANDLE,
- "parent", parent,
- NULL);
+ widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
+
+ if (priv->role == GTK_TEXT_HANDLE_ROLE_CURSOR)
+ x -= gtk_widget_get_width (widget) / 2;
+ else if ((priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_END &&
+ gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ||
+ (priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_START &&
+ gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL))
+ x -= gtk_widget_get_width (widget);
+
+ y += priv->border.top / 2;
+
+ priv->dx = x;
+ priv->dy = y;
+ priv->dragged = TRUE;
+ g_signal_emit (handle, signals[DRAG_STARTED], 0);
}
-void
-_gtk_text_handle_set_mode (GtkTextHandle *handle,
- GtkTextHandleMode mode)
+static void
+handle_drag_update (GtkGestureDrag *gesture,
+ gdouble offset_x,
+ gdouble offset_y,
+ GtkWidget *widget)
{
- GtkTextHandlePrivate *priv;
- HandleWindow *start, *end;
+ GtkTextHandle *text_handle = GTK_TEXT_HANDLE (widget);
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (text_handle);
+ gdouble start_x, start_y;
+ gint x, y;
- g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
+ gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
- priv = handle->priv;
+ x = priv->pointing_to.x + priv->pointing_to.width / 2 +
+ start_x + offset_x - priv->dx;
+ y = priv->pointing_to.y + priv->pointing_to.height +
+ start_y + offset_y - priv->dy;
- if (priv->mode == mode)
- return;
+ if (priv->role == GTK_TEXT_HANDLE_ROLE_CURSOR)
+ x -= gtk_widget_get_width (widget) / 2;
+ else if ((priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_END &&
+ gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ||
+ (priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_START &&
+ gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL))
+ x -= gtk_widget_get_width (widget);
+
+ g_signal_emit (widget, signals[HANDLE_DRAGGED], 0, x, y);
+}
+
+static void
+handle_drag_end (GtkGestureDrag *gesture,
+ gdouble offset_x,
+ gdouble offset_y,
+ GtkTextHandle *handle)
+{
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- priv->mode = mode;
- start = &priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START];
- end = &priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END];
+ g_signal_emit (handle, signals[DRAG_FINISHED], 0);
+ priv->dragged = FALSE;
+}
+
+static void
+gtk_text_handle_update_for_role (GtkTextHandle *handle)
+{
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
+ GtkWidget *widget = GTK_WIDGET (handle);
- switch (mode)
+ if (priv->role == GTK_TEXT_HANDLE_ROLE_CURSOR)
{
- case GTK_TEXT_HANDLE_MODE_CURSOR:
- start->mode_visible = FALSE;
- /* end = cursor */
- end->mode_visible = TRUE;
- break;
- case GTK_TEXT_HANDLE_MODE_SELECTION:
- start->mode_visible = TRUE;
- end->mode_visible = TRUE;
- break;
- case GTK_TEXT_HANDLE_MODE_NONE:
- default:
- start->mode_visible = FALSE;
- end->mode_visible = FALSE;
- break;
+ gtk_widget_remove_css_class (widget, GTK_STYLE_CLASS_TOP);
+ gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_BOTTOM);
+ gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_INSERTION_CURSOR);
}
-
- if (end->widget)
+ else if (priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_END)
{
- if (mode == GTK_TEXT_HANDLE_MODE_CURSOR)
- gtk_style_context_add_class (gtk_widget_get_style_context (end->widget),
GTK_STYLE_CLASS_INSERTION_CURSOR);
- else
- gtk_style_context_remove_class (gtk_widget_get_style_context (end->widget),
GTK_STYLE_CLASS_INSERTION_CURSOR);
+ gtk_widget_remove_css_class (widget, GTK_STYLE_CLASS_TOP);
+ gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_BOTTOM);
+ gtk_widget_remove_css_class (widget, GTK_STYLE_CLASS_INSERTION_CURSOR);
}
+ else if (priv->role == GTK_TEXT_HANDLE_ROLE_SELECTION_START)
+ {
+ gtk_widget_add_css_class (widget, GTK_STYLE_CLASS_TOP);
+ gtk_widget_remove_css_class (widget, GTK_STYLE_CLASS_BOTTOM);
+ gtk_widget_remove_css_class (widget, GTK_STYLE_CLASS_INSERTION_CURSOR);
+ }
+}
- _gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
- _gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
-
- if (start->widget && start->mode_visible)
- gtk_widget_queue_draw (start->widget);
- if (end->widget && end->mode_visible)
- gtk_widget_queue_draw (end->widget);
+static void
+gtk_text_handle_init (GtkTextHandle *widget)
+{
+ GtkEventController *controller;
+
+ controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
+ g_signal_connect (controller, "drag-begin",
+ G_CALLBACK (handle_drag_begin), widget);
+ g_signal_connect (controller, "drag-update",
+ G_CALLBACK (handle_drag_update), widget);
+ g_signal_connect (controller, "drag-end",
+ G_CALLBACK (handle_drag_end), widget);
+ gtk_widget_add_controller (GTK_WIDGET (widget), controller);
+
+ gtk_text_handle_update_for_role (GTK_TEXT_HANDLE (widget));
}
-GtkTextHandleMode
-_gtk_text_handle_get_mode (GtkTextHandle *handle)
+GtkTextHandle *
+gtk_text_handle_new (GtkWidget *parent)
{
- GtkTextHandlePrivate *priv;
+ GtkWidget *handle;
- g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), GTK_TEXT_HANDLE_MODE_NONE);
+ handle = g_object_new (GTK_TYPE_TEXT_HANDLE,
+ "css-name", I_("cursor-handle"),
+ NULL);
+ gtk_widget_set_parent (handle, parent);
- priv = handle->priv;
- return priv->mode;
+ return GTK_TEXT_HANDLE (handle);
}
void
-_gtk_text_handle_set_position (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GdkRectangle *rect)
+gtk_text_handle_set_role (GtkTextHandle *handle,
+ GtkTextHandleRole role)
{
- GtkTextHandlePrivate *priv;
- HandleWindow *handle_window;
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
- priv = handle->priv;
- pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
- GTK_TEXT_HANDLE_POSITION_SELECTION_START);
- handle_window = &priv->windows[pos];
-
- if (priv->mode == GTK_TEXT_HANDLE_MODE_NONE ||
- (priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
- pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
+ if (priv->role == role)
return;
- handle_window->pointing_to = *rect;
- handle_window->has_point = TRUE;
+ priv->role = role;
+ gtk_text_handle_update_for_role (handle);
- if (gtk_widget_is_visible (priv->parent))
- _gtk_text_handle_update (handle, pos);
+ if (gtk_widget_get_visible (GTK_WIDGET (handle)))
+ {
+ gtk_widget_queue_draw (GTK_WIDGET (handle));
+ if (priv->has_point)
+ gtk_text_handle_present_surface (handle);
+ }
}
-void
-_gtk_text_handle_set_visible (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- gboolean visible)
+GtkTextHandleRole
+gtk_text_handle_get_role (GtkTextHandle *handle)
{
- GtkTextHandlePrivate *priv;
-
- g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- priv = handle->priv;
- pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
- GTK_TEXT_HANDLE_POSITION_SELECTION_START);
+ g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), GTK_TEXT_HANDLE_ROLE_CURSOR);
- priv->windows[pos].user_visible = visible;
-
- if (gtk_widget_is_visible (priv->parent))
- _gtk_text_handle_update (handle, pos);
+ return priv->role;
}
-gboolean
-_gtk_text_handle_get_is_dragged (GtkTextHandle *handle,
- GtkTextHandlePosition pos)
+void
+gtk_text_handle_set_position (GtkTextHandle *handle,
+ const GdkRectangle *rect)
{
- GtkTextHandlePrivate *priv;
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), FALSE);
+ g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
+
+ if (priv->pointing_to.x == rect->x &&
+ priv->pointing_to.y == rect->y &&
+ priv->pointing_to.width == rect->width &&
+ priv->pointing_to.height == rect->height)
+ return;
- priv = handle->priv;
- pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
- GTK_TEXT_HANDLE_POSITION_SELECTION_START);
+ priv->pointing_to = *rect;
+ priv->has_point = TRUE;
- return priv->windows[pos].dragged;
+ if (gtk_widget_is_visible (GTK_WIDGET (handle)))
+ gtk_text_handle_present_surface (handle);
}
-void
-_gtk_text_handle_set_direction (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GtkTextDirection dir)
+gboolean
+gtk_text_handle_get_is_dragged (GtkTextHandle *handle)
{
- GtkTextHandlePrivate *priv;
+ GtkTextHandlePrivate *priv = gtk_text_handle_get_instance_private (handle);
- g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
-
- priv = handle->priv;
- pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
- GTK_TEXT_HANDLE_POSITION_SELECTION_START);
- priv->windows[pos].dir = dir;
+ g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), FALSE);
- if (priv->windows[pos].widget)
- {
- gtk_widget_set_direction (priv->windows[pos].widget, dir);
- _gtk_text_handle_update (handle, pos);
- }
+ return priv->dragged;
}
diff --git a/gtk/gtktexthandleprivate.h b/gtk/gtktexthandleprivate.h
index c79aa04cab..0a02eac12e 100644
--- a/gtk/gtktexthandleprivate.h
+++ b/gtk/gtktexthandleprivate.h
@@ -22,68 +22,27 @@
G_BEGIN_DECLS
-#define GTK_TYPE_TEXT_HANDLE (_gtk_text_handle_get_type ())
-#define GTK_TEXT_HANDLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_TEXT_HANDLE,
GtkTextHandle))
-#define GTK_TEXT_HANDLE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_TEXT_HANDLE,
GtkTextHandleClass))
-#define GTK_IS_TEXT_HANDLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_TEXT_HANDLE))
-#define GTK_IS_TEXT_HANDLE_CLASS(o) (G_TYPE_CHECK_CLASS_TYPE ((o), GTK_TYPE_TEXT_HANDLE))
-#define GTK_TEXT_HANDLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_TEXT_HANDLE,
GtkTextHandleClass))
-
-typedef struct _GtkTextHandle GtkTextHandle;
-typedef struct _GtkTextHandleClass GtkTextHandleClass;
+#define GTK_TYPE_TEXT_HANDLE (gtk_text_handle_get_type ())
+G_DECLARE_FINAL_TYPE (GtkTextHandle, gtk_text_handle,
+ GTK, TEXT_HANDLE, GtkWidget)
typedef enum
{
- GTK_TEXT_HANDLE_POSITION_CURSOR,
- GTK_TEXT_HANDLE_POSITION_SELECTION_START,
- GTK_TEXT_HANDLE_POSITION_SELECTION_END = GTK_TEXT_HANDLE_POSITION_CURSOR
-} GtkTextHandlePosition;
-
-typedef enum
-{
- GTK_TEXT_HANDLE_MODE_NONE,
- GTK_TEXT_HANDLE_MODE_CURSOR,
- GTK_TEXT_HANDLE_MODE_SELECTION
-} GtkTextHandleMode;
-
-struct _GtkTextHandle
-{
- GObject parent_instance;
- gpointer priv;
-};
-
-struct _GtkTextHandleClass
-{
- GObjectClass parent_class;
-
- void (* handle_dragged) (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- gint x,
- gint y);
- void (* drag_finished) (GtkTextHandle *handle,
- GtkTextHandlePosition pos);
-};
+ GTK_TEXT_HANDLE_ROLE_CURSOR,
+ GTK_TEXT_HANDLE_ROLE_SELECTION_START,
+ GTK_TEXT_HANDLE_ROLE_SELECTION_END,
+} GtkTextHandleRole;
-GType _gtk_text_handle_get_type (void) G_GNUC_CONST;
+GtkTextHandle * gtk_text_handle_new (GtkWidget *parent);
-GtkTextHandle * _gtk_text_handle_new (GtkWidget *parent);
+void gtk_text_handle_set_role (GtkTextHandle *handle,
+ GtkTextHandleRole role);
+GtkTextHandleRole gtk_text_handle_get_role (GtkTextHandle *handle);
-void _gtk_text_handle_set_mode (GtkTextHandle *handle,
- GtkTextHandleMode mode);
-GtkTextHandleMode
- _gtk_text_handle_get_mode (GtkTextHandle *handle);
-void _gtk_text_handle_set_position (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GdkRectangle *rect);
-void _gtk_text_handle_set_visible (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- gboolean visible);
+void gtk_text_handle_set_position (GtkTextHandle *handle,
+ const GdkRectangle *rect);
-gboolean _gtk_text_handle_get_is_dragged (GtkTextHandle *handle,
- GtkTextHandlePosition pos);
-void _gtk_text_handle_set_direction (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GtkTextDirection dir);
+gboolean gtk_text_handle_get_is_dragged (GtkTextHandle *handle);
G_END_DECLS
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index d80a94eee7..9e646217f1 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -148,6 +148,13 @@
typedef struct _GtkTextWindow GtkTextWindow;
typedef struct _GtkTextPendingScroll GtkTextPendingScroll;
+enum
+{
+ TEXT_HANDLE_CURSOR,
+ TEXT_HANDLE_SELECTION_BOUND,
+ TEXT_HANDLE_N_HANDLES
+};
+
struct _GtkTextViewPrivate
{
GtkTextLayout *layout;
@@ -160,7 +167,7 @@ struct _GtkTextViewPrivate
gint dnd_x;
gint dnd_y;
- GtkTextHandle *text_handle;
+ GtkTextHandle *text_handles[TEXT_HANDLE_N_HANDLES];
GtkWidget *selection_bubble;
guint selection_bubble_timeout_id;
@@ -272,6 +279,8 @@ struct _GtkTextViewPrivate
guint scroll_after_paste : 1;
+ guint text_handles_enabled : 1;
+
/* GtkScrollablePolicy needs to be checked when
* driving the scrollable adjustment values */
guint hscroll_policy : 1;
@@ -565,18 +574,14 @@ static void update_node_ordering (GtkWidget *widget);
/* GtkTextHandle handlers */
static void gtk_text_view_handle_drag_started (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
GtkTextView *text_view);
static void gtk_text_view_handle_dragged (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
gint x,
gint y,
GtkTextView *text_view);
static void gtk_text_view_handle_drag_finished (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
GtkTextView *text_view);
-static void gtk_text_view_update_handles (GtkTextView *text_view,
- GtkTextHandleMode mode);
+static void gtk_text_view_update_handles (GtkTextView *text_view);
static void gtk_text_view_selection_bubble_popup_unset (GtkTextView *text_view);
static void gtk_text_view_selection_bubble_popup_set (GtkTextView *text_view);
@@ -1607,6 +1612,24 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
gtk_text_view_activate_misc_insert_emoji);
}
+static void
+_gtk_text_view_create_text_handles (GtkTextView *text_view)
+{
+ GtkTextViewPrivate *priv = text_view->priv;
+ int i;
+
+ for (i = 0; i < TEXT_HANDLE_N_HANDLES; i++)
+ {
+ priv->text_handles[i] = gtk_text_handle_new (GTK_WIDGET (text_view));
+ g_signal_connect (priv->text_handles[i], "drag-started",
+ G_CALLBACK (gtk_text_view_handle_drag_started), text_view);
+ g_signal_connect (priv->text_handles[i], "handle-dragged",
+ G_CALLBACK (gtk_text_view_handle_dragged), text_view);
+ g_signal_connect (priv->text_handles[i], "drag-finished",
+ G_CALLBACK (gtk_text_view_handle_drag_finished), text_view);
+ }
+}
+
static void
gtk_text_view_init (GtkTextView *text_view)
{
@@ -1715,6 +1738,8 @@ gtk_text_view_init (GtkTextView *text_view)
gtk_widget_action_set_enabled (GTK_WIDGET (text_view), "text.can-redo", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (text_view), "text.can-undo", FALSE);
+
+ _gtk_text_view_create_text_handles (text_view);
}
GtkCssNode *
@@ -1729,23 +1754,6 @@ gtk_text_view_get_selection_node (GtkTextView *text_view)
return text_view->priv->selection_node;
}
-static void
-_gtk_text_view_ensure_text_handles (GtkTextView *text_view)
-{
- GtkTextViewPrivate *priv = text_view->priv;
-
- if (priv->text_handle)
- return;
-
- priv->text_handle = _gtk_text_handle_new (GTK_WIDGET (text_view));
- g_signal_connect (priv->text_handle, "drag-started",
- G_CALLBACK (gtk_text_view_handle_drag_started), text_view);
- g_signal_connect (priv->text_handle, "handle-dragged",
- G_CALLBACK (gtk_text_view_handle_dragged), text_view);
- g_signal_connect (priv->text_handle, "drag-finished",
- G_CALLBACK (gtk_text_view_handle_drag_finished), text_view);
-}
-
static void
_gtk_text_view_ensure_magnifier (GtkTextView *text_view)
{
@@ -1924,8 +1932,7 @@ gtk_text_view_set_buffer (GtkTextView *text_view,
gtk_text_buffer_add_selection_clipboard (priv->buffer, clipboard);
}
- if (priv->text_handle)
- gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_NONE);
+ gtk_text_view_update_handles (text_view);
gtk_widget_action_set_enabled (GTK_WIDGET (text_view), "text.undo", can_undo);
gtk_widget_action_set_enabled (GTK_WIDGET (text_view), "text.redo", can_redo);
@@ -2550,9 +2557,7 @@ gtk_text_view_flush_scroll (GtkTextView *text_view)
scroll->yalign,
TRUE);
- if (text_view->priv->text_handle)
- gtk_text_view_update_handles (text_view,
- _gtk_text_handle_get_mode (text_view->priv->text_handle));
+ gtk_text_view_update_handles (text_view);
free_pending_scroll (scroll);
@@ -3632,8 +3637,8 @@ gtk_text_view_finalize (GObject *object)
if (priv->magnifier_popover)
gtk_widget_destroy (priv->magnifier_popover);
- if (priv->text_handle)
- g_object_unref (priv->text_handle);
+ g_clear_object (&priv->text_handles[TEXT_HANDLE_CURSOR]);
+ g_clear_object (&priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]);
g_object_unref (priv->im_context);
g_free (priv->im_module);
@@ -4323,6 +4328,12 @@ gtk_text_view_size_allocate (GtkWidget *widget,
if (priv->popup_menu)
gtk_native_check_resize (GTK_NATIVE (priv->popup_menu));
+
+ if (priv->text_handles[TEXT_HANDLE_CURSOR])
+ gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_CURSOR]));
+
+ if (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])
+ gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
}
static void
@@ -4755,9 +4766,9 @@ _widget_to_text_surface_coords (GtkTextView *text_view,
}
static void
-gtk_text_view_set_handle_position (GtkTextView *text_view,
- GtkTextIter *iter,
- GtkTextHandlePosition pos)
+gtk_text_view_set_handle_position (GtkTextView *text_view,
+ GtkTextHandle *handle,
+ GtkTextIter *iter)
{
GtkTextViewPrivate *priv;
GdkRectangle rect;
@@ -4769,32 +4780,32 @@ gtk_text_view_set_handle_position (GtkTextView *text_view,
x = rect.x - priv->xoffset;
y = rect.y - priv->yoffset;
- if (!_gtk_text_handle_get_is_dragged (priv->text_handle, pos) &&
+ if (!gtk_text_handle_get_is_dragged (handle) &&
(x < 0 || x > SCREEN_WIDTH (text_view) ||
y < 0 || y > SCREEN_HEIGHT (text_view)))
{
/* Hide the handle if it's not being manipulated
* and fell outside of the visible text area.
*/
- _gtk_text_handle_set_visible (priv->text_handle, pos, FALSE);
+ gtk_widget_hide (GTK_WIDGET (handle));
}
else
{
GtkTextDirection dir = GTK_TEXT_DIR_LTR;
GtkTextAttributes attributes = { 0 };
- _gtk_text_handle_set_visible (priv->text_handle, pos, TRUE);
+ gtk_widget_show (GTK_WIDGET (handle));
rect.x = CLAMP (x, 0, SCREEN_WIDTH (text_view));
rect.y = CLAMP (y, 0, SCREEN_HEIGHT (text_view));
_text_window_to_widget_coords (text_view, &rect.x, &rect.y);
- _gtk_text_handle_set_position (priv->text_handle, pos, &rect);
+ gtk_text_handle_set_position (handle, &rect);
if (gtk_text_iter_get_attributes (iter, &attributes))
dir = attributes.direction;
- _gtk_text_handle_set_direction (priv->text_handle, pos, dir);
+ gtk_widget_set_direction (GTK_WIDGET (handle), dir);
}
}
@@ -4843,23 +4854,17 @@ gtk_text_view_show_magnifier (GtkTextView *text_view,
}
static void
-gtk_text_view_handle_dragged (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- gint x,
- gint y,
- GtkTextView *text_view)
+gtk_text_view_handle_dragged (GtkTextHandle *handle,
+ gint x,
+ gint y,
+ GtkTextView *text_view)
{
GtkTextViewPrivate *priv;
- GtkTextIter old_cursor, old_bound;
- GtkTextIter cursor, bound, iter;
- GtkTextIter *min, *max;
- GtkTextHandleMode mode;
+ GtkTextIter cursor, bound, iter, *old_iter;
GtkTextBuffer *buffer;
- GtkTextHandlePosition cursor_pos;
priv = text_view->priv;
buffer = get_buffer (text_view);
- mode = _gtk_text_handle_get_mode (handle);
_widget_to_text_surface_coords (text_view, &x, &y);
@@ -4867,93 +4872,81 @@ gtk_text_view_handle_dragged (GtkTextHandle *handle,
gtk_text_layout_get_iter_at_pixel (priv->layout, &iter,
x + priv->xoffset,
y + priv->yoffset);
- gtk_text_buffer_get_iter_at_mark (buffer, &old_cursor,
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &cursor,
gtk_text_buffer_get_insert (buffer));
- gtk_text_buffer_get_iter_at_mark (buffer, &old_bound,
+ gtk_text_buffer_get_iter_at_mark (buffer, &bound,
gtk_text_buffer_get_selection_bound (buffer));
- cursor = old_cursor;
- bound = old_bound;
- if (mode == GTK_TEXT_HANDLE_MODE_CURSOR ||
- gtk_text_iter_compare (&cursor, &bound) >= 0)
- {
- cursor_pos = GTK_TEXT_HANDLE_POSITION_CURSOR;
- max = &cursor;
- min = &bound;
- }
- else
- {
- cursor_pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
- max = &bound;
- min = &cursor;
- }
- if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
+ if (handle == priv->text_handles[TEXT_HANDLE_CURSOR])
{
- if (mode == GTK_TEXT_HANDLE_MODE_SELECTION &&
- gtk_text_iter_compare (&iter, min) <= 0)
+ /* Avoid running past the other handle in selection mode */
+ if (gtk_text_iter_compare (&iter, &bound) >= 0 &&
+ gtk_widget_is_visible (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])))
{
- iter = *min;
- gtk_text_iter_forward_char (&iter);
+ iter = bound;
+ gtk_text_iter_backward_char (&iter);
}
- *max = iter;
- gtk_text_view_set_handle_position (text_view, &iter, pos);
+ old_iter = &cursor;
+ gtk_text_view_set_handle_position (text_view, handle, &iter);
}
- else
+ else if (handle == priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])
{
- if (mode == GTK_TEXT_HANDLE_MODE_SELECTION &&
- gtk_text_iter_compare (&iter, max) >= 0)
+ /* Avoid running past the other handle */
+ if (gtk_text_iter_compare (&iter, &cursor) <= 0)
{
- iter = *max;
- gtk_text_iter_backward_char (&iter);
+ iter = cursor;
+ gtk_text_iter_forward_char (&iter);
}
- *min = iter;
- gtk_text_view_set_handle_position (text_view, &iter, pos);
+ old_iter = &bound;
+ gtk_text_view_set_handle_position (text_view, handle, &iter);
}
+ else
+ g_assert_not_reached ();
- if (gtk_text_iter_compare (&old_cursor, &cursor) != 0 ||
- gtk_text_iter_compare (&old_bound, &bound) != 0)
+ if (gtk_text_iter_compare (&iter, old_iter) != 0)
{
- if (mode == GTK_TEXT_HANDLE_MODE_CURSOR)
+ *old_iter = iter;
+
+ if (handle == priv->text_handles[TEXT_HANDLE_CURSOR] &&
+ !gtk_widget_is_visible (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])))
gtk_text_buffer_place_cursor (buffer, &cursor);
else
gtk_text_buffer_select_range (buffer, &cursor, &bound);
- if (_gtk_text_handle_get_is_dragged (priv->text_handle, cursor_pos))
+ if (handle == priv->text_handles[TEXT_HANDLE_CURSOR])
{
text_view->priv->cursor_handle_dragged = TRUE;
gtk_text_view_scroll_mark_onscreen (text_view,
gtk_text_buffer_get_insert (buffer));
}
- else
+ else if (handle == priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])
{
text_view->priv->selection_handle_dragged = TRUE;
gtk_text_view_scroll_mark_onscreen (text_view,
gtk_text_buffer_get_selection_bound (buffer));
}
+
+ gtk_text_view_update_handles (text_view);
}
- if (_gtk_text_handle_get_is_dragged (priv->text_handle, cursor_pos))
- gtk_text_view_show_magnifier (text_view, &cursor, x, y);
- else
- gtk_text_view_show_magnifier (text_view, &bound, x, y);
+ gtk_text_view_show_magnifier (text_view, &iter, x, y);
}
static void
-gtk_text_view_handle_drag_started (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GtkTextView *text_view)
+gtk_text_view_handle_drag_started (GtkTextHandle *handle,
+ GtkTextView *text_view)
{
text_view->priv->cursor_handle_dragged = FALSE;
text_view->priv->selection_handle_dragged = FALSE;
}
static void
-gtk_text_view_handle_drag_finished (GtkTextHandle *handle,
- GtkTextHandlePosition pos,
- GtkTextView *text_view)
+gtk_text_view_handle_drag_finished (GtkTextHandle *handle,
+ GtkTextView *text_view)
{
GtkTextViewPrivate *priv = text_view->priv;
@@ -4974,7 +4967,7 @@ gtk_text_view_handle_drag_finished (GtkTextHandle *handle,
extend_selection (text_view, SELECT_WORDS, &cursor, &start, &end);
gtk_text_buffer_select_range (buffer, &start, &end);
- gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_SELECTION);
+ gtk_text_view_update_handles (text_view);
}
else
gtk_text_view_selection_bubble_popup_set (text_view);
@@ -4987,52 +4980,61 @@ gtk_text_view_handle_drag_finished (GtkTextHandle *handle,
static gboolean cursor_visible (GtkTextView *text_view);
static void
-gtk_text_view_update_handles (GtkTextView *text_view,
- GtkTextHandleMode mode)
+gtk_text_view_update_handles (GtkTextView *text_view)
{
GtkTextViewPrivate *priv = text_view->priv;
- GtkTextIter cursor, bound, min, max;
+ GtkTextIter cursor, bound;
GtkTextBuffer *buffer;
- buffer = get_buffer (text_view);
-
- gtk_text_buffer_get_iter_at_mark (buffer, &cursor,
- gtk_text_buffer_get_insert (buffer));
- gtk_text_buffer_get_iter_at_mark (buffer, &bound,
- gtk_text_buffer_get_selection_bound (buffer));
-
- if (mode == GTK_TEXT_HANDLE_MODE_SELECTION &&
- gtk_text_iter_compare (&cursor, &bound) == 0)
- {
- mode = GTK_TEXT_HANDLE_MODE_CURSOR;
- }
-
- if (mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
- (!gtk_widget_is_sensitive (GTK_WIDGET (text_view)) || !cursor_visible (text_view)))
+ if (!priv->text_handles_enabled)
{
- mode = GTK_TEXT_HANDLE_MODE_NONE;
- }
-
- _gtk_text_handle_set_mode (priv->text_handle, mode);
-
- if (gtk_text_iter_compare (&cursor, &bound) >= 0)
- {
- min = bound;
- max = cursor;
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_CURSOR]));
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
}
else
{
- min = cursor;
- max = bound;
- }
+ buffer = get_buffer (text_view);
- if (mode != GTK_TEXT_HANDLE_MODE_NONE)
- gtk_text_view_set_handle_position (text_view, &max,
- GTK_TEXT_HANDLE_POSITION_SELECTION_END);
+ gtk_text_buffer_get_iter_at_mark (buffer, &cursor,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_buffer_get_iter_at_mark (buffer, &bound,
+ gtk_text_buffer_get_selection_bound (buffer));
- if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
- gtk_text_view_set_handle_position (text_view, &min,
- GTK_TEXT_HANDLE_POSITION_SELECTION_START);
+ if (gtk_text_iter_compare (&cursor, &bound) == 0 && priv->editable)
+ {
+ /* Cursor mode */
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
+
+ gtk_text_view_set_handle_position (text_view,
+ priv->text_handles[TEXT_HANDLE_CURSOR],
+ &cursor);
+ gtk_text_handle_set_role (priv->text_handles[TEXT_HANDLE_CURSOR],
+ GTK_TEXT_HANDLE_ROLE_CURSOR);
+ gtk_widget_show (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_CURSOR]));
+ }
+ else if (gtk_text_iter_compare (&cursor, &bound) != 0)
+ {
+ /* Selection mode */
+ gtk_text_view_set_handle_position (text_view,
+ priv->text_handles[TEXT_HANDLE_CURSOR],
+ &cursor);
+ gtk_text_handle_set_role (priv->text_handles[TEXT_HANDLE_CURSOR],
+ GTK_TEXT_HANDLE_ROLE_SELECTION_START);
+ gtk_widget_show (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_CURSOR]));
+
+ gtk_text_view_set_handle_position (text_view,
+ priv->text_handles[TEXT_HANDLE_SELECTION_BOUND],
+ &bound);
+ gtk_text_handle_set_role (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND],
+ GTK_TEXT_HANDLE_ROLE_SELECTION_END);
+ gtk_widget_show (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_CURSOR]));
+ gtk_widget_hide (GTK_WIDGET (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]));
+ }
+ }
}
static gboolean
@@ -5094,9 +5096,8 @@ gtk_text_view_key_controller_key_pressed (GtkEventControllerKey *controller,
gtk_text_view_reset_blink_time (text_view);
gtk_text_view_pend_cursor_blink (text_view);
- if (priv->text_handle)
- _gtk_text_handle_set_mode (priv->text_handle,
- GTK_TEXT_HANDLE_MODE_NONE);
+ text_view->priv->text_handles_enabled = FALSE;
+ gtk_text_view_update_handles (text_view);
gtk_text_view_selection_bubble_popup_unset (text_view);
@@ -5207,7 +5208,6 @@ gtk_text_view_click_gesture_pressed (GtkGestureClick *gesture,
}
else if (button == GDK_BUTTON_PRIMARY)
{
- GtkTextHandleMode handle_mode = GTK_TEXT_HANDLE_MODE_NONE;
gboolean extends = FALSE;
GdkModifierType state;
@@ -5227,8 +5227,7 @@ gtk_text_view_click_gesture_pressed (GtkGestureClick *gesture,
*/
GtkTextIter start, end;
- if (is_touchscreen)
- handle_mode = GTK_TEXT_HANDLE_MODE_CURSOR;
+ priv->text_handles_enabled = is_touchscreen;
get_iter_from_gesture (text_view, GTK_GESTURE (gesture),
&iter, NULL, NULL);
@@ -5243,12 +5242,11 @@ gtk_text_view_click_gesture_pressed (GtkGestureClick *gesture,
!gtk_widget_get_visible (priv->selection_bubble))
{
gtk_text_view_selection_bubble_popup_set (text_view);
- handle_mode = GTK_TEXT_HANDLE_MODE_NONE;
+ priv->text_handles_enabled = FALSE;
}
else
{
gtk_text_view_selection_bubble_popup_unset (text_view);
- handle_mode = GTK_TEXT_HANDLE_MODE_SELECTION;
}
}
else
@@ -5278,11 +5276,6 @@ gtk_text_view_click_gesture_pressed (GtkGestureClick *gesture,
}
case 2:
case 3:
- if (is_touchscreen)
- {
- handle_mode = GTK_TEXT_HANDLE_MODE_SELECTION;
- break;
- }
gtk_text_view_end_selection_drag (text_view);
get_iter_from_gesture (text_view, GTK_GESTURE (gesture),
@@ -5295,8 +5288,7 @@ gtk_text_view_click_gesture_pressed (GtkGestureClick *gesture,
break;
}
- _gtk_text_view_ensure_text_handles (text_view);
- gtk_text_view_update_handles (text_view, handle_mode);
+ gtk_text_view_update_handles (text_view);
}
if (n_press >= 3)
@@ -5363,9 +5355,8 @@ gtk_text_view_focus_out (GtkWidget *widget)
text_view);
gtk_text_view_selection_bubble_popup_unset (text_view);
- if (priv->text_handle)
- _gtk_text_handle_set_mode (priv->text_handle,
- GTK_TEXT_HANDLE_MODE_NONE);
+ text_view->priv->text_handles_enabled = FALSE;
+ gtk_text_view_update_handles (text_view);
if (priv->editable)
{
@@ -6735,11 +6726,8 @@ gtk_text_view_buffer_changed_handler (GtkTextBuffer *buffer,
gpointer data)
{
GtkTextView *text_view = data;
- GtkTextViewPrivate *priv = text_view->priv;
- if (priv->text_handle)
- gtk_text_view_update_handles (text_view,
- _gtk_text_handle_get_mode (priv->text_handle));
+ gtk_text_view_update_handles (text_view);
}
static void
@@ -7237,8 +7225,8 @@ gtk_text_view_drag_gesture_update (GtkGestureDrag *gesture,
if (is_touchscreen)
{
- _gtk_text_view_ensure_text_handles (text_view);
- gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_SELECTION);
+ text_view->priv->text_handles_enabled = TRUE;
+ gtk_text_view_update_handles (text_view);
gtk_text_view_show_magnifier (text_view, &cursor, x, y);
}
}
@@ -7287,7 +7275,6 @@ gtk_text_view_drag_gesture_end (GtkGestureDrag *gesture,
if (!is_touchscreen && clicked_in_selection &&
!gtk_drag_check_threshold (GTK_WIDGET (text_view), start_x, start_y, x, y))
{
- GtkTextHandleMode mode = GTK_TEXT_HANDLE_MODE_NONE;
GtkTextIter iter;
/* Unselect everything; we clicked inside selection, but
@@ -7300,13 +7287,7 @@ gtk_text_view_drag_gesture_end (GtkGestureDrag *gesture,
gtk_text_buffer_place_cursor (get_buffer (text_view), &iter);
gtk_text_view_check_cursor_blink (text_view);
- if (priv->text_handle)
- {
- if (is_touchscreen)
- mode = GTK_TEXT_HANDLE_MODE_CURSOR;
-
- gtk_text_view_update_handles (text_view, mode);
- }
+ gtk_text_view_update_handles (text_view);
}
}
@@ -8145,9 +8126,7 @@ gtk_text_view_value_changed (GtkAdjustment *adjustment,
*/
gtk_text_view_update_im_spot_location (text_view);
- if (priv->text_handle)
- gtk_text_view_update_handles (text_view,
- _gtk_text_handle_get_mode (priv->text_handle));
+ gtk_text_view_update_handles (text_view);
if (priv->anchored_children.length > 0)
gtk_widget_queue_allocate (GTK_WIDGET (text_view));
@@ -8336,9 +8315,7 @@ gtk_text_view_mark_set_handler (GtkTextBuffer *buffer,
if (need_reset)
{
gtk_text_view_reset_im_context (text_view);
- if (text_view->priv->text_handle)
- gtk_text_view_update_handles (text_view,
- _gtk_text_handle_get_mode (text_view->priv->text_handle));
+ gtk_text_view_update_handles (text_view);
has_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view), NULL, NULL);
gtk_css_node_set_visible (text_view->priv->selection_node, has_selection);
@@ -8748,21 +8725,10 @@ show_or_hide_handles (GtkWidget *popover,
GtkTextView *text_view)
{
gboolean visible;
- GtkTextHandle *handle;
- GtkTextHandleMode mode;
visible = gtk_widget_get_visible (popover);
-
- handle = text_view->priv->text_handle;
- mode = _gtk_text_handle_get_mode (handle);
-
- if (!visible)
- gtk_text_view_update_handles (text_view, mode);
- else
- {
- _gtk_text_handle_set_visible (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, FALSE);
- _gtk_text_handle_set_visible (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, FALSE);
- }
+ text_view->priv->text_handles_enabled = !visible;
+ gtk_text_view_update_handles (text_view);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]