comphelper/source/misc/lok.cxx                 |   12 +++
 desktop/source/lib/init.cxx                    |    2 
 editeng/source/editeng/impedit.cxx             |    3 
 include/LibreOfficeKit/LibreOfficeKitEnums.h   |    8 +-
 include/comphelper/lok.hxx                     |    6 +
 include/sfx2/lokhelper.hxx                     |    2 
 libreofficekit/source/gtk/lokdocview.cxx       |   17 +++-
 sfx2/source/view/lokhelper.cxx                 |   16 ++++
 sw/qa/extras/tiledrendering/tiledrendering.cxx |   97 ++++++++++++++++++++++++-
 sw/source/core/crsr/crsrsh.cxx                 |   13 ++-
 sw/source/core/crsr/viscrs.cxx                 |    6 +
 11 files changed, 172 insertions(+), 10 deletions(-)

New commits:
commit 83b7bfc0efefb3c77e5c59553320e98539250c62
Author: Tamás Zolnai <tamas.zol...@collabora.com>
Date:   Thu Apr 5 22:23:28 2018 +0200

    sw lok: View jumps to cursor position even if it is moved by an other view.
    
    Scrolling is done twice. Once in SwCursorShell::UpdateCursor() by
    SCROLLWIN flag. Here we can check the actual viewid and avoid scrolling
    if the cursor is move by an other user.
    The second instance in the LO online code, for it we need to pass the
    viewid identifying the view which moved the cursor.
    
    Change-Id: I033274f88ce41acbb632e2aeb0d986ab11cd2d52
    Reviewed-on: https://gerrit.libreoffice.org/52220
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Tamás Zolnai <tamas.zol...@collabora.com>

diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx
index 203426bdc691..8beb633a9218 100644
--- a/comphelper/source/misc/lok.cxx
+++ b/comphelper/source/misc/lok.cxx
@@ -29,6 +29,8 @@ static bool g_bTiledAnnotations(true);
 
 static bool g_bRangeHeaders(false);
 
+static bool g_bViewIdForVisCursorInvalidation(false);
+
 static bool g_bLocalRendering(false);
 
 static LanguageTag g_aLanguageTag("en-US", true);
@@ -88,6 +90,16 @@ void setRangeHeaders(bool bRangeHeaders)
     g_bRangeHeaders = bRangeHeaders;
 }
 
+void setViewIdForVisCursorInvalidation(bool bViewIdForVisCursorInvalidation)
+{
+    g_bViewIdForVisCursorInvalidation = bViewIdForVisCursorInvalidation;
+}
+
+bool isViewIdForVisCursorInvalidation()
+{
+    return g_bViewIdForVisCursorInvalidation;
+}
+
 bool isRangeHeaders()
 {
     return g_bRangeHeaders;
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 67beb36d3a56..28feff959221 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -3514,6 +3514,8 @@ static void lo_setOptionalFeatures(LibreOfficeKit* pThis, 
unsigned long long con
         comphelper::LibreOfficeKit::setTiledAnnotations(false);
     if (features & LOK_FEATURE_RANGE_HEADERS)
         comphelper::LibreOfficeKit::setRangeHeaders(true);
+    if (features & LOK_FEATURE_VIEWID_IN_VISCURSOR_INVALIDATION_CALLBACK)
+        comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(true);
 }
 
 static void lo_setDocumentPassword(LibreOfficeKit* pThis,
diff --git a/editeng/source/editeng/impedit.cxx 
b/editeng/source/editeng/impedit.cxx
index dabcd1c61d87..99d49c1eeae4 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -42,6 +42,7 @@
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <comphelper/string.hxx>
 #include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
@@ -1112,7 +1113,7 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool 
bForceVisCursor )
             }
             else
             {
-                
mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, 
sRect.getStr());
+                SfxLokHelper::notifyVisCursorInvalidation(mpViewShell, sRect);
                 
mpViewShell->NotifyOtherViews(LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", 
sRect);
             }
         }
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h 
b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 300d91e1c8c4..74d49fa15824 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -84,7 +84,13 @@ typedef enum
     /**
      * Enable range based header data
      */
-    LOK_FEATURE_RANGE_HEADERS = (1ULL << 4)
+    LOK_FEATURE_RANGE_HEADERS = (1ULL << 4),
+
+    /**
+     * Request to have the active view's Id as the 1st value in the
+     * LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR payload.
+     */
+    LOK_FEATURE_VIEWID_IN_VISCURSOR_INVALIDATION_CALLBACK = (1ULL << 5)
 }
 LibreOfficeKitOptionalFeatures;
 
diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx
index 9759bb524541..e0bd65690261 100644
--- a/include/comphelper/lok.hxx
+++ b/include/comphelper/lok.hxx
@@ -67,6 +67,12 @@ COMPHELPER_DLLPUBLIC void setRangeHeaders(bool 
bTiledAnnotations);
 /// Check if range based header data is enabled
 COMPHELPER_DLLPUBLIC bool isRangeHeaders();
 
+
+/// Check whether clients want viewId in visible cursor invalidation payload.
+COMPHELPER_DLLPUBLIC bool isViewIdForVisCursorInvalidation();
+/// Set whether clients want viewId in visible cursor invalidation payload.
+COMPHELPER_DLLPUBLIC void setViewIdForVisCursorInvalidation(bool 
bViewIdForVisCursorInvalidation);
+
 /// Update the current LOK's language.
 COMPHELPER_DLLPUBLIC void setLanguageTag(const LanguageTag& languageTag);
 /// Get the current LOK's language.
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index b2307eb428a6..08424a90f770 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -50,6 +50,8 @@ public:
                              const std::vector<vcl::LOKPayloadItem>& rPayload 
= std::vector<vcl::LOKPayloadItem>());
     /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to 
setOptionalFeatures() if needed.
     static void notifyInvalidation(SfxViewShell const* pThisView, const 
OString& rPayload);
+    /// Emits a LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, but tweaks it 
according to setOptionalFeatures() if needed.
+    static void notifyVisCursorInvalidation(OutlinerViewShell const* 
pThisView, const OString& rRectangle);
     /// Notifies all views with the given type and payload.
     static void notifyAllViews(int nType, const OString& rPayload);
     /// A special value to signify 'infinity'.
diff --git a/libreofficekit/source/gtk/lokdocview.cxx 
b/libreofficekit/source/gtk/lokdocview.cxx
index 8a76c78e1151..e55592e9c1da 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -1163,13 +1163,25 @@ callback (gpointer pData)
     break;
     case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
     {
-        priv->m_aVisibleCursor = payloadToRectangle(pDocView, 
pCallback->m_aPayload.c_str());
+
+        std::stringstream aStream(pCallback->m_aPayload);
+        boost::property_tree::ptree aTree;
+        boost::property_tree::read_json(aStream, aTree);
+        const std::string& rRectangle = aTree.get<std::string>("rectangle");
+        int nViewId = aTree.get<int>("viewId");
+
+        priv->m_aVisibleCursor = payloadToRectangle(pDocView, 
rRectangle.c_str());
         priv->m_bCursorOverlayVisible = true;
-        g_signal_emit(pDocView, doc_view_signals[CURSOR_CHANGED], 0,
+        std::cerr << nViewId;
+        std::cerr << priv->m_nViewId;
+        if(nViewId == priv->m_nViewId)
+        {
+            g_signal_emit(pDocView, doc_view_signals[CURSOR_CHANGED], 0,
                       priv->m_aVisibleCursor.x,
                       priv->m_aVisibleCursor.y,
                       priv->m_aVisibleCursor.width,
                       priv->m_aVisibleCursor.height);
+        }
         gtk_widget_queue_draw(GTK_WIDGET(pDocView));
     }
     break;
@@ -2701,6 +2713,7 @@ static gboolean lok_doc_view_initable_init (GInitable 
*initable, GCancellable* /
         return FALSE;
     }
     priv->m_nLOKFeatures |= LOK_FEATURE_PART_IN_INVALIDATION_CALLBACK;
+    priv->m_nLOKFeatures |= 
LOK_FEATURE_VIEWID_IN_VISCURSOR_INVALIDATION_CALLBACK;
     priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, 
priv->m_nLOKFeatures);
 
     return TRUE;
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index b84496be2c27..be2d5e3887a2 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -17,6 +17,7 @@
 #include <sfx2/viewfrm.hxx>
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <comphelper/lok.hxx>
+#include <editeng/outliner.hxx>
 
 #include <shellimpl.hxx>
 
@@ -199,6 +200,21 @@ void SfxLokHelper::notifyInvalidation(SfxViewShell const* 
pThisView, const OStri
     pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_TILES, 
aBuf.makeStringAndClear().getStr());
 }
 
+void SfxLokHelper::notifyVisCursorInvalidation(OutlinerViewShell const* 
pThisView, const OString& rRectangle)
+{
+    OString sPayload;
+    if (comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation())
+    {
+        sPayload = OString("{ \"viewId\": \"") + 
OString::number(SfxLokHelper::getView()) +
+            "\", \"rectangle\": \"" + rRectangle + "\" }";
+    }
+    else
+    {
+        sPayload = rRectangle;
+    }
+    
pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, 
sPayload.getStr());
+}
+
 void SfxLokHelper::notifyAllViews(int nType, const OString& rPayload)
 {
     const auto payload = rPayload.getStr();
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index 06a7ae836033..6d1dbaed5d27 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -106,6 +106,7 @@ public:
     void testIMESupport();
     void testSplitNodeRedlineCallback();
     void testDeleteNodeRedlineCallback();
+    void testVisCursorInvalidation();
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
     CPPUNIT_TEST(testRegisterCallback);
@@ -160,6 +161,7 @@ public:
     CPPUNIT_TEST(testIMESupport);
     CPPUNIT_TEST(testSplitNodeRedlineCallback);
     CPPUNIT_TEST(testDeleteNodeRedlineCallback);
+    CPPUNIT_TEST(testVisCursorInvalidation);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -672,6 +674,7 @@ class ViewCallback
 {
 public:
     bool m_bOwnCursorInvalidated;
+    int m_nOwnCursorInvalidatedBy;
     bool m_bOwnCursorAtOrigin;
     tools::Rectangle m_aOwnCursor;
     bool m_bViewCursorInvalidated;
@@ -693,6 +696,7 @@ public:
 
     ViewCallback()
         : m_bOwnCursorInvalidated(false),
+          m_nOwnCursorInvalidatedBy(-1),
           m_bOwnCursorAtOrigin(false),
           m_bViewCursorInvalidated(false),
           m_bOwnSelectionSet(false),
@@ -726,7 +730,18 @@ public:
         {
             m_bOwnCursorInvalidated = true;
 
-            uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(OUString::fromUtf8(aPayload));
+            OString sRect;
+            if(comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation())
+            {
+                std::stringstream aStream(pPayload);
+                boost::property_tree::ptree aTree;
+                boost::property_tree::read_json(aStream, aTree);
+                sRect = 
aTree.get_child("rectangle").get_value<std::string>().c_str();
+                m_nOwnCursorInvalidatedBy = 
aTree.get_child("viewId").get_value<int>();
+            }
+            else
+                sRect = aPayload;
+            uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(OUString::fromUtf8(sRect));
             if (OString("EMPTY") == pPayload)
                 return;
             CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), aSeq.getLength());
@@ -2276,6 +2291,86 @@ void 
SwTiledRenderingTest::testDeleteNodeRedlineCallback()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+
+void SwTiledRenderingTest::testVisCursorInvalidation()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
+    ViewCallback aView1;
+    
SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback,
 &aView1);
+    int nView1 = SfxLokHelper::getView();
+
+    SfxLokHelper::createView();
+    int nView2 = SfxLokHelper::getView();
+    ViewCallback aView2;
+    
SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback,
 &aView2);
+    Scheduler::ProcessEventsToIdle();
+
+
+    // Move visible cursor in the first view
+    SfxLokHelper::setView(nView1);
+    Scheduler::ProcessEventsToIdle();
+
+    aView1.m_bOwnCursorInvalidated = false;
+    aView1.m_bViewCursorInvalidated = false;
+    aView2.m_bOwnCursorInvalidated = false;
+    aView2.m_bViewCursorInvalidated = false;
+
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RIGHT);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RIGHT);
+    Scheduler::ProcessEventsToIdle();
+
+    CPPUNIT_ASSERT(!aView1.m_bViewCursorInvalidated);
+    CPPUNIT_ASSERT(aView1.m_bOwnCursorInvalidated);
+    CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated);
+    CPPUNIT_ASSERT(!aView2.m_bOwnCursorInvalidated);
+
+    // Insert text in the second view which moves the other view's cursor too
+    SfxLokHelper::setView(nView2);
+
+    aView1.m_bOwnCursorInvalidated = false;
+    aView1.m_bViewCursorInvalidated = false;
+    aView2.m_bOwnCursorInvalidated = false;
+    aView2.m_bViewCursorInvalidated = false;
+
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+    Scheduler::ProcessEventsToIdle();
+
+    CPPUNIT_ASSERT(aView1.m_bViewCursorInvalidated);
+    CPPUNIT_ASSERT(aView1.m_bOwnCursorInvalidated);
+    CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated);
+    CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated);
+
+    // Do the same as before, but set the related compatibility flag first
+    SfxLokHelper::setView(nView2);
+
+    comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(true);
+
+    aView1.m_bOwnCursorInvalidated = false;
+    aView1.m_bViewCursorInvalidated = false;
+    aView2.m_bOwnCursorInvalidated = false;
+    aView2.m_bViewCursorInvalidated = false;
+
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+    Scheduler::ProcessEventsToIdle();
+
+    CPPUNIT_ASSERT(aView1.m_bViewCursorInvalidated);
+    CPPUNIT_ASSERT(aView1.m_bOwnCursorInvalidated);
+    CPPUNIT_ASSERT_EQUAL(nView2, aView1.m_nOwnCursorInvalidatedBy);
+    CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated);
+    CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated);
+    CPPUNIT_ASSERT_EQUAL(nView2, aView2.m_nOwnCursorInvalidatedBy);
+
+    comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(false);
+
+    mxComponent->dispose();
+    mxComponent.clear();
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index f8f1e606b1d3..9fc5a8cb7fc9 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -1411,6 +1411,13 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, 
bool bIdleEnd )
     SET_CURR_SHELL( this );
     ClearUpCursors();
 
+    bool bScrollWin = eFlags & SwCursorShell::SCROLLWIN;
+    // Don't scroll to the cursor if it's moved by an other view
+    if(comphelper::LibreOfficeKit::isActive())
+    {
+        bScrollWin = SfxLokHelper::getView() != 
SfxLokHelper::getView(GetSfxViewShell());
+    }
+
     if (ActionPend())
     {
         if ( eFlags & SwCursorShell::READONLY )
@@ -1553,7 +1560,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool 
bIdleEnd )
 
             m_pVisibleCursor->Hide(); // always hide visible Cursor
             // scroll Cursor to visible area
-            if( (eFlags & SwCursorShell::SCROLLWIN) &&
+            if( bScrollWin &&
                 (HasSelection() || eFlags & SwCursorShell::READONLY ||
                  !IsCursorReadonly()) )
             {
@@ -1811,7 +1818,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool 
bIdleEnd )
         }
 
         // scroll Cursor to visible area
-        if( m_bHasFocus && eFlags & SwCursorShell::SCROLLWIN &&
+        if( m_bHasFocus && bScrollWin&&
             (HasSelection() || eFlags & SwCursorShell::READONLY ||
              !IsCursorReadonly() || GetViewOptions()->IsSelectionInReadonly()) 
)
         {
@@ -1823,7 +1830,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool 
bIdleEnd )
             m_bSVCursorVis = bSav;
         }
 
-    } while( eFlags & SwCursorShell::SCROLLWIN );
+    } while( bScrollWin );
 
     if( m_pBlockCursor )
         RefreshBlockCursor();
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index b7f370608115..443e494b6a7d 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -214,13 +214,15 @@ void SwVisibleCursor::SetPosAndShow(SfxViewShell const * 
pViewShell)
         if (pViewShell)
         {
             if (pViewShell == m_pCursorShell->GetSfxViewShell())
-                
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, 
sRect.getStr());
+            {
+                SfxLokHelper::notifyVisCursorInvalidation(pViewShell, sRect);
+            }
             else
                 
SfxLokHelper::notifyOtherView(m_pCursorShell->GetSfxViewShell(), pViewShell, 
LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect);
         }
         else
         {
-            
m_pCursorShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR,
 sRect.getStr());
+            
SfxLokHelper::notifyVisCursorInvalidation(m_pCursorShell->GetSfxViewShell(), 
sRect);
             SfxLokHelper::notifyOtherViews(m_pCursorShell->GetSfxViewShell(), 
LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect);
         }
     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to