summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2016-08-19 08:28:16 -0400
committerAshod Nakashian <ashnakash@gmail.com>2016-08-31 11:51:51 +0000
commitce7484ffff5ccb7c41975da1ac453c6cbd49531f (patch)
treec8ab736edda5fb1919de9fd5016ed2129be3d6c3 /desktop
parent6527b4073c72d3fdf2307a58a06023fe28fd9960 (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.hxx13
-rw-r--r--desktop/source/lib/init.cxx75
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);
}
}