summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamás Zolnai <tamas.zolnai@collabora.com>2018-04-05 22:23:28 +0200
committerTamás Zolnai <tamas.zolnai@collabora.com>2018-04-07 08:05:04 +0200
commit83b7bfc0efefb3c77e5c59553320e98539250c62 (patch)
tree1d23842491eb9f7bd12d315fa83ec85a9bf1cfff
parent602774aef7d8b2f03914939dd230dd1c67d0093b (diff)
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 <ci@libreoffice.org> Reviewed-by: Tamás Zolnai <tamas.zolnai@collabora.com>
-rw-r--r--comphelper/source/misc/lok.cxx12
-rw-r--r--desktop/source/lib/init.cxx2
-rw-r--r--editeng/source/editeng/impedit.cxx3
-rw-r--r--include/LibreOfficeKit/LibreOfficeKitEnums.h8
-rw-r--r--include/comphelper/lok.hxx6
-rw-r--r--include/sfx2/lokhelper.hxx2
-rw-r--r--libreofficekit/source/gtk/lokdocview.cxx17
-rw-r--r--sfx2/source/view/lokhelper.cxx16
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx97
-rw-r--r--sw/source/core/crsr/crsrsh.cxx13
-rw-r--r--sw/source/core/crsr/viscrs.cxx6
11 files changed, 172 insertions, 10 deletions
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);
}
}