desktop/inc/lib/init.hxx | 2 + desktop/source/lib/init.cxx | 49 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 9 deletions(-)
New commits: commit 876be07b6dd61eb323428aca6c31c3e58a8488fd Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Tue Jan 18 17:04:15 2022 +0000 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Mon Feb 7 13:09:07 2022 +0100 lok: avoid duplicate emission of statechanged: messages. We tend to get many of these per keystroke, with the same state. Change-Id: I9d759f54aee8d6dabcef094997e8f352dd608ec3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128578 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Ashod Nakashian <a...@collabora.com> diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index bb560264743b..b2ba47239f2f 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -85,6 +85,7 @@ namespace desktop { static tools::Rectangle CheckedRectangle(const tools::Rectangle& rect); }; + /// One instance of this per view, handles flushing callbacks class DESKTOP_DLLPUBLIC CallbackFlushHandler final : public Idle, public SfxLokCallbackInterface { public: @@ -190,6 +191,7 @@ namespace desktop { queue_type1 m_queue1; queue_type2 m_queue2; std::map<int, std::string> m_states; + std::unordered_map<std::string, std::string> m_lastStateChange; std::unordered_map<int, std::unordered_map<int, std::string>> m_viewStates; // For some types only the last message matters (see isUpdatedType()) or only the last message diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 4693e79ec3f6..2ae5fc89f731 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1350,6 +1350,7 @@ void CallbackFlushHandler::TimeoutIdle::Invoke() mHandler->Invoke(); } +// One of these is created per view to handle events cf. doc_registerCallback CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, LibreOfficeKitCallback pCallback, void* pData) : Idle( "lokit idle callback" ), m_pDocument(pDocument), @@ -2151,22 +2152,52 @@ void CallbackFlushHandler::Invoke() const auto& payload = it2->getPayload(); const int viewId = lcl_isViewCallbackType(type) ? it2->getViewId() : -1; + SAL_INFO("lok", "processing event: [" << type << ',' << viewId << "]: [" << payload << "]."); + + // common code-path for events on this view: if (viewId == -1) { - const auto stateIt = m_states.find(type); - if (stateIt != m_states.end()) + size_t idx; + // key-value pairs + if (type == LOK_CALLBACK_STATE_CHANGED && + (idx = payload.find('=')) != std::string::npos) { - // If the state didn't change, it's safe to ignore. - if (stateIt->second == payload) + std::string key = payload.substr(0, idx); + std::string value = payload.substr(idx+1); + const auto stateIt = m_lastStateChange.find(key); + if (stateIt != m_lastStateChange.end()) { - SAL_INFO("lok", "Skipping duplicate [" << type << "]: [" << payload << "]."); - continue; + // If the value didn't change, it's safe to ignore. + if (stateIt->second == value) + { + SAL_INFO("lok", "Skipping new state duplicate: [" << type << "]: [" << payload << "]."); + continue; + } + SAL_INFO("lok", "Replacing a state element [" << type << "]: [" << payload << "]."); + stateIt->second = value; + } + else + { + SAL_INFO("lok", "Inserted a new state element: [" << type << "]: [" << payload << "]"); + m_lastStateChange.emplace(key, value); + } + } + else + { + const auto stateIt = m_states.find(type); + if (stateIt != m_states.end()) + { + // If the state didn't change, it's safe to ignore. + if (stateIt->second == payload) + { + SAL_INFO("lok", "Skipping duplicate [" << type << "]: [" << payload << "]."); + continue; + } + stateIt->second = payload; } - - stateIt->second = payload; } } - else + else // less common path for events relating to other views { const auto statesIt = m_viewStates.find(viewId); if (statesIt != m_viewStates.end())