sfx2/source/control/bindings.cxx     |    1 +
 sw/qa/extras/unowriter/unowriter.cxx |   21 +++++++++++++++++++++
 sw/source/core/unocore/unoobj.cxx    |   12 +++++++++---
 vcl/win/dtrans/MtaOleClipb.cxx       |   35 +++++++++++++++++++++--------------
 vcl/win/dtrans/WinClipboard.cxx      |   14 +++++++++-----
 5 files changed, 61 insertions(+), 22 deletions(-)

New commits:
commit 1c52e94b2d926875d1a108c54988dbcb2dc9d017
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Mar 20 16:24:07 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Mar 21 17:51:23 2024 +0100

    tdf#160278: restore cursor bounds properly
    
    The passed string length is not a correct measure of how many steps
    should the selection expand in the resulting text: the cursor goes
    over glyphs, not over UTF-16 code units. Thus, it's easier to store
    the position prior to insertion, and restore it from the indexes.
    
    Change-Id: I1d592ff30199007ba3a99d7e1a6d2db2da35f1cb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165056
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sw/qa/extras/unowriter/unowriter.cxx 
b/sw/qa/extras/unowriter/unowriter.cxx
index c4bcbb7f5dd6..a11e928e8c1d 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -1200,6 +1200,27 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf129841)
     CPPUNIT_ASSERT_EQUAL(aRefColor, aColor);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf160278)
+{
+    createSwDoc();
+    auto xTextDocument(mxComponent.queryThrow<css::text::XTextDocument>());
+    auto xText(xTextDocument->getText());
+    xText->setString(u"123"_ustr);
+    CPPUNIT_ASSERT_EQUAL(u"123"_ustr, xText->getString());
+    auto xCursor = xText->createTextCursorByRange(xText->getEnd());
+    xCursor->goLeft(1, true);
+    CPPUNIT_ASSERT_EQUAL(u"3"_ustr, xCursor->getString());
+    // Insert an SMP character U+1f702 (so it's two UTF-16 code units, 0xd83d 
0xdf02):
+    xCursor->setString(u"🜂"_ustr);
+    // Without the fix, the replacement would expand the cursor one too many 
characters to the left,
+    // and the cursor text would become "2🜂", failing the next test:
+    CPPUNIT_ASSERT_EQUAL(u"🜂"_ustr, xCursor->getString());
+    xCursor->setString(u"test"_ustr);
+    CPPUNIT_ASSERT_EQUAL(u"test"_ustr, xCursor->getString());
+    // This test would fail, too; the text would be "1test":
+    CPPUNIT_ASSERT_EQUAL(u"12test"_ustr, xText->getString());
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/core/unocore/unoobj.cxx 
b/sw/source/core/unocore/unoobj.cxx
index 3c5f34f1940a..69fa9d3be300 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -752,13 +752,19 @@ void SwXTextCursor::DeleteAndInsert(std::u16string_view 
aText,
         }
         if(nTextLen)
         {
+            // Store node and content indexes prior to insertion: to select 
the inserted text,
+            // we need to account for possible surrogate pairs, combining 
characters, etc.; it
+            // is easier to just restore the correct position from the indexes.
+            const auto start = pCurrent->Start();
+            const auto nodeIndex = start->GetNodeIndex();
+            const auto contentIndex = start->GetContentIndex();
             const bool bSuccess(
                 SwUnoCursorHelper::DocInsertStringSplitCR(
-                    rDoc, *pCurrent, aText, bool(eMode & 
::sw::DeleteAndInsertMode::ForceExpandHints)));
+                    rDoc, SwPaM(*start, pCurrent), aText, bool(eMode & 
::sw::DeleteAndInsertMode::ForceExpandHints)));
             OSL_ENSURE( bSuccess, "Doc->Insert(Str) failed." );
 
-            SwUnoCursorHelper::SelectPam(*pUnoCursor, true);
-            pCurrent->Left(aText.size());
+            pCurrent->SetMark();
+            pCurrent->GetPoint()->Assign(nodeIndex, contentIndex);
         }
         pCurrent = pCurrent->GetNext();
     } while (pCurrent != pUnoCursor);
commit f4ade8244bf984712e65c2eb82cf3319d2679eeb
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Mar 21 10:01:36 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Mar 21 17:51:14 2024 +0100

    Downgrade sfx::SfxBindings aAutoTimer to an idle
    
    This is a follow-up to commit f45402ae3f5241b460d9f1dcb04183893e1f91f7
    (Fix a spurious JunitTest_sw_unoapi_3 failure, 2024-03-15). As noted
    by Stephan, the failure persisted; it was because the update of slots
    also accessed the changing document model, and it wasn't prevented by
    IdlesLockGuard, because aAutoTimer had a default priority.
    
    Change-Id: Iad8dfadcd35d9611e61e4c011511d6155a343f58
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165090
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sfx2/source/control/bindings.cxx b/sfx2/source/control/bindings.cxx
index 549a9fc45e67..458ef0431fc7 100644
--- a/sfx2/source/control/bindings.cxx
+++ b/sfx2/source/control/bindings.cxx
@@ -148,6 +148,7 @@ SfxBindings::SfxBindings()
 
     // all caches are valid (no pending invalidate-job)
     // create the list of caches
+    pImpl->aAutoTimer.SetPriority(TaskPriority::HIGH_IDLE);
     pImpl->aAutoTimer.SetInvokeHandler( LINK(this, SfxBindings, NextJob) );
 }
 
commit 7132e2975c354dbd29775c7167c324b53032bca6
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Mar 21 10:00:44 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Mar 21 17:51:09 2024 +0100

    Only hold clipboard mutexes to obtain the values, to avoid deadlocks
    
    Change-Id: I36a2f6e444b8a5397b96d3cba475a8d06ea86459
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165089
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/vcl/win/dtrans/MtaOleClipb.cxx b/vcl/win/dtrans/MtaOleClipb.cxx
index fcf16df1adf1..a62f4a1c0c72 100644
--- a/vcl/win/dtrans/MtaOleClipb.cxx
+++ b/vcl/win/dtrans/MtaOleClipb.cxx
@@ -707,25 +707,32 @@ unsigned __stdcall 
CMtaOleClipboard::clipboardChangedNotifierThreadProc(void* pP
         MsgWaitForMultipleObjects(2, pInst->m_hClipboardChangedNotifierEvents, 
false, INFINITE,
                                   QS_ALLINPUT | QS_ALLPOSTMESSAGE);
 
-        std::unique_lock aGuard2( pInst->m_ClipboardChangedEventCountMutex );
-
-        if ( pInst->m_ClipboardChangedEventCount > 0 )
+        bool hadEvents;
         {
-            pInst->m_ClipboardChangedEventCount--;
-            if ( 0 == pInst->m_ClipboardChangedEventCount )
-                ResetEvent( pInst->m_hClipboardChangedEvent );
-
-            aGuard2.unlock( );
+            std::unique_lock aGuard2(pInst->m_ClipboardChangedEventCountMutex);
+            hadEvents = pInst->m_ClipboardChangedEventCount > 0;
+            if (hadEvents)
+            {
+                pInst->m_ClipboardChangedEventCount--;
+                if (0 == pInst->m_ClipboardChangedEventCount)
+                    ResetEvent(pInst->m_hClipboardChangedEvent);
+            }
+        }
 
-            // nobody should touch m_pfncClipViewerCallback while we do
-            std::unique_lock aClipViewerGuard( 
pInst->m_pfncClipViewerCallbackMutex );
+        if (hadEvents)
+        {
+            LPFNC_CLIPVIEWER_CALLBACK_t pClipViewerCallback;
+            {
+                // nobody should touch m_pfncClipViewerCallback while we do
+                // but don't hold the mutex while calling the callback itself: 
it could deadlock
+                std::unique_lock 
aClipViewerGuard(pInst->m_pfncClipViewerCallbackMutex);
+                pClipViewerCallback = pInst->m_pfncClipViewerCallback;
+            }
 
             // notify all clipboard listener
-            if ( pInst->m_pfncClipViewerCallback )
-                pInst->m_pfncClipViewerCallback( );
+            if (pClipViewerCallback)
+                pClipViewerCallback();
         }
-        else
-            aGuard2.unlock( );
     }
 
     return 0;
diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx
index 1a8eaea151b5..5f46bebecfd2 100644
--- a/vcl/win/dtrans/WinClipboard.cxx
+++ b/vcl/win/dtrans/WinClipboard.cxx
@@ -370,13 +370,17 @@ void CWinClipboard::unregisterClipboardViewer() { 
m_MtaOleClipboard.registerClip
 
 void WINAPI CWinClipboard::onClipboardContentChanged()
 {
-    osl::MutexGuard aGuard(s_aClipboardSingletonMutex);
+    rtl::Reference<CWinClipboard> pWinClipboard;
+    {
+        // Only hold the mutex to obtain a safe reference to the impl, to 
avoid deadlock
+        osl::MutexGuard aGuard(s_aClipboardSingletonMutex);
+        pWinClipboard.set(s_pCWinClipbImpl);
+    }
 
-    // reassociation to instance through static member
-    if (nullptr != s_pCWinClipbImpl)
+    if (pWinClipboard)
     {
-        s_pCWinClipbImpl->m_foreignContent.clear();
-        s_pCWinClipbImpl->notifyAllClipboardListener();
+        pWinClipboard->m_foreignContent.clear();
+        pWinClipboard->notifyAllClipboardListener();
     }
 }
 

Reply via email to