diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2021-11-08 08:27:52 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2021-11-08 09:20:45 +0100 |
commit | 6680e51716e383c68bb1ec9cc0a05d698d3b6a3d (patch) | |
tree | 23340a5bd1e0c990aede7f725502b41df25a0641 /sw | |
parent | 033aea780cc8315979b6de2692f5f7aeb6a0e99b (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.
Change-Id: I31bd02db4fe653ab63e41a77c75b8bebfc749ff1
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124766
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/IDocumentContentOperations.hxx | 6 | ||||
-rw-r--r-- | sw/qa/core/doc/doc.cxx | 32 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentContentOperationsManager.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/doc/extinput.cxx | 12 | ||||
-rw-r--r-- | sw/source/core/edit/editsh.cxx | 1 | ||||
-rw-r--r-- | sw/source/core/inc/DocumentContentOperationsManager.hxx | 6 |
6 files changed, 65 insertions, 2 deletions
diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx index 1598c827cfcf..8f082a632d73 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 7cf0be3c0bb3..0d39c2fbd508 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> constexpr OUStringLiteral DATA_DIRECTORY = u"/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 75cdb398ba7b..0b2b7b8647f6 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -2902,6 +2902,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 e3b2767b6af2..d366a2f852a2 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 c72104c7b4e3..3348540fcf29 100644 --- a/sw/source/core/edit/editsh.cxx +++ b/sw/source/core/edit/editsh.cxx @@ -89,6 +89,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 16d67c667cbb..e81c62d1d9e0 100644 --- a/sw/source/core/inc/DocumentContentOperationsManager.hxx +++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx @@ -60,6 +60,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, @@ -157,6 +161,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); |