diff options
author | Matthias Clasen <mclasen@redhat.com> | 2021-09-24 12:36:30 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2021-09-24 12:36:30 +0000 |
commit | e41bf097d01011521f0235ab5f401f88fb188f39 (patch) | |
tree | 4c701852871e2e89366683082ca3fb191145c22c | |
parent | 7a82e9f557dc8cf65ccb4875c8f501c4d8c43a3e (diff) | |
parent | 659393049e640145979c73dddd19acc1ca4b5e14 (diff) | |
download | gtk+-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.c | 6 | ||||
-rw-r--r-- | gtk/gtktextview.c | 25 | ||||
-rw-r--r-- | testsuite/gtk/texthistory.c | 18 |
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 (); } |