desktop/inc/lib/init.hxx | 13 ++++++- desktop/source/lib/init.cxx | 75 +++++++++++++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 23 deletions(-)
New commits: commit ce7484ffff5ccb7c41975da1ac453c6cbd49531f Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Fri Aug 19 08:28:16 2016 -0400 LOK: queue-up events while processing client calls To prevent feedback effects and improve performance, we now queue up events fired during the processing of a client call on the LOK API. This has the advantage of giving us a chance to compress redundant events and to combine others (where possible) into fewer ones. Change-Id: I2f6ea12c5d85205e6495cb130f6a6262534b6bb2 Reviewed-on: https://gerrit.libreoffice.org/28311 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 815f1ac..da03cfa 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -35,8 +35,16 @@ namespace desktop { virtual void Invoke() override; static void callback(const int type, const char* payload, void* data); void queue(const int type, const char* data); - void setPartTilePainting(const bool bPartPainting); - bool isPartTilePainting() const; + + /// When enabled events are queued but callback not invoked. + void setEventLatch(const bool bEventLatch) + { + m_bEventLatch = bEventLatch; + } + + bool isEventLatchOn() const { return m_bEventLatch; } + void setPartTilePainting(const bool bPartPainting) { m_bPartTilePainting = bPartPainting; } + bool isPartTilePainting() const { return m_bPartTilePainting; } private: void flush(); @@ -48,6 +56,7 @@ namespace desktop { LibreOfficeKitCallback m_pCallback; void *m_pData; bool m_bPartTilePainting; + bool m_bEventLatch; std::mutex m_mutex; }; diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 6ab1cf3..9f32bcf 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -311,6 +311,16 @@ static boost::property_tree::ptree unoAnyToPropertyTree(const uno::Any& anyItem) return aTree; } +Rectangle lcl_ParseRect(const std::string& payload) +{ + std::istringstream iss(payload); + long left, top, right, bottom; + char comma; + iss >> left >> comma >> top >> comma >> right >> comma >> bottom; + Rectangle rc(left, top, left + right, top + bottom); + return rc; +} + extern "C" { @@ -453,7 +463,8 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li m_pDocument(pDocument), m_pCallback(pCallback), m_pData(pData), - m_bPartTilePainting(false) + m_bPartTilePainting(false), + m_bEventLatch(false) { SetPriority(SchedulerPriority::POST_PAINT); @@ -474,6 +485,7 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li m_states.emplace(LOK_CALLBACK_CURSOR_VISIBLE, "NIL"); m_states.emplace(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "NIL"); m_states.emplace(LOK_CALLBACK_SET_PART, "NIL"); + m_states.emplace(LOK_CALLBACK_TEXT_VIEW_SELECTION, "NIL"); Start(); } @@ -481,9 +493,6 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li CallbackFlushHandler::~CallbackFlushHandler() { Stop(); - - // We might have important notification (.uno:save?). - flush(); } void CallbackFlushHandler::Invoke() @@ -519,7 +528,7 @@ void CallbackFlushHandler::queue(const int type, const char* data) type != LOK_CALLBACK_VIEW_CURSOR_VISIBLE && type != LOK_CALLBACK_TEXT_SELECTION) { - //SAL_WARN("lokevt", "Skipping while painting [" + std::to_string(type) + "]: [" + payload + "]."); + SAL_WARN("lok", "Skipping while painting [" + std::to_string(type) + "]: [" + payload + "]."); return; } @@ -536,7 +545,7 @@ void CallbackFlushHandler::queue(const int type, const char* data) // issueing it, instead of the absolute one that we expect. // This is temporary however, and, once the control is created and initialized // correctly, it eventually emits the correct absolute coordinates. - //SAL_WARN("lokevt", "Skipping invalid event [" + std::to_string(type) + "]: [" + payload + "]."); + SAL_WARN("lok", "Skipping invalid event [" + std::to_string(type) + "]: [" + payload + "]."); return; } @@ -548,7 +557,7 @@ void CallbackFlushHandler::queue(const int type, const char* data) // If the state didn't change, it's safe to ignore. if (stateIt->second == payload) { - //SAL_WARN("lokevt", "Skipping duplicate [" + std::to_string(type) + "]: [" + payload + "]."); + //SAL_WARN("lok", "Skipping duplicate [" + std::to_string(type) + "]: [" + payload + "]."); return; } @@ -581,6 +590,7 @@ void CallbackFlushHandler::queue(const int type, const char* data) case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: case LOK_CALLBACK_SET_PART: case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE: + case LOK_CALLBACK_TEXT_VIEW_SELECTION: removeAllButLast(type, false); break; @@ -595,10 +605,43 @@ void CallbackFlushHandler::queue(const int type, const char* data) // invalidated tiles can be dropped. removeAllButLast(type, false); } - else + else if (type == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR) { removeAllButLast(type, true); } + else if (type == LOK_CALLBACK_INVALIDATE_TILES) + { + Rectangle rcNew = lcl_ParseRect(payload); + //SAL_WARN("lok", "New: " << rcNew.toString()); + const auto rcOrig = rcNew; + int i = m_queue.size(); + i -= 2; + for (; i >= 0; --i) + { + if (m_queue[i].first == type) + { + const Rectangle rcOld = lcl_ParseRect(m_queue[i].second); + //SAL_WARN("lok", "#" << i << " Old: " << rcOld.toString()); + const Rectangle rcOverlap = rcNew.GetIntersection(rcOld); + //SAL_WARN("lok", "#" << i << " Overlap: " << rcOverlap.toString()); + if (rcOverlap.GetWidth() > 0 && rcOverlap.GetHeight() > 0) + { + //SAL_WARN("lok", rcOld.toString() << " U " << rcNew.toString()); + rcNew.Union(rcOld); + //SAL_WARN("lok", "#" << i << " Union: " << rcNew.toString()); + m_queue.erase(m_queue.begin() + i); + } + } + } + + assert(!m_queue.empty()); + if (rcNew != rcOrig) + { + SAL_WARN("lok", "Replacing: " << rcOrig.toString() << " by " << rcNew.toString()); + m_queue.erase(m_queue.begin() + m_queue.size() - 1); + m_queue.emplace_back(type, rcNew.toString().getStr()); + } + } break; } @@ -610,19 +653,9 @@ void CallbackFlushHandler::queue(const int type, const char* data) } } -void CallbackFlushHandler::setPartTilePainting(const bool bPartPainting) -{ - m_bPartTilePainting = bPartPainting; -} - -bool CallbackFlushHandler::isPartTilePainting() const -{ - return m_bPartTilePainting; -} - void CallbackFlushHandler::flush() { - if (m_pCallback) + if (m_pCallback && !m_bEventLatch) { std::unique_lock<std::mutex> lock(m_mutex); for (auto& pair : m_queue) @@ -643,7 +676,7 @@ void CallbackFlushHandler::removeAllButLast(const int type, const bool identical if (m_queue[i].first == type) { payload = m_queue[i].second; - //SAL_WARN("lokevt", "Found [" + std::to_string(type) + "] at " + std::to_string(i) + ": [" + payload + "]."); + //SAL_WARN("lok", "Found [" + std::to_string(type) + "] at " + std::to_string(i) + ": [" + payload + "]."); break; } } @@ -653,7 +686,7 @@ void CallbackFlushHandler::removeAllButLast(const int type, const bool identical if (m_queue[i].first == type && (!identical || m_queue[i].second == payload)) { - //SAL_WARN("lokevt", "Removing [" + std::to_string(type) + "] at " + std::to_string(i) + ": " + m_queue[i].second + "]."); + //SAL_WARN("lok", "Removing [" + std::to_string(type) + "] at " + std::to_string(i) + ": " + m_queue[i].second + "]."); m_queue.erase(m_queue.begin() + i); } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits