diff options
author | Ashod Nakashian <ashod.nakashian@collabora.co.uk> | 2019-05-08 11:45:49 -0400 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2019-07-25 19:22:44 +0200 |
commit | 5f4fa7bf17542f74e29082b065b0e7bac6af53ef (patch) | |
tree | 2d62aeb1ed47f1216cf63236a4c75b1828d764df /desktop | |
parent | 01b1e44f03bd3f9c2e56712d8a75719c2b7b906d (diff) |
LOK: Refactor large event queueing cases
This makes it more readable and reduces indentations.
No functional change intended.
(cherry picked from commit 570a3c5361d58635e4d0ac8baf6df787bd2290ad)
Change-Id: I129ecff9083c459d633c0965eab6e06ba3dcf499
Reviewed-on: https://gerrit.libreoffice.org/76320
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/inc/lib/init.hxx | 2 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 566 |
2 files changed, 303 insertions, 265 deletions
diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index b63794d2a9de..3587ba003e37 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -131,6 +131,8 @@ namespace desktop { private: bool removeAll(const std::function<bool (const queue_type::value_type&)>& rTestFunc); + bool processInvalidateTilesEvent(CallbackData& aCallbackData); + bool processWindowEvent(CallbackData& aCallbackData); queue_type m_queue; std::map<int, std::string> m_states; diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 56d685bc5d4b..27ae125e4098 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1139,124 +1139,8 @@ void CallbackFlushHandler::queue(const int type, const char* data) break; case LOK_CALLBACK_INVALIDATE_TILES: - { - RectangleAndPart& rcNew = aCallbackData.setRectangleAndPart(payload); - if (rcNew.isEmpty()) - { - SAL_INFO("lok", "Skipping invalid event [" << type << "]: [" << payload << "]."); + if (processInvalidateTilesEvent(aCallbackData)) 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.Type == LOK_CALLBACK_INVALIDATE_TILES); }); - if (pos != m_queue.rend()) - { - const RectangleAndPart& rcOld = pos->getRectangleAndPart(); - if (rcOld.isInfinite() && (rcOld.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart)) - { - SAL_INFO("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_INFO("lok", "Skipping queue [" << type << "]: [" << payload << "] since overlaps existing all-parts."); - return; - } - } - } - - if (rcNew.isInfinite()) - { - SAL_INFO("lok", "Have Empty [" << type << "]: [" << payload << "] so removing all with part " << rcNew.m_nPart << "."); - removeAll( - [&rcNew] (const queue_type::value_type& elem) { - if (elem.Type == LOK_CALLBACK_INVALIDATE_TILES) - { - // Remove exiting if new is all-encompassing, or if of the same part. - const RectangleAndPart rcOld = RectangleAndPart::Create(elem.PayloadString); - return (rcNew.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart); - } - - // Keep others. - return false; - } - ); - } - else - { - const auto rcOrig = rcNew; - - SAL_INFO("lok", "Have [" << type << "]: [" << payload << "] so merging overlapping."); - removeAll( - [&rcNew] (const queue_type::value_type& elem) { - if (elem.Type == LOK_CALLBACK_INVALIDATE_TILES) - { - const RectangleAndPart& rcOld = elem.getRectangleAndPart(); - if (rcNew.m_nPart != -1 && rcOld.m_nPart != -1 && rcOld.m_nPart != rcNew.m_nPart) - { - SAL_INFO("lok", "Nothing to merge between new: " << rcNew.toString() << ", and old: " << rcOld.toString()); - return false; - } - - if (rcNew.m_nPart == -1) - { - // Don't merge unless fully overlapped. - SAL_INFO("lok", "New " << rcNew.toString() << " has " << rcOld.toString() << "?"); - if (rcNew.m_aRectangle.IsInside(rcOld.m_aRectangle)) - { - SAL_INFO("lok", "New " << rcNew.toString() << " engulfs old " << rcOld.toString() << "."); - return true; - } - } - else if (rcOld.m_nPart == -1) - { - // Don't merge unless fully overlapped. - SAL_INFO("lok", "Old " << rcOld.toString() << " has " << rcNew.toString() << "?"); - if (rcOld.m_aRectangle.IsInside(rcNew.m_aRectangle)) - { - SAL_INFO("lok", "New " << rcNew.toString() << " engulfs old " << rcOld.toString() << "."); - return true; - } - } - else - { - const tools::Rectangle rcOverlap = rcNew.m_aRectangle.GetIntersection(rcOld.m_aRectangle); - const bool bOverlap = !rcOverlap.IsEmpty(); - SAL_INFO("lok", "Merging " << rcNew.toString() << " & " << rcOld.toString() << " => " << - rcOverlap.toString() << " Overlap: " << bOverlap); - if (bOverlap) - { - rcNew.m_aRectangle.Union(rcOld.m_aRectangle); - SAL_INFO("lok", "Merged: " << rcNew.toString()); - return true; - } - } - } - - // Keep others. - return false; - } - ); - - if (rcNew.m_aRectangle != rcOrig.m_aRectangle) - { - SAL_INFO("lok", "Replacing: " << rcOrig.toString() << " by " << rcNew.toString()); - if (rcNew.m_aRectangle.GetWidth() < rcOrig.m_aRectangle.GetWidth() || - rcNew.m_aRectangle.GetHeight() < rcOrig.m_aRectangle.GetHeight()) - { - SAL_WARN("lok", "Error: merged rect smaller."); - } - } - } - - aCallbackData.setRectangleAndPart(rcNew); - } break; // State changes with same name override previous ones with a different value. @@ -1278,154 +1162,8 @@ void CallbackFlushHandler::queue(const int type, const char* data) break; case LOK_CALLBACK_WINDOW: - { - // reading JSON by boost might be slow? - boost::property_tree::ptree& aTree = aCallbackData.setJson(payload); - const unsigned nLOKWindowId = aTree.get<unsigned>("id", 0); - if (aTree.get<std::string>("action", "") == "invalidate") - { - std::string aRectStr = aTree.get<std::string>("rectangle", ""); - // no 'rectangle' field => invalidate all of the window => - // remove all previous window part invalidations - if (aRectStr.empty()) - { - removeAll([&nLOKWindowId] (const queue_type::value_type& elem) { - if (elem.Type == LOK_CALLBACK_WINDOW) - { - const boost::property_tree::ptree& aOldTree = elem.getJson(); - const unsigned nOldDialogId = aOldTree.get<unsigned>("id", 0); - if (aOldTree.get<std::string>("action", "") == "invalidate" && - nLOKWindowId == nOldDialogId) - { - return true; - } - } - return false; - }); - } - else - { - // if we have to invalidate all of the window, ignore - // any part invalidation message - const auto invAllExist = std::any_of(m_queue.rbegin(), m_queue.rend(), - [&nLOKWindowId] (const queue_type::value_type& elem) - { - if (elem.Type != LOK_CALLBACK_WINDOW) - return false; - - const boost::property_tree::ptree& aOldTree = elem.getJson(); - const unsigned nOldDialogId = aOldTree.get<unsigned>("id", 0); - return aOldTree.get<std::string>("action", "") == "invalidate" && - nLOKWindowId == nOldDialogId && - aOldTree.get<std::string>("rectangle", "").empty(); - }); - - // we found an invalidate-all window callback - if (invAllExist) - { - SAL_INFO("lok.dialog", "Skipping queue [" << type << "]: [" << payload << "] since whole window needs to be invalidated."); - return; - } - - std::istringstream aRectStream(aRectStr); - long nLeft, nTop, nWidth, nHeight; - char nComma; - aRectStream >> nLeft >> nComma >> nTop >> nComma >> nWidth >> nComma >> nHeight; - tools::Rectangle aNewRect(nLeft, nTop, nLeft + nWidth, nTop + nHeight); - bool currentIsRedundant = false; - removeAll([&aNewRect, &nLOKWindowId, ¤tIsRedundant] (const queue_type::value_type& elem) { - if (elem.Type != LOK_CALLBACK_WINDOW) - return false; - - const boost::property_tree::ptree& aOldTree = elem.getJson(); - if (aOldTree.get<std::string>("action", "") == "invalidate") - { - const unsigned nOldDialogId = aOldTree.get<unsigned>("id", 0); - std::string aOldRectStr = aOldTree.get<std::string>("rectangle", ""); - // not possible that we encounter an empty - // rectangle here; we already handled this - // case before - std::istringstream aOldRectStream(aOldRectStr); - long nOldLeft, nOldTop, nOldWidth, nOldHeight; - char nOldComma; - aOldRectStream >> nOldLeft >> nOldComma >> nOldTop >> nOldComma >> nOldWidth >> nOldComma >> nOldHeight; - tools::Rectangle aOldRect = tools::Rectangle(nOldLeft, nOldTop, nOldLeft + nOldWidth, nOldTop + nOldHeight); - - if (nLOKWindowId == nOldDialogId) - { - // new one engulfs the old one? - if (aNewRect.IsInside(aOldRect)) - { - SAL_INFO("lok.dialog", "New " << aNewRect.toString() << " engulfs old " << aOldRect.toString() << "."); - return true; - } - // old one engulfs the new one? - else if (aOldRect.IsInside(aNewRect)) - { - SAL_INFO("lok.dialog", "Old " << aOldRect.toString() << " engulfs new " << aNewRect.toString() << "."); - // we have a rectangle in the queue - // already that makes the current - // Callback useless - currentIsRedundant = true; - return false; - } - else - { - SAL_INFO("lok.dialog", "Merging " << aNewRect.toString() << " & " << aOldRect.toString()); - aNewRect.Union(aOldRect); - SAL_INFO("lok.dialog", "Merged: " << aNewRect.toString()); - return true; - } - } - } - - // keep rest - return false; - }); - - if (currentIsRedundant) - { - SAL_INFO("lok.dialog", "Current payload is engulfed by one already in the queue. Skipping redundant payload: " << aNewRect.toString()); - return; - } - - aTree.put("rectangle", aNewRect.toString().getStr()); - aCallbackData.setJson(aTree); - assert(aCallbackData.validate() && "Validation after setJson failed!"); - } - } - else if (aTree.get<std::string>("action", "") == "created") - { - // Remove all previous actions on same dialog, if we are creating it anew. - removeAll([&nLOKWindowId](const queue_type::value_type& elem) { - if (elem.Type == LOK_CALLBACK_WINDOW) - { - const boost::property_tree::ptree& aOldTree = elem.getJson(); - if (nLOKWindowId == aOldTree.get<unsigned>("id", 0)) - return true; - } - return false; - }); - } - else if (aTree.get<std::string>("action", "") == "size_changed") - { - // A size change is practically re-creation of the window. - // But at a minimum it's a full invalidation. - removeAll([&nLOKWindowId](const queue_type::value_type& elem) { - if (elem.Type == LOK_CALLBACK_WINDOW) - { - const boost::property_tree::ptree& aOldTree = elem.getJson(); - if (nLOKWindowId == aOldTree.get<unsigned>("id", 0)) - { - const std::string aOldAction = aOldTree.get<std::string>("action", ""); - if (aOldAction == "invalidate") - return true; - } - } - return false; - }); - } - } + if (processWindowEvent(aCallbackData)) + return; break; } } @@ -1458,6 +1196,304 @@ void CallbackFlushHandler::queue(const int type, const char* data) } } +bool CallbackFlushHandler::processInvalidateTilesEvent(CallbackData& aCallbackData) +{ + const std::string& payload = aCallbackData.PayloadString; + const int type = aCallbackData.Type; + + RectangleAndPart& rcNew = aCallbackData.setRectangleAndPart(payload); + if (rcNew.isEmpty()) + { + SAL_INFO("lok", "Skipping invalid event [" << type << "]: [" << payload << "]."); + return true; + } + + // 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.Type == LOK_CALLBACK_INVALIDATE_TILES); + }); + if (pos != m_queue.rend()) + { + const RectangleAndPart& rcOld = pos->getRectangleAndPart(); + if (rcOld.isInfinite() && (rcOld.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart)) + { + SAL_INFO("lok", "Skipping queue [" << type << "]: [" << payload + << "] since all tiles need to be invalidated."); + return true; + } + + if (rcOld.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart) + { + // If fully overlapping. + if (rcOld.m_aRectangle.IsInside(rcNew.m_aRectangle)) + { + SAL_INFO("lok", "Skipping queue [" << type << "]: [" << payload + << "] since overlaps existing all-parts."); + return true; + } + } + } + + if (rcNew.isInfinite()) + { + SAL_INFO("lok", "Have Empty [" << type << "]: [" << payload + << "] so removing all with part " << rcNew.m_nPart << "."); + removeAll([&rcNew](const queue_type::value_type& elem) { + if (elem.Type == LOK_CALLBACK_INVALIDATE_TILES) + { + // Remove exiting if new is all-encompassing, or if of the same part. + const RectangleAndPart rcOld = RectangleAndPart::Create(elem.PayloadString); + return (rcNew.m_nPart == -1 || rcOld.m_nPart == rcNew.m_nPart); + } + + // Keep others. + return false; + }); + } + else + { + const auto rcOrig = rcNew; + + SAL_INFO("lok", "Have [" << type << "]: [" << payload << "] so merging overlapping."); + removeAll([&rcNew](const queue_type::value_type& elem) { + if (elem.Type == LOK_CALLBACK_INVALIDATE_TILES) + { + const RectangleAndPart& rcOld = elem.getRectangleAndPart(); + if (rcNew.m_nPart != -1 && rcOld.m_nPart != -1 && rcOld.m_nPart != rcNew.m_nPart) + { + SAL_INFO("lok", "Nothing to merge between new: " + << rcNew.toString() << ", and old: " << rcOld.toString()); + return false; + } + + if (rcNew.m_nPart == -1) + { + // Don't merge unless fully overlaped. + SAL_INFO("lok", "New " << rcNew.toString() << " has " << rcOld.toString() + << "?"); + if (rcNew.m_aRectangle.IsInside(rcOld.m_aRectangle)) + { + SAL_INFO("lok", "New " << rcNew.toString() << " engulfs old " + << rcOld.toString() << "."); + return true; + } + } + else if (rcOld.m_nPart == -1) + { + // Don't merge unless fully overlaped. + SAL_INFO("lok", "Old " << rcOld.toString() << " has " << rcNew.toString() + << "?"); + if (rcOld.m_aRectangle.IsInside(rcNew.m_aRectangle)) + { + SAL_INFO("lok", "New " << rcNew.toString() << " engulfs old " + << rcOld.toString() << "."); + return true; + } + } + else + { + const tools::Rectangle rcOverlap + = rcNew.m_aRectangle.GetIntersection(rcOld.m_aRectangle); + const bool bOverlap = !rcOverlap.IsEmpty(); + SAL_INFO("lok", "Merging " << rcNew.toString() << " & " << rcOld.toString() + << " => " << rcOverlap.toString() + << " Overlap: " << bOverlap); + if (bOverlap) + { + rcNew.m_aRectangle.Union(rcOld.m_aRectangle); + SAL_INFO("lok", "Merged: " << rcNew.toString()); + return true; + } + } + } + + // Keep others. + return false; + }); + + if (rcNew.m_aRectangle != rcOrig.m_aRectangle) + { + SAL_INFO("lok", "Replacing: " << rcOrig.toString() << " by " << rcNew.toString()); + if (rcNew.m_aRectangle.GetWidth() < rcOrig.m_aRectangle.GetWidth() + || rcNew.m_aRectangle.GetHeight() < rcOrig.m_aRectangle.GetHeight()) + { + SAL_WARN("lok", "Error: merged rect smaller."); + } + } + } + + aCallbackData.setRectangleAndPart(rcNew); + // Queue this one. + return false; +} + +bool CallbackFlushHandler::processWindowEvent(CallbackData& aCallbackData) +{ + const std::string& payload = aCallbackData.PayloadString; + const int type = aCallbackData.Type; + + boost::property_tree::ptree& aTree = aCallbackData.setJson(payload); + const unsigned nLOKWindowId = aTree.get<unsigned>("id", 0); + if (aTree.get<std::string>("action", "") == "invalidate") + { + std::string aRectStr = aTree.get<std::string>("rectangle", ""); + // no 'rectangle' field => invalidate all of the window => + // remove all previous window part invalidations + if (aRectStr.empty()) + { + removeAll([&nLOKWindowId](const queue_type::value_type& elem) { + if (elem.Type == LOK_CALLBACK_WINDOW) + { + const boost::property_tree::ptree& aOldTree = elem.getJson(); + const unsigned nOldDialogId = aOldTree.get<unsigned>("id", 0); + if (aOldTree.get<std::string>("action", "") == "invalidate" + && nLOKWindowId == nOldDialogId) + { + return true; + } + } + return false; + }); + } + else + { + // if we have to invalidate all of the window, ignore + // any part invalidation message + const auto invAllExist = std::any_of(m_queue.rbegin(), m_queue.rend(), + [&nLOKWindowId] (const queue_type::value_type& elem) + { + if (elem.Type != LOK_CALLBACK_WINDOW) + return false; + + const boost::property_tree::ptree& aOldTree = elem.getJson(); + const unsigned nOldDialogId = aOldTree.get<unsigned>("id", 0); + return aOldTree.get<std::string>("action", "") == "invalidate" && + nLOKWindowId == nOldDialogId && + aOldTree.get<std::string>("rectangle", "").empty(); + }); + + // we found a invalidate-all window callback + if (invAllExist) + { + SAL_INFO("lok.dialog", "Skipping queue [" + << type << "]: [" << payload + << "] since whole window needs to be invalidated."); + return true; + } + + std::istringstream aRectStream(aRectStr); + long nLeft, nTop, nWidth, nHeight; + char nComma; + aRectStream >> nLeft >> nComma >> nTop >> nComma >> nWidth >> nComma >> nHeight; + tools::Rectangle aNewRect(nLeft, nTop, nLeft + nWidth, nTop + nHeight); + bool currentIsRedundant = false; + removeAll([&aNewRect, &nLOKWindowId, + ¤tIsRedundant](const queue_type::value_type& elem) { + if (elem.Type != LOK_CALLBACK_WINDOW) + return false; + + const boost::property_tree::ptree& aOldTree = elem.getJson(); + if (aOldTree.get<std::string>("action", "") == "invalidate") + { + const unsigned nOldDialogId = aOldTree.get<unsigned>("id", 0); + std::string aOldRectStr = aOldTree.get<std::string>("rectangle", ""); + // not possible that we encounter an empty + // rectangle here; we already handled this + // case before + std::istringstream aOldRectStream(aOldRectStr); + long nOldLeft, nOldTop, nOldWidth, nOldHeight; + char nOldComma; + aOldRectStream >> nOldLeft >> nOldComma >> nOldTop >> nOldComma >> nOldWidth + >> nOldComma >> nOldHeight; + tools::Rectangle aOldRect = tools::Rectangle( + nOldLeft, nOldTop, nOldLeft + nOldWidth, nOldTop + nOldHeight); + + if (nLOKWindowId == nOldDialogId) + { + // new one engulfs the old one? + if (aNewRect.IsInside(aOldRect)) + { + SAL_INFO("lok.dialog", "New " << aNewRect.toString() << " engulfs old " + << aOldRect.toString() << "."); + return true; + } + // old one engulfs the new one? + else if (aOldRect.IsInside(aNewRect)) + { + SAL_INFO("lok.dialog", "Old " << aOldRect.toString() << " engulfs new " + << aNewRect.toString() << "."); + // we have a rectangle in the queue + // already that makes the current + // Callback useless + currentIsRedundant = true; + return false; + } + else + { + SAL_INFO("lok.dialog", "Merging " << aNewRect.toString() << " & " + << aOldRect.toString()); + aNewRect.Union(aOldRect); + SAL_INFO("lok.dialog", "Merged: " << aNewRect.toString()); + return true; + } + } + } + + // keep rest + return false; + }); + + if (currentIsRedundant) + { + SAL_INFO("lok.dialog", "Current payload is engulfed by one already in the queue. " + "Skipping redundant payload: " + << aNewRect.toString()); + return true; + } + + aTree.put("rectangle", aNewRect.toString().getStr()); + aCallbackData.setJson(aTree); + assert(aCallbackData.validate() && "Validation after setJson failed!"); + } + } + else if (aTree.get<std::string>("action", "") == "created") + { + // Remove all previous actions on same dialog, if we are creating it anew. + removeAll([&nLOKWindowId](const queue_type::value_type& elem) { + if (elem.Type == LOK_CALLBACK_WINDOW) + { + const boost::property_tree::ptree& aOldTree = elem.getJson(); + if (nLOKWindowId == aOldTree.get<unsigned>("id", 0)) + return true; + } + return false; + }); + } + else if (aTree.get<std::string>("action", "") == "size_changed") + { + // A size change is practically re-creation of the window. + // But at a minimum it's a full invalidation. + removeAll([&nLOKWindowId](const queue_type::value_type& elem) { + if (elem.Type == LOK_CALLBACK_WINDOW) + { + const boost::property_tree::ptree& aOldTree = elem.getJson(); + if (nLOKWindowId == aOldTree.get<unsigned>("id", 0)) + { + const std::string aOldAction = aOldTree.get<std::string>("action", ""); + if (aOldAction == "invalidate") + return true; + } + } + return false; + }); + } + + // Queue this one. + return false; +} + void CallbackFlushHandler::Invoke() { comphelper::ProfileZone aZone("CallbackFlushHander::Invoke"); |