summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/source/lib/init.cxx2
-rw-r--r--include/LibreOfficeKit/LibreOfficeKitEnums.h16
-rw-r--r--libreofficekit/source/gtk/lokdocview.cxx43
-rw-r--r--sd/qa/unit/tiledrendering/tiledrendering.cxx68
-rw-r--r--sfx2/source/view/viewsh.cxx2
-rw-r--r--svx/source/svdraw/svdmrkv.cxx10
6 files changed, 137 insertions, 4 deletions
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index e8df4df0bb36..ba749c421e80 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -473,6 +473,7 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li
m_states.emplace(LOK_CALLBACK_TEXT_SELECTION_END, "NIL");
m_states.emplace(LOK_CALLBACK_TEXT_SELECTION, "NIL");
m_states.emplace(LOK_CALLBACK_GRAPHIC_SELECTION, "NIL");
+ m_states.emplace(LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "NIL");
m_states.emplace(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, "NIL");
m_states.emplace(LOK_CALLBACK_INVALIDATE_VIEW_CURSOR , "NIL");
m_states.emplace(LOK_CALLBACK_STATE_CHANGED, "NIL");
@@ -579,6 +580,7 @@ void CallbackFlushHandler::queue(const int type, const char* data)
case LOK_CALLBACK_TEXT_SELECTION_END:
case LOK_CALLBACK_TEXT_SELECTION:
case LOK_CALLBACK_GRAPHIC_SELECTION:
+ case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
case LOK_CALLBACK_MOUSE_POINTER:
case LOK_CALLBACK_CELL_CURSOR:
case LOK_CALLBACK_CELL_VIEW_CURSOR:
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index c687879793ca..d8e46dbddfd3 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -358,6 +358,22 @@ typedef enum
*/
LOK_CALLBACK_CELL_VIEW_CURSOR,
+ /**
+ * The size and/or the position of a graphic selection in one of the other
+ * views has changed.
+ *
+ * The payload format:
+ *
+ * {
+ * "viewId": "..."
+ * "selection": "..."
+ * }
+ *
+ * - viewId is a value returned earlier by lok::Document::createView()
+ * - selection uses the format of LOK_CALLBACK_INVALIDATE_TILES.
+ */
+ LOK_CALLBACK_GRAPHIC_VIEW_SELECTION,
+
}
LibreOfficeKitCallbackType;
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index a6fbe7871d9a..6c7c305b4062 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -101,9 +101,12 @@ struct LOKDocViewPrivateImpl
/// Position and size of the selection end.
GdkRectangle m_aTextSelectionEnd;
GdkRectangle m_aGraphicSelection;
+ /// Position and size of the graphic view selections. The current view can only
+ /// see them, can't modify them. Key is the view id.
+ std::map<int, GdkRectangle> m_aGraphicViewSelections;
GdkRectangle m_aCellCursor;
/// Position and size of the cell view cursors. The current view can only
- //see / them, can't modify them. Key is the view id.
+ /// see them, can't modify them. Key is the view id.
std::map<int, GdkRectangle> m_aCellViewCursors;
gboolean m_bInDragGraphicSelection;
@@ -323,6 +326,8 @@ callbackTypeToString (int nType)
return "LOK_CALLBACK_CURSOR_VISIBLE";
case LOK_CALLBACK_GRAPHIC_SELECTION:
return "LOK_CALLBACK_GRAPHIC_SELECTION";
+ case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
+ return "LOK_CALLBACK_GRAPHIC_VIEW_SELECTION";
case LOK_CALLBACK_CELL_CURSOR:
return "LOK_CALLBACK_CELL_CURSOR";
case LOK_CALLBACK_HYPERLINK_CLICKED:
@@ -1102,6 +1107,25 @@ callback (gpointer pData)
gtk_widget_queue_draw(GTK_WIDGET(pDocView));
}
break;
+ case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
+ {
+ std::stringstream aStream(pCallback->m_aPayload);
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ int nViewId = aTree.get<int>("viewId");
+ const std::string& rRectangle = aTree.get<std::string>("selection");
+ if (rRectangle != "EMPTY")
+ priv->m_aGraphicViewSelections[nViewId] = payloadToRectangle(pDocView, rRectangle.c_str());
+ else
+ {
+ auto it = priv->m_aGraphicViewSelections.find(nViewId);
+ if (it != priv->m_aGraphicViewSelections.end())
+ priv->m_aGraphicViewSelections.erase(it);
+ }
+ gtk_widget_queue_draw(GTK_WIDGET(pDocView));
+ break;
+ }
+ break;
case LOK_CALLBACK_CELL_CURSOR:
{
if (pCallback->m_aPayload != "EMPTY")
@@ -1265,7 +1289,8 @@ renderHandle(LOKDocView* pDocView,
static void
renderGraphicHandle(LOKDocView* pDocView,
cairo_t* pCairo,
- const GdkRectangle& rSelection)
+ const GdkRectangle& rSelection,
+ const GdkRGBA& rColor)
{
LOKDocViewPrivate& priv = getPrivate(pDocView);
int nHandleWidth = 9, nHandleHeight = 9;
@@ -1319,7 +1344,7 @@ renderGraphicHandle(LOKDocView* pDocView,
priv->m_aGraphicHandleRects[i].width = nHandleWidth;
priv->m_aGraphicHandleRects[i].height = nHandleHeight;
- cairo_set_source_rgb(pCairo, 0, 0, 0);
+ cairo_set_source_rgb(pCairo, rColor.red, rColor.green, rColor.blue);
cairo_rectangle(pCairo, x, y, nHandleWidth, nHandleHeight);
cairo_fill(pCairo);
}
@@ -1580,7 +1605,17 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
}
if (!isEmptyRectangle(priv->m_aGraphicSelection))
- renderGraphicHandle(pDocView, pCairo, priv->m_aGraphicSelection);
+ {
+ GdkRGBA aBlack{0, 0, 0, 0};
+ renderGraphicHandle(pDocView, pCairo, priv->m_aGraphicSelection, aBlack);
+ }
+
+ // Graphic selections of other views.
+ for (std::pair<const int, GdkRectangle>& rPair : priv->m_aGraphicViewSelections)
+ {
+ const GdkRGBA& rDark = getDarkColor(rPair.first);
+ renderGraphicHandle(pDocView, pCairo, rPair.second, rDark);
+ }
// Draw the cell cursor.
if (!isEmptyRectangle(priv->m_aCellCursor))
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index ab9196c0b865..316936f44d47 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -12,6 +12,7 @@
#include <test/xmltesttools.hxx>
#include <boost/property_tree/json_parser.hpp>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <sfx2/lokhelper.hxx>
#include <com/sun/star/frame/Desktop.hpp>
#include <comphelper/dispatchcommand.hxx>
#include <comphelper/processfactory.hxx>
@@ -62,6 +63,7 @@ public:
void testPartHash();
void testResizeTable();
void testResizeTableColumn();
+ void testViewCursors();
CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
CPPUNIT_TEST(testRegisterCallback);
@@ -81,6 +83,7 @@ public:
CPPUNIT_TEST(testPartHash);
CPPUNIT_TEST(testResizeTable);
CPPUNIT_TEST(testResizeTableColumn);
+ CPPUNIT_TEST(testViewCursors);
CPPUNIT_TEST_SUITE_END();
private:
@@ -806,6 +809,71 @@ void SdTiledRenderingTest::testResizeTableColumn()
comphelper::LibreOfficeKit::setActive(false);
}
+class ViewCallback
+{
+public:
+ bool m_bGraphicSelectionInvalidated;
+ bool m_bGraphicViewSelectionInvalidated;
+
+ ViewCallback()
+ : m_bGraphicSelectionInvalidated(false),
+ m_bGraphicViewSelectionInvalidated(false)
+ {
+ }
+
+ static void callback(int nType, const char* pPayload, void* pData)
+ {
+ static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
+ }
+
+ void callbackImpl(int nType, const char* /*pPayload*/)
+ {
+ switch (nType)
+ {
+ case LOK_CALLBACK_GRAPHIC_SELECTION:
+ {
+ m_bGraphicSelectionInvalidated = true;
+ }
+ break;
+ case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
+ {
+ m_bGraphicViewSelectionInvalidated = true;
+ }
+ break;
+ }
+ }
+};
+
+void SdTiledRenderingTest::testViewCursors()
+{
+ comphelper::LibreOfficeKit::setActive();
+
+ // Create two views.
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ ViewCallback aView1;
+ SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
+ SfxLokHelper::createView();
+ ViewCallback aView2;
+ SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2);
+
+ // Select the shape in the second view.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ Scheduler::ProcessEventsToIdle();
+
+ // First view notices that there was a selection change in the other view.
+ CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated);
+ // Second view notices that there was a selection change in its own view.
+ CPPUNIT_ASSERT(aView2.m_bGraphicSelectionInvalidated);
+ mxComponent->dispose();
+ mxComponent.clear();
+
+ comphelper::LibreOfficeKit::setActive(false);
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index dea40535534a..a68e8c0ef330 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -1620,9 +1620,11 @@ void SfxViewShell::libreOfficeKitViewCallback(int nType, const char* pPayload) c
switch (nType)
{
case LOK_CALLBACK_TEXT_SELECTION:
+ case LOK_CALLBACK_TEXT_VIEW_SELECTION:
case LOK_CALLBACK_TEXT_SELECTION_START:
case LOK_CALLBACK_TEXT_SELECTION_END:
case LOK_CALLBACK_GRAPHIC_SELECTION:
+ case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
return;
}
}
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index db1b683f14e9..df1abb7f3632 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -53,6 +53,7 @@
#include <editeng/editdata.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
#include <sfx2/viewsh.hxx>
using namespace com::sun::star;
@@ -714,7 +715,10 @@ void SdrMarkView::SetMarkHandles()
{
// Suppress handles -> empty graphic selection.
if(SfxViewShell* pViewShell = SfxViewShell::Current())
+ {
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, "EMPTY");
+ SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
+ }
}
return;
}
@@ -735,7 +739,10 @@ void SdrMarkView::SetMarkHandles()
{
// The table shape has selected cells, which provide text selection already -> no graphic selection.
if(SfxViewShell* pViewShell = SfxViewShell::Current())
+ {
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, "EMPTY");
+ SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
+ }
return;
}
}
@@ -768,7 +775,10 @@ void SdrMarkView::SetMarkHandles()
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, "");
}
if(SfxViewShell* pViewShell = SfxViewShell::Current())
+ {
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION, sSelection.getStr());
+ SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", sSelection);
+ }
}
if (bFrmHdl)