summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-09-24 12:36:30 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-09-24 12:36:30 +0000
commite41bf097d01011521f0235ab5f401f88fb188f39 (patch)
tree4c701852871e2e89366683082ca3fb191145c22c
parent7a82e9f557dc8cf65ccb4875c8f501c4d8c43a3e (diff)
parent659393049e640145979c73dddd19acc1ca4b5e14 (diff)
downloadgtk+-e41bf097d01011521f0235ab5f401f88fb188f39.tar.gz
Merge branch 'wip/chergert/undo-fixes' into 'master'
texthistory: add barriers after final grouping Closes #4276 See merge request GNOME/gtk!3989
-rw-r--r--gtk/gtktexthistory.c6
-rw-r--r--gtk/gtktextview.c25
-rw-r--r--testsuite/gtk/texthistory.c18
3 files changed, 44 insertions, 5 deletions
diff --git a/gtk/gtktexthistory.c b/gtk/gtktexthistory.c
index 61ccc33f08..3b9379ccc3 100644
--- a/gtk/gtktexthistory.c
+++ b/gtk/gtktexthistory.c
@@ -224,6 +224,12 @@ action_chain (Action *action,
if (other->kind == ACTION_KIND_BARRIER)
{
+ /* If we're not in a user action, this barrier is meant to
+ * stop items from coallescing into this group.
+ */
+ if (!in_user_action && action->u.group.depth == 0)
+ return FALSE;
+
action_free (other);
return TRUE;
}
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 2e930f756e..3f7e6cb4fe 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -8439,17 +8439,32 @@ gtk_text_view_commit_text (GtkTextView *text_view,
{
GtkTextViewPrivate *priv;
gboolean had_selection;
+ GtkTextIter begin, end;
+ guint length;
priv = text_view->priv;
gtk_text_view_obscure_mouse_cursor (text_view);
gtk_text_buffer_begin_user_action (get_buffer (text_view));
- had_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
- NULL, NULL);
-
- gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE,
- priv->editable);
+ had_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view), &begin, &end);
+ gtk_text_iter_order (&begin, &end);
+ length = gtk_text_iter_get_offset (&end) - gtk_text_iter_get_offset (&begin);
+
+ if (gtk_text_buffer_delete_selection (get_buffer (text_view), TRUE, priv->editable))
+ {
+ /* If something was deleted, create a second group for the insert. This
+ * ensures that there are two undo operations. One for the deletion, and
+ * one for the insertion of new text. However, if there is only a single
+ * character overwritten, that isn't very useful, just keep the single
+ * undo group.
+ */
+ if (length > 1)
+ {
+ gtk_text_buffer_end_user_action (get_buffer (text_view));
+ gtk_text_buffer_begin_user_action (get_buffer (text_view));
+ }
+ }
if (!strcmp (str, "\n"))
{
diff --git a/testsuite/gtk/texthistory.c b/testsuite/gtk/texthistory.c
index cca4008196..a740d3523b 100644
--- a/testsuite/gtk/texthistory.c
+++ b/testsuite/gtk/texthistory.c
@@ -606,6 +606,23 @@ test14 (void)
g_free (fill_after_2);
}
+static void
+test_issue_4276 (void)
+{
+ const Command commands[] = {
+ { INSERT, 0, -1, "this is some text", "this is some text", SET, UNSET, UNSET },
+ { SELECT, 0, 17, NULL, "this is some text", SET, UNSET, UNSET },
+ { BEGIN_USER, -1, -1, NULL, NULL, UNSET, UNSET, UNSET },
+ { DELETE_KEY, 0, 17, "this is some text", "", UNSET, UNSET, UNSET },
+ { INSERT, 0, -1, "z", "z", UNSET, UNSET, UNSET },
+ { END_USER, -1, -1, NULL, NULL, SET, UNSET, UNSET },
+ { INSERT, 1, -1, "zzz", "zzzz", SET, UNSET, UNSET },
+ { UNDO, -1, -1, NULL, "z", SET, SET, UNSET },
+ };
+
+ run_test (commands, G_N_ELEMENTS (commands), 0);
+}
+
int
main (int argc,
char *argv[])
@@ -626,6 +643,7 @@ main (int argc,
g_test_add_func ("/Gtk/TextHistory/test12", test12);
g_test_add_func ("/Gtk/TextHistory/test13", test13);
g_test_add_func ("/Gtk/TextHistory/test14", test14);
+ g_test_add_func ("/Gtk/TextHistory/issue_4276", test_issue_4276);
return g_test_run ();
}