diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2021-10-07 18:02:12 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2021-10-25 19:30:34 +0200 |
commit | 4bb6533d398cc76d7ff292a9e47dae87fac74f83 (patch) | |
tree | 6104d470627c2592624f315e8c8b32435ff5c109 | |
parent | 9e3ec1b50052e687d6bc79db8e2ed5ebbd0eb24a (diff) |
use pull model also for LOK text selection
Make LOK_CALLBACK_TEXT_SELECTION, LOK_CALLBACK_TEXT_SELECTION_START,
LOK_CALLBACK_TEXT_SELECTION_END and LOK_CALLBACK_TEXT_VIEW_SELECTION
also use pull model, i.e. LO core will only set a flag and when
CallbackFlushHandler needs the actual data it'll use getLOKPayload().
This again avoids a large number of messages passed to
CallbackFlushHandler only for them to be sooner or later discarded.
Change-Id: Ia7528039be996a6e9e8491b4eba3f4133582fa56
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124146
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r-- | desktop/qa/desktop_lib/test_desktop_lib.cxx | 12 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 56 | ||||
-rw-r--r-- | sw/inc/viscrs.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/crsr/viscrs.cxx | 70 | ||||
-rw-r--r-- | sw/source/uibase/uiview/viewsrch.cxx | 4 | ||||
-rw-r--r-- | sw/source/uibase/wrtsh/wrtsh4.cxx | 5 | ||||
-rw-r--r-- | test/source/lokcallback.cxx | 2 |
7 files changed, 121 insertions, 30 deletions
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index cfa8e039a5d0..1144a5e48369 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -1545,6 +1545,7 @@ void DesktopLOKTest::testNotificationCompression() LibLODocument_Impl* pDocument = loadDoc("blank_text.odt"); std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, ""); // 0 handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"); // Superseded. @@ -1640,6 +1641,7 @@ void DesktopLOKTest::testTileInvalidationCompression() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); @@ -1660,6 +1662,7 @@ void DesktopLOKTest::testTileInvalidationCompression() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 1"); // Different part @@ -1683,6 +1686,7 @@ void DesktopLOKTest::testTileInvalidationCompression() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); // 0 handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 1"); // 1: Different part @@ -1709,6 +1713,7 @@ void DesktopLOKTest::testTileInvalidationCompression() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 0"); // 0 handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 100, 100, 1"); // 1: Different part @@ -1744,6 +1749,7 @@ void DesktopLOKTest::testTileInvalidationCompression() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0"); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "EMPTY, 0"); @@ -1768,6 +1774,7 @@ void DesktopLOKTest::testPartInInvalidation() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10"); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10"); @@ -1783,6 +1790,7 @@ void DesktopLOKTest::testPartInInvalidation() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10"); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "40, 10, 20, 10"); @@ -1802,6 +1810,7 @@ void DesktopLOKTest::testPartInInvalidation() std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10, 0"); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10, 0"); @@ -1820,6 +1829,7 @@ void DesktopLOKTest::testPartInInvalidation() std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "10, 10, 20, 10, 0"); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "20, 10, 20, 10, 1"); @@ -1848,6 +1858,7 @@ void DesktopLOKTest::testBinaryCallback() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackBinaryCallbackTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->queue(LOK_CALLBACK_INVALIDATE_TILES, rect1String.c_str()); @@ -1860,6 +1871,7 @@ void DesktopLOKTest::testBinaryCallback() { std::vector<std::tuple<int, std::string>> notifs; std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackBinaryCallbackTest, ¬ifs)); + handler->setViewId(SfxLokHelper::getView()); handler->libreOfficeKitViewInvalidateTilesCallback(&rect1, INT_MIN); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index c38a6dd8d754..30bfd4594754 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -698,9 +698,17 @@ static bool lcl_isViewCallbackType(const int type) } } -static bool isUpdatedType(int /*type*/) +static bool isUpdatedType(int type) { - return false; + switch (type) + { + case LOK_CALLBACK_TEXT_SELECTION: + case LOK_CALLBACK_TEXT_SELECTION_START: + case LOK_CALLBACK_TEXT_SELECTION_END: + return true; + default: + return false; + } } static bool isUpdatedTypePerViewId(int type) @@ -709,6 +717,7 @@ static bool isUpdatedTypePerViewId(int type) { case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR: + case LOK_CALLBACK_TEXT_VIEW_SELECTION: return true; default: return false; @@ -2121,31 +2130,53 @@ void CallbackFlushHandler::enqueueUpdatedTypes() { if( m_updatedTypes.empty() && m_updatedTypesPerViewId.empty()) return; + assert(m_viewId >= 0); SfxViewShell* viewShell = SfxViewShell::GetFirst( false, [this](const SfxViewShell* shell) { return shell->GetViewShellId().get() == m_viewId; } ); assert(viewShell != nullptr); - for( size_t type = 0; type < m_updatedTypes.size(); ++type ) - { - if(m_updatedTypes[ type ]) + + // First move data to local structures, so that callbacks don't possibly modify it. + std::vector<bool> updatedTypes; + std::swap(updatedTypes, m_updatedTypes); + std::unordered_map<int, std::vector<PerViewIdData>> updatedTypesPerViewId; + std::swap(updatedTypesPerViewId, m_updatedTypesPerViewId); + + // Some types must always precede other types, for example + // LOK_CALLBACK_TEXT_SELECTION_START and LOK_CALLBACK_TEXT_SELECTION_END + // must always precede LOK_CALLBACK_TEXT_SELECTION if present. + // Only these types should be present (see isUpdatedType()) and should be processed in this order. + static const int orderedUpdatedTypes[] = { + LOK_CALLBACK_TEXT_SELECTION_START, LOK_CALLBACK_TEXT_SELECTION_END, LOK_CALLBACK_TEXT_SELECTION }; + // Only these types should be present (see isUpdatedTypePerViewId()) and (as of now) + // the order doesn't matter. + static const int orderedUpdatedTypesPerViewId[] = { + LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, + LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, + LOK_CALLBACK_TEXT_VIEW_SELECTION }; + + for( int type : orderedUpdatedTypes ) + { + if(o3tl::make_unsigned( type ) < updatedTypes.size() && updatedTypes[ type ]) { - assert(isUpdatedType( type )); enqueueUpdatedType( type, viewShell, m_viewId ); } } - for( const auto& it : m_updatedTypesPerViewId ) + for( const auto& it : updatedTypesPerViewId ) { int viewId = it.first; const std::vector<PerViewIdData>& types = it.second; - for( size_t type = 0; type < types.size(); ++type ) + for( int type : orderedUpdatedTypesPerViewId ) { - if(types[ type ].set) + if(o3tl::make_unsigned( type ) < types.size() && types[ type ].set) { - assert(isUpdatedTypePerViewId( type )); SfxViewShell* sourceViewShell = viewShell; const int sourceViewId = types[ type ].sourceViewId; if( sourceViewId != m_viewId ) + { + assert(sourceViewId >= 0); sourceViewShell = SfxViewShell::GetFirst( false, [sourceViewId](const SfxViewShell* shell) { return shell->GetViewShellId().get() == sourceViewId; } ); + } if(sourceViewShell == nullptr) { SAL_INFO("lok", "View #" << sourceViewId << " no longer found for updated event [" << type << "]"); @@ -2155,13 +2186,13 @@ void CallbackFlushHandler::enqueueUpdatedTypes() } } } - m_updatedTypes.clear(); - m_updatedTypesPerViewId.clear(); } void CallbackFlushHandler::enqueueUpdatedType( int type, SfxViewShell* viewShell, int viewId ) { OString payload = viewShell->getLOKPayload( type, viewId ); + if(payload.isEmpty()) + return; // No actual payload to send. CallbackData callbackData(payload.getStr(), viewId); m_queue1.emplace_back(type); m_queue2.emplace_back(callbackData); @@ -2178,6 +2209,7 @@ void CallbackFlushHandler::Invoke() // Get any pending invalidate tile events. This will call our callbacks, // so it must be done before taking the mutex. + assert(m_viewId >= 0); if(SfxViewShell* viewShell = SfxViewShell::GetFirst( false, [this](const SfxViewShell* shell) { return shell->GetViewShellId().get() == m_viewId; } )) { diff --git a/sw/inc/viscrs.hxx b/sw/inc/viscrs.hxx index c8b8b356f7e3..3c355e01800c 100644 --- a/sw/inc/viscrs.hxx +++ b/sw/inc/viscrs.hxx @@ -113,6 +113,8 @@ public: // Optional set the parameters pX, pY static void Get1PixelInLogic( const SwViewShell& rSh, tools::Long* pX = nullptr, tools::Long* pY = nullptr ); + + OString getLOKPayload(int nType, int nViewId) const; }; class SW_DLLPUBLIC SwShellCursor : public virtual SwCursor, public SwSelPaintRects diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx index 2c77e6d4dd87..d28dab2c7d98 100644 --- a/sw/source/core/crsr/viscrs.cxx +++ b/sw/source/core/crsr/viscrs.cxx @@ -478,25 +478,14 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) // If pSelectionRectangles is set, we're just collecting the text selections -> don't emit start/end. if (!empty() && !pSelectionRectangles) { - // The selection may be a complex polygon, emit the logical - // start/end cursor rectangle of the selection as separate - // events, if there is a real selection. - // This can be used to easily show selection handles on the - // client side. SwRect aStartRect; SwRect aEndRect; FillStartEnd(aStartRect, aEndRect); if (aStartRect.HasArea()) - { - OString sRect = aStartRect.SVRect().toString(); - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, sRect.getStr()); - } + SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_SELECTION_START); if (aEndRect.HasArea()) - { - OString sRect = aEndRect.SVRect().toString(); - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, sRect.getStr()); - } + SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_SELECTION_END); } std::vector<OString> aRect; @@ -509,13 +498,64 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) OString sRect = comphelper::string::join("; ", aRect); if (!pSelectionRectangles) { - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRect.getStr()); - SfxLokHelper::notifyOtherViews(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRect); + SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION); + SfxLokHelper::notifyOtherViewsUpdatePerViewId(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION); } else pSelectionRectangles->push_back(sRect); } +OString SwSelPaintRects::getLOKPayload( int nType, int nViewId ) const +{ + switch( nType ) + { + case LOK_CALLBACK_TEXT_SELECTION_START: + case LOK_CALLBACK_TEXT_SELECTION_END: + { + // The selection may be a complex polygon, emit the logical + // start/end cursor rectangle of the selection as separate + // events, if there is a real selection. + // This can be used to easily show selection handles on the + // client side. + SwRect aStartRect; + SwRect aEndRect; + FillStartEnd(aStartRect, aEndRect); + + if( nType == LOK_CALLBACK_TEXT_SELECTION_START ) + { + if (aStartRect.HasArea()) + return aStartRect.SVRect().toString(); + return OString(); + } + else // LOK_CALLBACK_TEXT_SELECTION_END + { + if (aEndRect.HasArea()) + return aEndRect.SVRect().toString(); + return OString(); + } + } + break; + case LOK_CALLBACK_TEXT_SELECTION: + case LOK_CALLBACK_TEXT_VIEW_SELECTION: + { + std::vector<OString> aRect; + aRect.reserve(size()); + for (size_type i = 0; i < size(); ++i) + { + const SwRect& rRect = (*this)[i]; + aRect.push_back(rRect.SVRect().toString()); + } + OString sRect = comphelper::string::join("; ", aRect); + if( nType == LOK_CALLBACK_TEXT_SELECTION ) + return sRect; + else // LOK_CALLBACK_TEXT_VIEW_SELECTION + return SfxLokHelper::makePayloadJSON(GetShell()->GetSfxViewShell(), nViewId, "selection", sRect); + } + break; + } + abort(); +} + void SwSelPaintRects::HighlightInputField() { std::vector< basegfx::B2DRange > aInputFieldRanges; diff --git a/sw/source/uibase/uiview/viewsrch.cxx b/sw/source/uibase/uiview/viewsrch.cxx index c6d42d7830dd..d2e1731bbc91 100644 --- a/sw/source/uibase/uiview/viewsrch.cxx +++ b/sw/source/uibase/uiview/viewsrch.cxx @@ -126,8 +126,8 @@ static void lcl_emitSearchResultCallbacks(SvxSearchItem const * pSearchItem, SwW if(bHighlightAll) { // FindAll disables this during find, do it once when done. - pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, textSelection.getStr()); - SfxLokHelper::notifyOtherViews(pWrtShell->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", textSelection); + SfxLokHelper::notifyUpdate(pWrtShell->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION); + SfxLokHelper::notifyOtherViewsUpdatePerViewId(pWrtShell->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION); } } diff --git a/sw/source/uibase/wrtsh/wrtsh4.cxx b/sw/source/uibase/wrtsh/wrtsh4.cxx index b80b41b41e54..0bafa1e75941 100644 --- a/sw/source/uibase/wrtsh/wrtsh4.cxx +++ b/sw/source/uibase/wrtsh/wrtsh4.cxx @@ -241,6 +241,11 @@ OString SwWrtShell::getLOKPayload(int nType, int nViewId) const case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR: return GetVisibleCursor()->getLOKPayload(nType, nViewId); + case LOK_CALLBACK_TEXT_SELECTION: + case LOK_CALLBACK_TEXT_SELECTION_START: + case LOK_CALLBACK_TEXT_SELECTION_END: + case LOK_CALLBACK_TEXT_VIEW_SELECTION: + return GetCursor_()->getLOKPayload( nType, nViewId ); } abort(); } diff --git a/test/source/lokcallback.cxx b/test/source/lokcallback.cxx index 6a39b9064470..90ca5f2c9203 100644 --- a/test/source/lokcallback.cxx +++ b/test/source/lokcallback.cxx @@ -143,7 +143,7 @@ void TestLokCallbackWrapper::flushLOKData() return shell->GetViewShellId().get() == m_viewId; }); assert(viewShell != nullptr); - // First move data to local structures, so that notifyFromLOKCallback() doesn't modify it. + // First move data to local structures, so that callbacks don't possibly modify it. std::vector<int> updatedTypes; std::swap(updatedTypes, m_updatedTypes); std::vector<PerViewIdData> updatedTypesPerViewId; |