diff options
author | Ashod Nakashian <ashod.nakashian@collabora.co.uk> | 2016-08-19 08:28:16 -0400 |
---|---|---|
committer | Ashod Nakashian <ashnakash@gmail.com> | 2016-08-31 11:51:51 +0000 |
commit | ce7484ffff5ccb7c41975da1ac453c6cbd49531f (patch) | |
tree | c8ab736edda5fb1919de9fd5016ed2129be3d6c3 /desktop | |
parent | 6527b4073c72d3fdf2307a58a06023fe28fd9960 (diff) |
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 <ci@libreoffice.org>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/inc/lib/init.hxx | 13 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 75 |
2 files changed, 65 insertions, 23 deletions
diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 815f1ac6b4da..da03cfaf8843 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 6ab1cf3bb6b4..9f32bcfd1edb 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); } } |