From af8419fa1d3cea57481e0e53518237eea2d9cdad Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Fri, 8 Jul 2016 15:13:13 +0200 Subject: sw lok: add LOK_CALLBACK_VIEW_CURSOR_VISIBLE With this, in case a text cursor is turned into a graphic selection in view#0, then view#1 can also hide the text cursor of view#0. Change-Id: I7de89b8537ef8b0985336793b719d93733604bff Reviewed-on: https://gerrit.libreoffice.org/27044 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- desktop/source/lib/init.cxx | 3 ++ include/LibreOfficeKit/LibreOfficeKitEnums.h | 16 ++++++++++ libreofficekit/source/gtk/lokdocview.cxx | 21 +++++++++++++ sw/qa/extras/tiledrendering/tiledrendering.cxx | 43 ++++++++++++++++++++++++-- sw/source/core/crsr/crsrsh.cxx | 9 ++++-- 5 files changed, 88 insertions(+), 4 deletions(-) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index ae92ce78777a..f25c861d4f2c 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -455,6 +455,7 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li m_states.emplace(LOK_CALLBACK_CELL_VIEW_CURSOR, "NIL"); m_states.emplace(LOK_CALLBACK_CELL_FORMULA, "NIL"); m_states.emplace(LOK_CALLBACK_CURSOR_VISIBLE, "NIL"); + m_states.emplace(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "NIL"); m_states.emplace(LOK_CALLBACK_SET_PART, "NIL"); Start(); @@ -498,6 +499,7 @@ void CallbackFlushHandler::queue(const int type, const char* data) type != LOK_CALLBACK_INVALIDATE_TILES && type != LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR && type != LOK_CALLBACK_CURSOR_VISIBLE && + type != LOK_CALLBACK_VIEW_CURSOR_VISIBLE && type != LOK_CALLBACK_TEXT_SELECTION) { //SAL_WARN("lokevt", "Skipping while painting [" + std::to_string(type) + "]: [" + payload + "]."); @@ -559,6 +561,7 @@ void CallbackFlushHandler::queue(const int type, const char* data) case LOK_CALLBACK_CELL_VIEW_CURSOR: case LOK_CALLBACK_CELL_FORMULA: case LOK_CALLBACK_CURSOR_VISIBLE: + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: case LOK_CALLBACK_SET_PART: case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE: removeAllButLast(type, false); diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h index d8e46dbddfd3..63abda8ecebd 100644 --- a/include/LibreOfficeKit/LibreOfficeKitEnums.h +++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h @@ -374,6 +374,22 @@ typedef enum */ LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, + /** + * The blinking text cursor in one of the other views is now visible or + * not. + * + * The payload format: + * + * { + * "viewId": "..." + * "visible": "..." + * } + * + * - viewId is a value returned earlier by lok::Document::createView() + * - visible uses the format of LOK_CALLBACK_CURSOR_VISIBLE. + */ + LOK_CALLBACK_VIEW_CURSOR_VISIBLE, + } LibreOfficeKitCallbackType; diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 8bf889ff9f79..667b4d4feb98 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -83,6 +83,9 @@ struct LOKDocViewPrivateImpl gboolean m_bCursorOverlayVisible; /// Cursor is visible or hidden (e.g. for graphic selection). gboolean m_bCursorVisible; + /// Visibility of view selections. The current view can only see / them, + /// can't modify them. Key is the view id. + std::map m_aViewCursorVisibilities; /// Time of the last button press. guint32 m_nLastButtonPressTime; /// Time of the last button release. @@ -324,6 +327,8 @@ callbackTypeToString (int nType) return "LOK_CALLBACK_TEXT_SELECTION_END"; case LOK_CALLBACK_CURSOR_VISIBLE: return "LOK_CALLBACK_CURSOR_VISIBLE"; + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: + return "LOK_CALLBACK_VIEW_CURSOR_VISIBLE"; case LOK_CALLBACK_GRAPHIC_SELECTION: return "LOK_CALLBACK_GRAPHIC_SELECTION"; case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION: @@ -1222,6 +1227,18 @@ callback (gpointer pData) gtk_widget_queue_draw(GTK_WIDGET(pDocView)); break; } + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: + { + std::stringstream aStream(pCallback->m_aPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + int nViewId = aTree.get("viewId"); + const std::string& rVisible = aTree.get("visible"); + priv->m_aViewCursorVisibilities[nViewId] = rVisible == "true"; + gtk_widget_queue_draw(GTK_WIDGET(pDocView)); + break; + } + break; case LOK_CALLBACK_CELL_VIEW_CURSOR: { std::stringstream aStream(pCallback->m_aPayload); @@ -1523,6 +1540,10 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo) { for (auto& rPair : priv->m_aViewCursors) { + auto itVisibility = priv->m_aViewCursorVisibilities.find(rPair.first); + if (itVisibility != priv->m_aViewCursorVisibilities.end() && !itVisibility->second) + continue; + GdkRectangle& rCursor = rPair.second; if (rCursor.width < 30) // Set a minimal width if it would be 0. diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index 7709df87b1f4..476b6d618066 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -53,6 +53,7 @@ public: void testPartHash(); void testViewCursors(); void testMissingInvalidation(); + void testViewCursorVisibility(); CPPUNIT_TEST_SUITE(SwTiledRenderingTest); CPPUNIT_TEST(testRegisterCallback); @@ -73,6 +74,7 @@ public: CPPUNIT_TEST(testPartHash); CPPUNIT_TEST(testViewCursors); CPPUNIT_TEST(testMissingInvalidation); + CPPUNIT_TEST(testViewCursorVisibility); CPPUNIT_TEST_SUITE_END(); private: @@ -553,13 +555,15 @@ public: bool m_bOwnSelectionSet; bool m_bViewSelectionSet; bool m_bTilesInvalidated; + bool m_bViewCursorVisible; ViewCallback() : m_bOwnCursorInvalidated(false), m_bViewCursorInvalidated(false), m_bOwnSelectionSet(false), m_bViewSelectionSet(false), - m_bTilesInvalidated(false) + m_bTilesInvalidated(false), + m_bViewCursorVisible(false) { } @@ -568,7 +572,7 @@ public: static_cast(pData)->callbackImpl(nType, pPayload); } - void callbackImpl(int nType, const char* /*pPayload*/) + void callbackImpl(int nType, const char* pPayload) { switch (nType) { @@ -597,6 +601,11 @@ public: m_bViewSelectionSet = true; } break; + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: + { + m_bViewCursorVisible = OString("true") == pPayload; + } + break; } } }; @@ -680,6 +689,36 @@ void SwTiledRenderingTest::testViewCursors() comphelper::LibreOfficeKit::setActive(false); } +void SwTiledRenderingTest::testViewCursorVisibility() +{ + comphelper::LibreOfficeKit::setActive(); + + // Load a document that has a shape and create two views. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1; + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence()); + ViewCallback aView2; + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2); + + // Click on the shape in the second view. + aView1.m_bViewCursorVisible = true; + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + Point aCenter = pObject->GetSnapRect().Center(); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aCenter.getX(), aCenter.getY(), 1); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aCenter.getX(), aCenter.getY(), 1); + Scheduler::ProcessEventsToIdle(); + // Make sure the "view/text" cursor of the first view gets a notification. + CPPUNIT_ASSERT(!aView1.m_bViewCursorVisible); + 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 bd7670136ac2..62f751d1d125 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -2138,7 +2139,9 @@ void SwCursorShell::ShowCursor() if (comphelper::LibreOfficeKit::isActive()) { - GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, OString::boolean(true).getStr()); + OString aPayload = OString::boolean(m_bSVCursorVis); + GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); + SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); } UpdateCursor(); @@ -2157,7 +2160,9 @@ void SwCursorShell::HideCursor() if (comphelper::LibreOfficeKit::isActive()) { - GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, OString::boolean(false).getStr()); + OString aPayload = OString::boolean(m_bSVCursorVis); + GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); + SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); } } } -- cgit