From 03989b70e005599fc4dc290d7689a014a25c48de Mon Sep 17 00:00:00 2001 From: Pranav Kant Date: Wed, 8 Nov 2017 19:45:13 +0530 Subject: lokdialog: Compress invalidation callbacks in Callback flush handler Change-Id: Id76bde54395611f509a5d4be6bb2ac9b7f6ed1c0 Reviewed-on: https://gerrit.libreoffice.org/44474 Tested-by: Jenkins Reviewed-by: pranavk --- desktop/source/lib/init.cxx | 133 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) (limited to 'desktop') diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index a5df72c72ac9..45a59345375a 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1022,6 +1022,139 @@ void CallbackFlushHandler::queue(const int type, const char* data) } } break; + + case LOK_CALLBACK_DIALOG: + { + // reading JSON by boost might be slow? + boost::property_tree::ptree aTree; + std::stringstream aStream(payload); + boost::property_tree::read_json(aStream, aTree); + const std::string aDialogId = aTree.get("dialogId", ""); + if (aTree.get("action", "") == "invalidate") + { + std::string aRectStr = aTree.get("rectangle", ""); + // no 'rectangle' field => invalidate all of the dialog => + // remove all previous dialog part invalidations + if (aRectStr.empty()) + { + removeAll([&aDialogId] (const queue_type::value_type& elem) { + if (elem.first == LOK_CALLBACK_DIALOG) + { + boost::property_tree::ptree aOldTree; + std::stringstream aOldStream(elem.second); + boost::property_tree::read_json(aOldStream, aOldTree); + const std::string aOldDialogId = aOldTree.get("dialogId", ""); + if (aOldTree.get("action", "") == "invalidate" && + aDialogId == aOldDialogId) + { + return true; + } + } + return false; + }); + } + else + { + // if we have to invalidate all of the dialog, ignore + // any part invalidation message + const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(), + [&aDialogId] (const queue_type::value_type& elem) + { + if (elem.first != LOK_CALLBACK_DIALOG) + return false; + + boost::property_tree::ptree aOldTree; + std::stringstream aOldStream(elem.second); + boost::property_tree::read_json(aOldStream, aOldTree); + const std::string aOldDialogId = aOldTree.get("dialogId", ""); + if (aOldTree.get("action", "") == "invalidate" && + aDialogId == aOldDialogId && + aOldTree.get("rectangle", "").empty()) + { + return true; + } + return false; + }); + + // we found a invalidate-all dialog callback + if (pos != m_queue.rend()) + { + SAL_INFO("lok.dialog", "Skipping queue [" << type << "]: [" << payload << "] since whole dialog 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 = tools::Rectangle(nLeft, nTop, nLeft + nWidth, nTop + nHeight); + bool currentIsRedundant = false; + removeAll([&aNewRect, &aDialogId, ¤tIsRedundant] (const queue_type::value_type& elem) { + if (elem.first != LOK_CALLBACK_DIALOG) + return false; + + boost::property_tree::ptree aOldTree; + std::stringstream aOldStream(elem.second); + boost::property_tree::read_json(aOldStream, aOldTree); + if (aOldTree.get("action", "") == "invalidate") + { + const std::string aOldDialogId = aOldTree.get("dialogId", ""); + std::string aOldRectStr = aOldTree.get("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 (aDialogId == aOldDialogId) + { + // 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()); + std::stringstream aJSONStream; + boost::property_tree::write_json(aJSONStream, aTree); + payload = aJSONStream.str(); + } + } + } + break; } } -- cgit