[Libreoffice-commits] online.git: kit/ChildSession.cpp wsd/ClientSession.cpp wsd/ClientSession.hpp

Dennis Francis (via logerrit) logerrit at kemper.freedesktop.org
Wed Jul 8 15:18:53 UTC 2020


 kit/ChildSession.cpp  |    2 
 wsd/ClientSession.cpp |  156 ++++++++++++++++++++++++++++++++++++++++++--------
 wsd/ClientSession.hpp |   20 ++++++
 3 files changed, 153 insertions(+), 25 deletions(-)

New commits:
commit d1b3f4c6af35849e0da7a1148a88f183a4e1101f
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Wed Jul 8 07:10:13 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Wed Jul 8 17:18:33 2020 +0200

    wsd/kit: use splitx/splity in clientvisiblearea message...
    
    to filter tile-invalidation messages, so that the client gets
    invalidations/new tiles for all split panes.
    
    Change-Id: Ifacc452ed6bb43dfd36ff16386fb4a547ec8302b
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/98362
    Tested-by: Jenkins
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Dennis Francis <dennis.francis at collabora.com>

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index c2644e68a..39b9d3b41 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -850,7 +850,7 @@ bool ChildSession::clientVisibleArea(const char* /*buffer*/, int /*length*/, con
     int width;
     int height;
 
-    if (tokens.size() != 5 ||
+    if ((tokens.size() != 5 && tokens.size() != 7) ||
         !getTokenInteger(tokens[1], "x", x) ||
         !getTokenInteger(tokens[2], "y", y) ||
         !getTokenInteger(tokens[3], "width", width) ||
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index b313742ec..abed4c5df 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -58,6 +58,8 @@ ClientSession::ClientSession(
     _state(SessionState::DETACHED),
     _keyEvents(1),
     _clientVisibleArea(0, 0, 0, 0),
+    _splitX(0),
+    _splitY(0),
     _clientSelectedPart(-1),
     _tileWidthPixel(0),
     _tileHeightPixel(0),
@@ -571,7 +573,7 @@ bool ClientSession::_handleInput(const char *buffer, int length)
         int y;
         int width;
         int height;
-        if (tokens.size() != 5 ||
+        if ((tokens.size() != 5 && tokens.size() != 7) ||
             !getTokenInteger(tokens[1], "x", x) ||
             !getTokenInteger(tokens[2], "y", y) ||
             !getTokenInteger(tokens[3], "width", width) ||
@@ -584,6 +586,20 @@ bool ClientSession::_handleInput(const char *buffer, int length)
         }
         else
         {
+            if (tokens.size() == 7)
+            {
+                int splitX, splitY;
+                if (!getTokenInteger(tokens[5], "splitx", splitX) ||
+                    !getTokenInteger(tokens[6], "splity", splitY))
+                {
+                    LOG_WRN("Invalid syntax for '" << tokens[0] << "' message: [" << firstLine << "].");
+                    return true;
+                }
+
+                _splitX = splitX;
+                _splitY = splitY;
+            }
+
             _clientVisibleArea = Util::Rectangle(x, y, width, height);
             resetWireIdMap();
             return forwardToChild(std::string(buffer, length), docBroker);
@@ -1732,15 +1748,31 @@ void ClientSession::handleTileInvalidation(const std::string& message,
         return;
     }
 
-    // Visible area can have negative value as position, but we have tiles only in the positive range
-    Util::Rectangle normalizedVisArea = getNormalizedVisibleArea();
-
     std::pair<int, Util::Rectangle> result = TileCache::parseInvalidateMsg(message);
     int part = result.first;
     Util::Rectangle& invalidateRect = result.second;
 
-    // We can ignore the invalidation if it's outside of the visible area
-    if(!normalizedVisArea.intersects(invalidateRect))
+    constexpr SplitPaneName panes[4] = {
+        TOPLEFT_PANE,
+        TOPRIGHT_PANE,
+        BOTTOMLEFT_PANE,
+        BOTTOMRIGHT_PANE
+    };
+    Util::Rectangle paneRects[4];
+    int numPanes = 0;
+    for(int i = 0; i < 4; ++i)
+    {
+        if(!isSplitPane(panes[i]))
+            continue;
+
+        Util::Rectangle rect = getNormalizedVisiblePaneArea(panes[i]);
+        if (rect.intersects(invalidateRect)) {
+            paneRects[numPanes++] = rect;
+        }
+    }
+
+    // We can ignore the invalidation if it's outside of all split-panes.
+    if(!numPanes)
         return;
 
     if( part == -1 ) // If no part is specified we use the part used by the client
@@ -1751,26 +1783,30 @@ void ClientSession::handleTileInvalidation(const std::string& message,
     std::vector<TileDesc> invalidTiles;
     if(part == _clientSelectedPart || _isTextDocument)
     {
-        // Iterate through visible tiles
-        for(int i = std::ceil(normalizedVisArea.getTop() / _tileHeightTwips);
-                    i <= std::ceil(normalizedVisArea.getBottom() / _tileHeightTwips); ++i)
+        for(int paneIdx = 0; paneIdx < numPanes; ++paneIdx)
         {
-            for(int j = std::ceil(normalizedVisArea.getLeft() / _tileWidthTwips);
-                j <= std::ceil(normalizedVisArea.getRight() / _tileWidthTwips); ++j)
+            const Util::Rectangle& normalizedVisArea = paneRects[paneIdx];
+            // Iterate through visible tiles
+            for(int i = std::ceil(normalizedVisArea.getTop() / _tileHeightTwips);
+                        i <= std::ceil(normalizedVisArea.getBottom() / _tileHeightTwips); ++i)
             {
-                // Find tiles affected by invalidation
-                Util::Rectangle tileRect (j * _tileWidthTwips, i * _tileHeightTwips, _tileWidthTwips, _tileHeightTwips);
-                if(invalidateRect.intersects(tileRect))
+                for(int j = std::ceil(normalizedVisArea.getLeft() / _tileWidthTwips);
+                    j <= std::ceil(normalizedVisArea.getRight() / _tileWidthTwips); ++j)
                 {
-                    invalidTiles.emplace_back(normalizedViewId, part, _tileWidthPixel, _tileHeightPixel, j * _tileWidthTwips, i * _tileHeightTwips, _tileWidthTwips, _tileHeightTwips, -1, 0, -1, false);
+                    // Find tiles affected by invalidation
+                    Util::Rectangle tileRect (j * _tileWidthTwips, i * _tileHeightTwips, _tileWidthTwips, _tileHeightTwips);
+                    if(invalidateRect.intersects(tileRect))
+                    {
+                        invalidTiles.emplace_back(normalizedViewId, part, _tileWidthPixel, _tileHeightPixel, j * _tileWidthTwips, i * _tileHeightTwips, _tileWidthTwips, _tileHeightTwips, -1, 0, -1, false);
 
-                    TileWireId oldWireId = 0;
-                    auto iter = _oldWireIds.find(invalidTiles.back().generateID());
-                    if(iter != _oldWireIds.end())
-                        oldWireId = iter->second;
+                        TileWireId oldWireId = 0;
+                        auto iter = _oldWireIds.find(invalidTiles.back().generateID());
+                        if(iter != _oldWireIds.end())
+                            oldWireId = iter->second;
 
-                    invalidTiles.back().setOldWireId(oldWireId);
-                    invalidTiles.back().setWireId(0);
+                        invalidTiles.back().setOldWireId(oldWireId);
+                        invalidTiles.back().setWireId(0);
+                    }
                 }
             }
         }
@@ -1784,6 +1820,80 @@ void ClientSession::handleTileInvalidation(const std::string& message,
     }
 }
 
+bool ClientSession::isSplitPane(const SplitPaneName paneName) const
+{
+    if (paneName == BOTTOMRIGHT_PANE)
+        return true;
+
+    if (paneName == TOPLEFT_PANE)
+        return (_splitX && _splitY);
+
+    if (paneName == TOPRIGHT_PANE)
+        return _splitY;
+
+    if (paneName == BOTTOMLEFT_PANE)
+        return _splitX;
+
+    return false;
+}
+
+Util::Rectangle ClientSession::getNormalizedVisiblePaneArea(const SplitPaneName paneName) const
+{
+    Util::Rectangle normalizedVisArea = getNormalizedVisibleArea();
+    if (!_splitX && !_splitY)
+        return paneName == BOTTOMRIGHT_PANE ? normalizedVisArea : Util::Rectangle();
+
+    int freeStartX = normalizedVisArea.getLeft() + _splitX;
+    int freeStartY = normalizedVisArea.getTop()  + _splitY;
+    int freeWidth = normalizedVisArea.getWidth() - _splitX;
+    int freeHeight = normalizedVisArea.getHeight() - _splitY;
+
+    switch (paneName)
+    {
+    case BOTTOMRIGHT_PANE:
+        return Util::Rectangle(freeStartX, freeStartY, freeWidth, freeHeight);
+    case TOPLEFT_PANE:
+        return (_splitX && _splitY) ? Util::Rectangle(0, 0, _splitX, _splitY) : Util::Rectangle();
+    case TOPRIGHT_PANE:
+        return _splitY ? Util::Rectangle(freeStartX, 0, freeWidth, _splitY) : Util::Rectangle();
+    case BOTTOMLEFT_PANE:
+        return _splitX ? Util::Rectangle(0, freeStartY, _splitX, freeHeight) : Util::Rectangle();
+    default:
+        assert(false && "Unknown split-pane name");
+    }
+
+    return Util::Rectangle();
+}
+
+bool ClientSession::isTileInsideVisibleArea(const TileDesc& tile) const
+{
+    if (!_splitX && !_splitY)
+    {
+        return (tile.getTilePosX() >= _clientVisibleArea.getLeft() && tile.getTilePosX() <= _clientVisibleArea.getRight() &&
+            tile.getTilePosY() >= _clientVisibleArea.getTop() && tile.getTilePosY() <= _clientVisibleArea.getBottom());
+    }
+
+    constexpr SplitPaneName panes[4] = {
+        TOPLEFT_PANE,
+        TOPRIGHT_PANE,
+        BOTTOMLEFT_PANE,
+        BOTTOMRIGHT_PANE
+    };
+
+    for (int i = 0; i < 4; ++i)
+    {
+        if (!isSplitPane(panes[i]))
+            continue;
+
+        Util::Rectangle paneRect = getNormalizedVisiblePaneArea(panes[i]);
+        if (tile.getTilePosX() >= paneRect.getLeft() && tile.getTilePosX() <= paneRect.getRight() &&
+            tile.getTilePosY() >= paneRect.getTop() && tile.getTilePosY() <= paneRect.getBottom())
+            return true;
+    }
+
+    return false;
+}
+
 void ClientSession::resetWireIdMap()
 {
     _oldWireIds.clear();
@@ -1802,9 +1912,7 @@ void ClientSession::traceTileBySend(const TileDesc& tile, bool deduplicated)
     else
     {
         // Track only tile inside the visible area
-        if(_clientVisibleArea.hasSurface() &&
-           tile.getTilePosX() >= _clientVisibleArea.getLeft() && tile.getTilePosX() <= _clientVisibleArea.getRight() &&
-           tile.getTilePosY() >= _clientVisibleArea.getTop() && tile.getTilePosY() <= _clientVisibleArea.getBottom())
+        if(_clientVisibleArea.hasSurface() && isTileInsideVisibleArea(tile))
         {
             _oldWireIds.insert(std::pair<std::string, TileWireId>(tileID, tile.getWireId()));
         }
diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp
index cc153bdd8..6304cd4a9 100644
--- a/wsd/ClientSession.hpp
+++ b/wsd/ClientSession.hpp
@@ -138,6 +138,20 @@ public:
     /// Visible area can have negative value as position, but we have tiles only in the positive range
     Util::Rectangle getNormalizedVisibleArea() const;
 
+    /// The client's visible area can be divided into a maximum of 4 panes.
+    enum SplitPaneName {
+        TOPLEFT_PANE,
+        TOPRIGHT_PANE,
+        BOTTOMLEFT_PANE,
+        BOTTOMRIGHT_PANE
+    };
+
+    /// Returns true if the given split-pane is currently valid.
+    bool isSplitPane(const SplitPaneName) const;
+
+    /// Returns the normalized visible area of a given split-pane.
+    Util::Rectangle getNormalizedVisiblePaneArea(const SplitPaneName) const;
+
     int getTileWidthInTwips() const { return _tileWidthTwips; }
     int getTileHeightInTwips() const { return _tileHeightTwips; }
 
@@ -220,6 +234,8 @@ private:
     void handleTileInvalidation(const std::string& message,
                                 const std::shared_ptr<DocumentBroker>& docBroker);
 
+    bool isTileInsideVisibleArea(const TileDesc& tile) const;
+
 private:
     std::weak_ptr<DocumentBroker> _docBroker;
 
@@ -255,6 +271,10 @@ private:
     /// Visible area of the client
     Util::Rectangle _clientVisibleArea;
 
+    /// Split position that defines the current split panes
+    int _splitX;
+    int _splitY;
+
     /// Selected part of the document viewed by the client (no parts in Writer)
     int _clientSelectedPart;
 


More information about the Libreoffice-commits mailing list