summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2016-12-06 00:42:58 -0500
committerAndras Timar <andras.timar@collabora.com>2017-02-17 16:36:50 +0100
commit9f3e57e5fa31ca5654ee9eeaba03c871a1c83150 (patch)
tree328d936af468a6c96fd378bdca390051e9c1deb7 /desktop
parent6b8c3d6690445ffedefdbef56bc94c0aa7c267fc (diff)
Lok: improved tile invalidation compression
Handle corner cases better and eliminate invalid rects and out-of-bounds coordinates. Change-Id: Ib9247ae4f0306cf68937cd2678f6386fe7710eec Reviewed-on: https://gerrit.libreoffice.org/31665 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> (cherry picked from commit 3db1ce30ab235ad22aed71c22e4f6f52b7b88829)
Diffstat (limited to 'desktop')
-rw-r--r--desktop/qa/desktop_lib/test_desktop_lib.cxx174
-rw-r--r--desktop/source/lib/init.cxx183
2 files changed, 266 insertions, 91 deletions
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 9acd2c70c3bb..833e80110cae 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -1299,29 +1299,29 @@ void DesktopLOKTest::testNotificationCompression()
std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, &notifs));
handler->queue(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, ""); // 0
- handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15 25 15 10"); // Superseeded.
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"); // Superseeded.
handler->queue(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, ""); // Should be dropped.
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15 25 15 10"); // Superseeded.
- handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15 25 15 10"); // Should be dropped.
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"); // 1
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"); // Should be dropped.
handler->queue(LOK_CALLBACK_TEXT_SELECTION, ""); // Superseeded.
handler->queue(LOK_CALLBACK_STATE_CHANGED, ""); // 2
handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:Bold"); // 3
handler->queue(LOK_CALLBACK_STATE_CHANGED, ""); // 4
handler->queue(LOK_CALLBACK_MOUSE_POINTER, "text"); // 5
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15 25 15 10"); // 6
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15 25 15 10"); // Should be dropped.
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"); // Should be dropped.
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "15, 25, 15, 10"); // Should be dropped.
handler->queue(LOK_CALLBACK_MOUSE_POINTER, "text"); // Should be dropped.
- handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15 25 15 10"); // Superseeded.
- handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15 25 15 10"); // Superseeded.
- handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15 25 15 10"); // Superseedd.
- handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15 25 15 10"); // Should be dropped.
- handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15 25 15 10"); // Should be dropped.
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"); // Superseeded.
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"); // Superseeded.
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION, "15, 25, 15, 10"); // Superseedd.
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"); // Should be dropped.
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"); // Should be dropped.
handler->queue(LOK_CALLBACK_TEXT_SELECTION, ""); // 7
- handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15 25 15 10"); // 8
- handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15 25 15 10"); // 9
- handler->queue(LOK_CALLBACK_CELL_CURSOR, "15 25 15 10"); // 10
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION_START, "15, 25, 15, 10"); // 8
+ handler->queue(LOK_CALLBACK_TEXT_SELECTION_END, "15, 25, 15, 10"); // 9
+ handler->queue(LOK_CALLBACK_CELL_CURSOR, "15, 25, 15, 10"); // 10
handler->queue(LOK_CALLBACK_CURSOR_VISIBLE, ""); // 11
- handler->queue(LOK_CALLBACK_CELL_CURSOR, "15 25 15 10"); // Should be dropped.
+ handler->queue(LOK_CALLBACK_CELL_CURSOR, "15, 25, 15, 10"); // Should be dropped.
handler->queue(LOK_CALLBACK_CELL_FORMULA, "blah"); // 12
handler->queue(LOK_CALLBACK_SET_PART, "1"); // 13
handler->queue(LOK_CALLBACK_STATE_CHANGED, ".uno:AssignLayout=20"); // Superseeded
@@ -1338,6 +1338,9 @@ void DesktopLOKTest::testNotificationCompression()
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, (int)std::get<0>(notifs[i]));
CPPUNIT_ASSERT_EQUAL(std::string(""), std::get<1>(notifs[i++]));
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("15, 25, 15, 10"), std::get<1>(notifs[i++]));
+
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_STATE_CHANGED, (int)std::get<0>(notifs[i]));
CPPUNIT_ASSERT_EQUAL(std::string(""), std::get<1>(notifs[i++]));
@@ -1350,20 +1353,17 @@ void DesktopLOKTest::testNotificationCompression()
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_MOUSE_POINTER, (int)std::get<0>(notifs[i]));
CPPUNIT_ASSERT_EQUAL(std::string("text"), std::get<1>(notifs[i++]));
- CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
- CPPUNIT_ASSERT_EQUAL(std::string("15 25 15 10"), std::get<1>(notifs[i++]));
-
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_TEXT_SELECTION, (int)std::get<0>(notifs[i]));
CPPUNIT_ASSERT_EQUAL(std::string(""), std::get<1>(notifs[i++]));
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_TEXT_SELECTION_START, (int)std::get<0>(notifs[i]));
- CPPUNIT_ASSERT_EQUAL(std::string("15 25 15 10"), std::get<1>(notifs[i++]));
+ CPPUNIT_ASSERT_EQUAL(std::string("15, 25, 15, 10"), std::get<1>(notifs[i++]));
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_TEXT_SELECTION_END, (int)std::get<0>(notifs[i]));
- CPPUNIT_ASSERT_EQUAL(std::string("15 25 15 10"), std::get<1>(notifs[i++]));
+ CPPUNIT_ASSERT_EQUAL(std::string("15, 25, 15, 10"), std::get<1>(notifs[i++]));
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_CELL_CURSOR, (int)std::get<0>(notifs[i]));
- CPPUNIT_ASSERT_EQUAL(std::string("15 25 15 10"), std::get<1>(notifs[i++]));
+ CPPUNIT_ASSERT_EQUAL(std::string("15, 25, 15, 10"), std::get<1>(notifs[i++]));
CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_CURSOR_VISIBLE, (int)std::get<0>(notifs[i]));
CPPUNIT_ASSERT_EQUAL(std::string(""), std::get<1>(notifs[i++]));
@@ -1381,8 +1381,6 @@ void DesktopLOKTest::testNotificationCompression()
void DesktopLOKTest::testTileInvalidationCompression()
{
LibLODocument_Impl* pDocument = loadDoc("blank_text.odt");
- std::vector<std::tuple<int, std::string>> notifs;
- std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, &notifs));
comphelper::LibreOfficeKit::setPartInInvalidation(true);
comphelper::ScopeGuard aGuard([]()
@@ -1390,23 +1388,129 @@ void DesktopLOKTest::testTileInvalidationCompression()
comphelper::LibreOfficeKit::setPartInInvalidation(false);
});
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0");
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 2147483767, 2147483767, 0");
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0");
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 300, 300, 0");
- handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 0");
+ // Single part merging
+ {
+ std::vector<std::tuple<int, std::string>> notifs;
+ std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, &notifs));
- Scheduler::ProcessEventsToIdle();
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-100, -50, 500, 650, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "100, 100, 200, 200, 0");
-/*
- // Broken on Tinderbox, for whatever unreproducible reason.
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), notifs.size());
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), notifs.size());
+ size_t i = 0;
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 400, 600, 0"), std::get<1>(notifs[i++]));
+ }
- size_t i = 0;
- CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
- CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 2147483767, 2147483767, 0"), std::get<1>(notifs[i++]));
-*/
+ // Part Number
+ {
+ std::vector<std::tuple<int, std::string>> notifs;
+ std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, &notifs));
+
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 1"); // Different part
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, 2"); // Invalid
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 200, 200, 0"); // Inside first
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 1"); // Invalid
+
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), notifs.size());
+
+ size_t i = 0;
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 1"), std::get<1>(notifs[i++]));
+
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 239, 239, 0"), std::get<1>(notifs[i++]));
+ }
+
+ // All Parts
+ {
+ std::vector<std::tuple<int, std::string>> notifs;
+ std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, &notifs));
+
+ 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
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, -1"); // Invalid
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 200, 200, -1"); // 0: All parts
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, -1"); // Invalid
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-100, -100, 1200, 1200, -1"); // 0: All parts
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 3"); // Overlapped
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "1000, 1000, 1239, 1239, 2"); // 1: Unique region
+
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), notifs.size());
+
+ size_t i = 0;
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 1100, 1100, -1"), std::get<1>(notifs[i++]));
+
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("1000, 1000, 1239, 1239, 2"), std::get<1>(notifs[i++]));
+ }
+
+ // All Parts (partial)
+ {
+ std::vector<std::tuple<int, std::string>> notifs;
+ std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, &notifs));
+
+ 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
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 0, 0, -1"); // Invalid
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "150, 150, 50, 50, -1"); // 2: All-parts
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, -1"); // Invalid
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "150, 150, 40, 40, 3"); // Overlapped w/ 2
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 200, 200, 4"); // 3: Unique
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "1000, 1000, 1239, 1239, 1"); // 4: Unique
+
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), notifs.size());
+
+ size_t i = 0;
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 0"), std::get<1>(notifs[i++]));
+
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 100, 100, 1"), std::get<1>(notifs[i++]));
+
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("150, 150, 50, 50, -1"), std::get<1>(notifs[i++]));
+
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 200, 200, 4"), std::get<1>(notifs[i++]));
+
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("1000, 1000, 1239, 1239, 1"), std::get<1>(notifs[i++]));
+ }
+
+ // Merge with "EMPTY"
+ {
+ std::vector<std::tuple<int, std::string>> notifs;
+ std::unique_ptr<CallbackFlushHandler> handler(new CallbackFlushHandler(pDocument, callbackCompressionTest, &notifs));
+
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 239, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "EMPTY, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, 239, 240, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "-121, -121, 300, 300, 0");
+ handler->queue(LOK_CALLBACK_INVALIDATE_TILES, "0, 0, -32767, -32767, 0");
+
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), notifs.size());
+
+ size_t i = 0;
+ CPPUNIT_ASSERT_EQUAL((int)LOK_CALLBACK_INVALIDATE_TILES, (int)std::get<0>(notifs[i]));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 1000000000, 1000000000, 0"), std::get<1>(notifs[i++]));
+ }
}
void DesktopLOKTest::testPartInInvalidation()
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index d3835472dc8f..268f37286213 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -343,7 +343,7 @@ struct RectangleAndPart
int m_nPart;
RectangleAndPart()
- : m_nPart(-1)
+ : m_nPart(INT_MIN) // -1 is reserved to mean "all parts".
{
}
@@ -351,17 +351,23 @@ struct RectangleAndPart
{
std::stringstream ss;
ss << m_aRectangle.toString().getStr();
- if (m_nPart != -1)
+ if (m_nPart >= -1)
ss << ", " << m_nPart;
return ss.str().c_str();
}
- /// Infinite Rectangle is when both dimensions are >= 2e7.
- // ~2 billion twips is INT_MAX, which is full-area.
+ /// Infinite Rectangle is both sides are
+ /// equal or longer than SfxLokHelper::MaxTwips.
bool isInfinite() const
{
- return m_aRectangle.GetWidth() >= 2e7 &&
- m_aRectangle.GetHeight() >= 2e7;
+ return m_aRectangle.GetWidth() >= SfxLokHelper::MaxTwips &&
+ m_aRectangle.GetHeight() >= SfxLokHelper::MaxTwips;
+ }
+
+ /// Empty Rectangle is when it has zero dimensions.
+ bool isEmpty() const
+ {
+ return m_aRectangle.IsEmpty();
}
static RectangleAndPart Create(const std::string& rPayload)
@@ -369,7 +375,7 @@ struct RectangleAndPart
RectangleAndPart aRet;
if (rPayload.find("EMPTY") == 0) // payload starts with "EMPTY"
{
- aRet.m_aRectangle = Rectangle(0, 0, INT_MAX, INT_MAX);
+ aRet.m_aRectangle = Rectangle(0, 0, SfxLokHelper::MaxTwips, SfxLokHelper::MaxTwips);
if (comphelper::LibreOfficeKit::isPartInInvalidation())
aRet.m_nPart = std::stol(rPayload.substr(6));
@@ -377,15 +383,41 @@ struct RectangleAndPart
}
std::istringstream aStream(rPayload);
- long nLeft, nTop, nRight, nBottom;
- long nPart = -1;
+ long nLeft, nTop, nWidth, nHeight;
+ long nPart = INT_MIN;
char nComma;
if (comphelper::LibreOfficeKit::isPartInInvalidation())
- aStream >> nLeft >> nComma >> nTop >> nComma >> nRight >> nComma >> nBottom >> nComma >> nPart;
+ {
+ aStream >> nLeft >> nComma >> nTop >> nComma >> nWidth >> nComma >> nHeight >> nComma >> nPart;
+ }
else
- aStream >> nLeft >> nComma >> nTop >> nComma >> nRight >> nComma >> nBottom;
+ {
+ aStream >> nLeft >> nComma >> nTop >> nComma >> nWidth >> nComma >> nHeight;
+ }
+
+ if (nWidth > 0 && nHeight > 0)
+ {
+ // The top-left corner starts at (0, 0).
+ // Anything negative is invalid.
+ if (nLeft < 0)
+ {
+ nWidth += nLeft;
+ nLeft = 0;
+ }
+
+ if (nTop < 0)
+ {
+ nHeight += nTop;
+ nTop = 0;
+ }
+
+ if (nWidth > 0 && nHeight > 0)
+ {
+ aRet.m_aRectangle = Rectangle(nLeft, nTop, nLeft + nWidth, nTop + nHeight);
+ }
+ }
+ // else leave empty rect.
- aRet.m_aRectangle = Rectangle(nLeft, nTop, nLeft + nRight, nTop + nBottom);
aRet.m_nPart = nPart;
return aRet;
}
@@ -602,6 +634,7 @@ void CallbackFlushHandler::queue(const int type, const char* data)
{
std::string payload(data ? data : "(nil)");
//SAL_WARN("lok", "Queue: " << type << " : " << payload);
+
if (m_bPartTilePainting)
{
// We drop notifications when this is set, except for important ones.
@@ -673,24 +706,6 @@ void CallbackFlushHandler::queue(const int type, const char* data)
break;
}
- // if we have to invalidate all tiles, we can skip any new tile invalidation
- if (type == LOK_CALLBACK_INVALIDATE_TILES)
- {
- const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
- [] (const queue_type::value_type& elem) { return (elem.first == LOK_CALLBACK_INVALIDATE_TILES); });
-
- if (pos != m_queue.rend())
- {
- RectangleAndPart rcOld = RectangleAndPart::Create(pos->second);
- RectangleAndPart rcNew = RectangleAndPart::Create(payload);
- if (rcOld.isInfinite() && rcOld.m_nPart == rcNew.m_nPart)
- {
- SAL_WARN("lok", "Skipping queue [" << type << "]: [" << payload << "] since all tiles need to be invalidated.");
- return;
- }
- }
- }
-
if (type == LOK_CALLBACK_TEXT_SELECTION && payload.empty())
{
const auto& posStart = std::find_if(m_queue.rbegin(), m_queue.rend(),
@@ -773,20 +788,50 @@ void CallbackFlushHandler::queue(const int type, const char* data)
{
RectangleAndPart rcNew = RectangleAndPart::Create(payload);
//SAL_WARN("lok", "New: " << rcNew.toString());
+ if (rcNew.isEmpty())
+ {
+ SAL_WARN("lok", "Skipping invalid event [" << type << "]: [" << payload << "].");
+ return;
+ }
+
+ // If we have to invalidate all tiles, we can skip any new tile invalidation.
+ // Find the last INVALIDATE_TILES entry, if any to see if it's invalidate-all.
+ const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
+ [] (const queue_type::value_type& elem) { return (elem.first == LOK_CALLBACK_INVALIDATE_TILES); });
+ if (pos != m_queue.rend())
+ {
+ RectangleAndPart rcOld = RectangleAndPart::Create(pos->second);
+ if (rcOld.isInfinite() && (rcOld.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart))
+ {
+ SAL_WARN("lok", "Skipping queue [" << type << "]: [" << payload << "] since all tiles need to be invalidated.");
+ return;
+ }
+
+ if (rcOld.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart)
+ {
+ // If fully overlapping.
+ if (rcOld.m_aRectangle.IsInside(rcNew.m_aRectangle))
+ {
+ SAL_WARN("lok", "Skipping queue [" << type << "]: [" << payload << "] since overlaps existing all-parts.");
+ return;
+ }
+ }
+ }
+
if (rcNew.isInfinite())
{
SAL_WARN("lok", "Have Empty [" << type << "]: [" << payload << "] so removing all with part " << rcNew.m_nPart << ".");
removeAll(
- [type, &rcNew] (const queue_type::value_type& elem) {
- if (elem.first == type)
+ [&rcNew] (const queue_type::value_type& elem) {
+ if (elem.first == LOK_CALLBACK_INVALIDATE_TILES)
{
+ // Remove exiting if new is all-encompasing, or if of the same part.
const RectangleAndPart rcOld = RectangleAndPart::Create(elem.second);
- return (rcOld.m_nPart == rcNew.m_nPart);
- }
- else
- {
- return false;
+ return (rcNew.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart);
}
+
+ // Keep others.
+ return false;
}
);
}
@@ -794,30 +839,55 @@ void CallbackFlushHandler::queue(const int type, const char* data)
{
const auto rcOrig = rcNew;
- //SAL_WARN("lok", "Have [" << type << "]: [" << payload << "] so merging overlapping.");
+ SAL_WARN("lok", "Have [" << type << "]: [" << payload << "] so merging overlapping.");
removeAll(
- [type, &rcNew] (const queue_type::value_type& elem) {
- if (elem.first == type)
+ [&rcNew] (const queue_type::value_type& elem) {
+ if (elem.first == LOK_CALLBACK_INVALIDATE_TILES)
{
const RectangleAndPart rcOld = RectangleAndPart::Create(elem.second);
- if (rcOld.m_nPart != rcNew.m_nPart)
+ if (rcNew.m_nPart != -1 && rcOld.m_nPart != -1 && rcOld.m_nPart != rcNew.m_nPart)
+ {
+ SAL_WARN("lok", "Nothing to merge between new: " << rcNew.toString() << ", and old: " << rcOld.toString());
return false;
+ }
- const Rectangle rcOverlap = rcNew.m_aRectangle.GetIntersection(rcOld.m_aRectangle);
- bool bOverlap = (rcOverlap.GetWidth() > 0 && rcOverlap.GetHeight() > 0);
- SAL_WARN("lok", "Merging " << rcNew.toString() << " & " << rcOld.toString() << " => " <<
- rcOverlap.toString() << " Overlap: " << bOverlap);
- if (bOverlap)
+ if (rcNew.m_nPart == -1)
{
- rcNew.m_aRectangle.Union(rcOld.m_aRectangle);
- SAL_WARN("lok", "Merged: " << rcNew.toString());
+ // Don't merge unless fully overlaped.
+ SAL_WARN("lok", "New " << rcNew.toString() << " has " << rcOld.toString() << "?");
+ if (rcNew.m_aRectangle.IsInside(rcOld.m_aRectangle))
+ {
+ SAL_WARN("lok", "New " << rcNew.toString() << " engulfs old " << rcOld.toString() << ".");
+ return true;
+ }
+ }
+ else if (rcOld.m_nPart == -1)
+ {
+ // Don't merge unless fully overlaped.
+ SAL_WARN("lok", "Old " << rcOld.toString() << " has " << rcNew.toString() << "?");
+ if (rcOld.m_aRectangle.IsInside(rcNew.m_aRectangle))
+ {
+ SAL_WARN("lok", "New " << rcNew.toString() << " engulfs old " << rcOld.toString() << ".");
+ return true;
+ }
+ }
+ else
+ {
+ const Rectangle rcOverlap = rcNew.m_aRectangle.GetIntersection(rcOld.m_aRectangle);
+ const bool bOverlap = !rcOverlap.IsEmpty();
+ SAL_WARN("lok", "Merging " << rcNew.toString() << " & " << rcOld.toString() << " => " <<
+ rcOverlap.toString() << " Overlap: " << bOverlap);
+ if (bOverlap)
+ {
+ rcNew.m_aRectangle.Union(rcOld.m_aRectangle);
+ SAL_WARN("lok", "Merged: " << rcNew.toString());
+ return true;
+ }
}
- return bOverlap;
- }
- else
- {
- return false;
}
+
+ // Keep others.
+ return false;
}
);
@@ -829,10 +899,10 @@ void CallbackFlushHandler::queue(const int type, const char* data)
{
SAL_WARN("lok", "Error: merged rect smaller.");
}
-
- payload = rcNew.toString().getStr();
}
}
+
+ payload = rcNew.toString().getStr();
}
break;
@@ -857,7 +927,8 @@ void CallbackFlushHandler::queue(const int type, const char* data)
}
m_queue.emplace_back(type, payload);
- SAL_WARN("lok", "Queued [" << type << "]: [" << payload << "] to have " << m_queue.size() << " entries.");
+ SAL_WARN("lok", "Queued #" << (m_queue.size() - 1) <<
+ " [" << type << "]: [" << payload << "] to have " << m_queue.size() << " entries.");
lock.unlock();
if (!IsActive())