summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2021-11-08 08:27:52 +0100
committerMike Kaganski <mike.kaganski@collabora.com>2021-11-09 10:05:16 +0100
commitb8e0b887efb35b0afd85b81349d5f8e2f7d1c359 (patch)
tree97894f073302c5a23986039d3eca1f0af7738589
parentc274eeaa46206a42b3356d18f7a0d6dc5fb92cda (diff)
sw: try grouping undo actions of IME-edited text
This is a problem since commit e7760d428bc82ccfcae14f1907b78f9f1013b88c (Fix tdf#87500 - Freeze with English/Japanese mixture undo., 2015-09-08), that started not grouping IME-edited text completely. This means that in case you go via SwEditWin::Command() instead of SwEditWin::KeyInput() to type a 4 characters word, then it'll create 4 undo actions. Fix the problem by tracking who was the last caller of sw::DocumentContentOperationsManager::InsertString(), so we can only disable grouping switching between IME and non-IME, and we can have grouping for a series of IME input. (cherry picked from commit 6680e51716e383c68bb1ec9cc0a05d698d3b6a3d) Change-Id: I31bd02db4fe653ab63e41a77c75b8bebfc749ff1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124834 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sw/inc/IDocumentContentOperations.hxx6
-rw-r--r--sw/qa/core/doc/doc.cxx32
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx10
-rw-r--r--sw/source/core/doc/extinput.cxx12
-rw-r--r--sw/source/core/edit/editsh.cxx1
-rw-r--r--sw/source/core/inc/DocumentContentOperationsManager.hxx6
6 files changed, 65 insertions, 2 deletions
diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx
index 14724eae3731..d9a6a8b518e9 100644
--- a/sw/inc/IDocumentContentOperations.hxx
+++ b/sw/inc/IDocumentContentOperations.hxx
@@ -163,6 +163,12 @@ public:
virtual bool InsertString(const SwPaM &rRg, const OUString&,
const SwInsertFlags nInsertMode = SwInsertFlags::EMPTYEXPAND ) = 0;
+ /// States that the last inserted string came from IME.
+ virtual void SetIME(bool bIME) = 0;
+
+ /// Did the last inserted string come from IME?
+ virtual bool GetIME() const = 0;
+
/** change text to Upper/Lower/Hiragana/Katakana/...
*/
virtual void TransliterateText(const SwPaM& rPaM, utl::TransliterationWrapper&) = 0;
diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index 14f724328fe0..bda78bda8e48 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -18,6 +18,7 @@
#include <editeng/langitem.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/dispatch.hxx>
+#include <vcl/scheduler.hxx>
#include <wrtsh.hxx>
#include <fmtanchr.hxx>
@@ -29,6 +30,7 @@
#include <swdtflvr.hxx>
#include <cmdid.h>
#include <unotxdoc.hxx>
+#include <UndoManager.hxx>
char const DATA_DIRECTORY[] = "/sw/qa/core/doc/data/";
@@ -165,6 +167,36 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testTextBoxMakeFlyFrame)
assertXPath(pLayout, "/root/page/body/txt/anchored/fly", 1);
}
+CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testIMEGrouping)
+{
+// TODO figure out why the ext text input in this test code reaches the wrong window on
+// non-headless.
+#if !defined MACOSX && !defined _WIN32
+ // Given an empty document:
+ SwDoc* pDoc = createSwDoc();
+ // Make sure no idle is in action, so the ExtTextInput events go to SwEditWin.
+ Scheduler::ProcessEventsToIdle();
+
+ // When pressing two keys via IME:
+ SwDocShell* pDocShell = pDoc->GetDocShell();
+ SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin();
+ rEditWin.PostExtTextInputEvent(VclEventId::ExtTextInput, "a");
+ rEditWin.PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+ rEditWin.PostExtTextInputEvent(VclEventId::ExtTextInput, "b");
+ rEditWin.PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ // Then make sure that gets grouped together to a single undo action:
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ SwTextNode* pTextNode = pWrtShell->GetCursor()->GetNode().GetTextNode();
+ CPPUNIT_ASSERT_EQUAL(OUString("ab"), pTextNode->GetText());
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : 2
+ // i.e. 2 subsequent IME events got their own undo actions.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pDoc->GetUndoManager().GetUndoActionCount());
+#endif
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index aefd7feb881e..c3251b6232f2 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -2818,6 +2818,16 @@ bool DocumentContentOperationsManager::InsertString( const SwPaM &rRg, const OUS
return true;
}
+void DocumentContentOperationsManager::SetIME(bool bIME)
+{
+ m_bIME = bIME;
+}
+
+bool DocumentContentOperationsManager::GetIME() const
+{
+ return m_bIME;
+}
+
void DocumentContentOperationsManager::TransliterateText(
const SwPaM& rPaM,
utl::TransliterationWrapper& rTrans )
diff --git a/sw/source/core/doc/extinput.cxx b/sw/source/core/doc/extinput.cxx
index 09f4dba1e016..500f5d157b6c 100644
--- a/sw/source/core/doc/extinput.cxx
+++ b/sw/source/core/doc/extinput.cxx
@@ -61,7 +61,12 @@ SwExtTextInput::~SwExtTextInput()
// Prevent IME edited text being grouped with non-IME edited text.
bool bKeepGroupUndo = rDoc.GetIDocumentUndoRedo().DoesGroupUndo();
- rDoc.GetIDocumentUndoRedo().DoGroupUndo(false);
+ bool bWasIME = rDoc.GetIDocumentUndoRedo().GetUndoActionCount() == 0 || rDoc.getIDocumentContentOperations().GetIME();
+ if (!bWasIME)
+ {
+ rDoc.GetIDocumentUndoRedo().DoGroupUndo(false);
+ }
+ rDoc.getIDocumentContentOperations().SetIME(true);
if( nEndCnt < nSttCnt )
{
std::swap(nSttCnt, nEndCnt);
@@ -119,7 +124,10 @@ SwExtTextInput::~SwExtTextInput()
pTNd->EraseText( rIdx, nLenghtOfOldString );
}
- rDoc.GetIDocumentUndoRedo().DoGroupUndo(bKeepGroupUndo);
+ if (!bWasIME)
+ {
+ rDoc.GetIDocumentUndoRedo().DoGroupUndo(bKeepGroupUndo);
+ }
if (m_eInputLanguage == LANGUAGE_DONTKNOW)
return;
diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index 85c065d60fed..967ce1f2e203 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -88,6 +88,7 @@ void SwEditShell::Insert2(const OUString &rStr, const bool bForceExpandHints )
for(SwPaM& rCurrentCursor : getShellCursor( true )->GetRingContainer())
{
//OPT: GetSystemCharSet
+ GetDoc()->getIDocumentContentOperations().SetIME(false);
const bool bSuccess =
GetDoc()->getIDocumentContentOperations().InsertString(rCurrentCursor, rStr, nInsertFlags);
OSL_ENSURE( bSuccess, "Doc->Insert() failed." );
diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx
index 3df39532978c..ab5d260bce7f 100644
--- a/sw/source/core/inc/DocumentContentOperationsManager.hxx
+++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx
@@ -61,6 +61,10 @@ public:
bool InsertString(const SwPaM &rRg, const OUString&,
const SwInsertFlags nInsertMode = SwInsertFlags::EMPTYEXPAND ) override;
+ void SetIME(bool bIME) override;
+
+ bool GetIME() const override;
+
void TransliterateText(const SwPaM& rPaM, utl::TransliterationWrapper&) override;
SwFlyFrameFormat* InsertGraphic(const SwPaM &rRg, const OUString& rGrfName, const OUString& rFltName, const Graphic* pGraphic,
@@ -159,6 +163,8 @@ public:
private:
SwDoc& m_rDoc;
+ bool m_bIME = false;
+
bool DeleteAndJoinImpl(SwPaM&, const bool);
bool DeleteAndJoinWithRedlineImpl(SwPaM&, const bool unused = false);
bool DeleteRangeImpl(SwPaM&, const bool unused = false);