summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2019-07-20 10:43:39 +0100
committerMichael Meeks <michael.meeks@collabora.com>2019-08-02 11:41:48 -0400
commitf59e986d0dc04a2d62cc1f236acedfcf727449ce (patch)
treed4739978f593ba969cac9467f1d87e5c1a109186
parent482419ffeab01642db00cd16a2b46a5790a3323e (diff)
lok: clipboard: per view clipboard creation.
A bit brutal, but the mess around clipboard instantiation is awful. Change-Id: I62d6af8bf6813e6bab81123417ea8bfb28394e29
-rw-r--r--desktop/qa/desktop_lib/test_desktop_lib.cxx6
-rw-r--r--desktop/source/lib/init.cxx71
-rw-r--r--desktop/source/lib/lokclipboard.cxx98
-rw-r--r--desktop/source/lib/lokclipboard.hxx73
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.h4
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.hxx6
6 files changed, 214 insertions, 44 deletions
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 4ebb21cdfe0a..6874c92f4cf7 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -2772,9 +2772,13 @@ void DesktopLOKTest::testABI()
CPPUNIT_ASSERT_EQUAL(documentClassOffset(49), offsetof(struct _LibreOfficeKitDocumentClass, selectPart));
CPPUNIT_ASSERT_EQUAL(documentClassOffset(50), offsetof(struct _LibreOfficeKitDocumentClass, moveSelectedParts));
CPPUNIT_ASSERT_EQUAL(documentClassOffset(51), offsetof(struct _LibreOfficeKitDocumentClass, resizeWindow));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(52), offsetof(struct _LibreOfficeKitDocumentClass, getSelection));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(53), offsetof(struct _LibreOfficeKitDocumentClass, setClipboard));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(54), offsetof(struct _LibreOfficeKitDocumentClass, getSelectionType));
+
// Extending is fine, update this, and add new assert for the offsetof the
// new method
- CPPUNIT_ASSERT_EQUAL(documentClassOffset(52), sizeof(struct _LibreOfficeKitDocumentClass));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(55), sizeof(struct _LibreOfficeKitDocumentClass));
}
CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest);
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index eb9c7854bc13..2eb862c07564 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -790,7 +790,7 @@ static char* doc_getTextSelection(LibreOfficeKitDocument* pThis,
const char* pMimeType,
char** pUsedMimeType);
static int doc_getSelectionType(LibreOfficeKitDocument* pThis);
-static int doc_getSelection (LibreOfficeKitDocument* pThis,
+static int doc_getClipboard (LibreOfficeKitDocument* pThis,
const char **pMimeTypes,
size_t *pOutCount,
char ***pOutMimeTypes,
@@ -863,6 +863,34 @@ static size_t doc_renderShapeSelection(LibreOfficeKitDocument* pThis, char** pOu
static void doc_resizeWindow(LibreOfficeKitDocument* pThis, unsigned nLOKWindowId,
const int nWidth, const int nHeight);
+} // extern "C"
+
+namespace {
+ITiledRenderable* getTiledRenderable(LibreOfficeKitDocument* pThis)
+{
+ LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis);
+ return dynamic_cast<ITiledRenderable*>(pDocument->mxComponent.get());
+}
+
+/*
+ * Unfortunately clipboard creation using UNO is insanely baroque.
+ * we also need to ensure that this works for the first view which
+ * has no clear 'createView' called for it (unfortunately).
+ */
+
+rtl::Reference<LOKClipboard> forceSetClipboardForCurrentView(LibreOfficeKitDocument *pThis)
+{
+ ITiledRenderable* pDoc = getTiledRenderable(pThis);
+ rtl::Reference<LOKClipboard> xClip(LOKClipboardFactory::getClipboardForCurView());
+
+ SAL_INFO("lok", "Set to clipboard for view " << xClip.get());
+ // FIXME: using a hammer here - should not be necessary if all tests used createView.
+ pDoc->setClipboard(uno::Reference<datatransfer::clipboard::XClipboard>(xClip->getXI(), UNO_QUERY));
+
+ return xClip;
+}
+} // anonymous namespace
+
LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XComponent> &xComponent)
: mxComponent(xComponent)
{
@@ -901,7 +929,7 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
m_pDocumentClass->setTextSelection = doc_setTextSelection;
m_pDocumentClass->getTextSelection = doc_getTextSelection;
m_pDocumentClass->getSelectionType = doc_getSelectionType;
- m_pDocumentClass->getSelection = doc_getSelection;
+ m_pDocumentClass->getClipboard = doc_getClipboard;
m_pDocumentClass->setClipboard = doc_setClipboard;
m_pDocumentClass->paste = doc_paste;
m_pDocumentClass->setGraphicSelection = doc_setGraphicSelection;
@@ -942,6 +970,8 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
gDocumentClass = m_pDocumentClass;
}
pClass = m_pDocumentClass.get();
+
+ forceSetClipboardForCurrentView(this);
}
LibLODocument_Impl::~LibLODocument_Impl()
@@ -956,6 +986,8 @@ LibLODocument_Impl::~LibLODocument_Impl()
}
}
+extern "C" {
+
CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, LibreOfficeKitCallback pCallback, void* pData)
: Idle( "lokit timer callback" ),
m_pDocument(pDocument),
@@ -1691,12 +1723,6 @@ LibLibreOffice_Impl::~LibLibreOffice_Impl()
namespace
{
-ITiledRenderable* getTiledRenderable(LibreOfficeKitDocument* pThis)
-{
- LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis);
- return dynamic_cast<ITiledRenderable*>(pDocument->mxComponent.get());
-}
-
#ifdef IOS
void paintTileToCGContext(ITiledRenderable* pDocument,
void* rCGContext, const Size nCanvasSize,
@@ -3535,7 +3561,7 @@ static int doc_getSelectionType(LibreOfficeKitDocument* pThis)
return aRet.getLength() ? LOK_SELTYPE_TEXT : LOK_SELTYPE_NONE;
}
-static int doc_getSelection(LibreOfficeKitDocument* pThis,
+static int doc_getClipboard(LibreOfficeKitDocument* pThis,
const char **pMimeTypes,
size_t *pOutCount,
char ***pOutMimeTypes,
@@ -3562,7 +3588,10 @@ static int doc_getSelection(LibreOfficeKitDocument* pThis,
return 0;
}
- css::uno::Reference<css::datatransfer::XTransferable> xTransferable = pDoc->getSelection();
+ rtl::Reference<LOKClipboard> xClip(LOKClipboardFactory::getClipboardForCurView());
+ SAL_INFO("lok", "Got clipboard for view " << xClip.get());
+
+ css::uno::Reference<css::datatransfer::XTransferable> xTransferable = xClip->getContents();
if (!xTransferable)
{
SetLastExceptionMsg("No selection available");
@@ -3637,9 +3666,9 @@ static int doc_setClipboard(LibreOfficeKitDocument* pThis,
}
uno::Reference<datatransfer::XTransferable> xTransferable(new LOKTransferable(nInCount, pInMimeTypes, pInSizes, pInStreams));
- uno::Reference<datatransfer::clipboard::XClipboard> xClipboard(new LOKClipboard);
- xClipboard->setContents(xTransferable, uno::Reference<datatransfer::clipboard::XClipboardOwner>());
- pDoc->setClipboard(xClipboard);
+
+ auto xClip = forceSetClipboardForCurrentView(pThis);
+ xClip->setContents(xTransferable, uno::Reference<datatransfer::clipboard::XClipboardOwner>());
if (!pDoc->isMimeTypeSupported())
{
@@ -4305,7 +4334,7 @@ static void doc_setOutlineState(LibreOfficeKitDocument* pThis, bool bColumn, int
pDoc->setOutlineState(bColumn, nLevel, nIndex, bHidden);
}
-static int doc_createViewWithOptions(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/,
+static int doc_createViewWithOptions(LibreOfficeKitDocument* pThis,
const char* pOptions)
{
comphelper::ProfileZone aZone("doc_createView");
@@ -4322,7 +4351,11 @@ static int doc_createViewWithOptions(SAL_UNUSED_PARAMETER LibreOfficeKitDocument
comphelper::LibreOfficeKit::setLanguageTag(LanguageTag(aLanguage));
}
- return SfxLokHelper::createView();
+ int nId = SfxLokHelper::createView();
+
+ forceSetClipboardForCurrentView(pThis);
+
+ return nId;
}
static int doc_createView(LibreOfficeKitDocument* pThis)
@@ -5498,14 +5531,10 @@ static void lo_destroy(LibreOfficeKit* pThis)
SAL_INFO("lok", "LO Destroy Done");
}
-}
-
#ifdef IOS
// Used by the unmaintained LibreOfficeLight app. Once that has been retired, get rid of this, too.
-extern "C"
-{
__attribute__((visibility("default")))
void temporaryHackToInvokeCallbackHandlers(LibreOfficeKitDocument* pThis)
{
@@ -5519,7 +5548,9 @@ void temporaryHackToInvokeCallbackHandlers(LibreOfficeKitDocument* pThis)
pDocument->mpCallbackFlushHandlers[nOrigViewId]->Invoke();
}
}
-}
+
#endif
+} // extern "C"
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx
index 015690bd9bc4..74e5131f435d 100644
--- a/desktop/source/lib/lokclipboard.cxx
+++ b/desktop/source/lib/lokclipboard.cxx
@@ -8,23 +8,103 @@
*/
#include "lokclipboard.hxx"
-#include <comphelper/sequence.hxx>
+#include <sfx2/lokhelper.hxx>
-using namespace com::sun::star;
+using namespace css;
+using namespace css::uno;
-uno::Reference<datatransfer::XTransferable> SAL_CALL LOKClipboard::getContents()
+osl::Mutex LOKClipboardFactory::gMutex;
+std::unordered_map<int, rtl::Reference<LOKClipboard>> LOKClipboardFactory::gClipboards;
+
+rtl::Reference<LOKClipboard> LOKClipboardFactory::getClipboardForCurView()
+{
+ int nViewId = SfxLokHelper::getView(); // currently active.
+
+ osl::MutexGuard aGuard(gMutex);
+
+ auto it = gClipboards.find(nViewId);
+ if (it != gClipboards.end())
+ return it->second;
+ rtl::Reference<LOKClipboard> xClip(new LOKClipboard());
+ gClipboards[nViewId] = xClip;
+ SAL_INFO("lok", "Created clipboard for view " << nViewId << " as " << xClip.get());
+ return xClip;
+}
+
+uno::Reference<uno::XInterface>
+ SAL_CALL LOKClipboardFactory::createInstanceWithArguments(const Sequence<Any>& /* rArgs */)
+{
+ return uno::Reference<uno::XInterface>(
+ static_cast<cppu::OWeakObject*>(getClipboardForCurView().get()));
+}
+
+LOKClipboard::LOKClipboard()
+ : cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
+ css::lang::XServiceInfo>(m_aMutex)
+{
+}
+
+Sequence<OUString> LOKClipboard::getSupportedServiceNames_static()
+{
+ Sequence<OUString> aRet{ "com.sun.star.datatransfer.clipboard.SystemClipboard" };
+ return aRet;
+}
+
+OUString LOKClipboard::getImplementationName()
+{
+ return OUString("com.sun.star.datatransfer.LOKClipboard");
+}
+
+Sequence<OUString> LOKClipboard::getSupportedServiceNames()
+{
+ return getSupportedServiceNames_static();
+}
+
+sal_Bool LOKClipboard::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Reference<css::datatransfer::XTransferable> LOKClipboard::getContents() { return m_xTransferable; }
+
+void LOKClipboard::setContents(
+ const Reference<css::datatransfer::XTransferable>& xTrans,
+ const Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
{
- return m_xTransferable;
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+ Reference<datatransfer::clipboard::XClipboardOwner> xOldOwner(m_aOwner);
+ Reference<datatransfer::XTransferable> xOldContents(m_xTransferable);
+ m_xTransferable = xTrans;
+ m_aOwner = xClipboardOwner;
+
+ std::vector<Reference<datatransfer::clipboard::XClipboardListener>> aListeners(m_aListeners);
+ datatransfer::clipboard::ClipboardEvent aEv;
+ aEv.Contents = m_xTransferable;
+
+ aGuard.clear();
+
+ if (xOldOwner.is() && xOldOwner != xClipboardOwner)
+ xOldOwner->lostOwnership(this, xOldContents);
+ for (auto const& listener : aListeners)
+ {
+ listener->changedContents(aEv);
+ }
}
-void SAL_CALL LOKClipboard::setContents(
- const uno::Reference<datatransfer::XTransferable>& xTransferable,
- const uno::Reference<datatransfer::clipboard::XClipboardOwner>& /*xClipboardOwner*/)
+void LOKClipboard::addClipboardListener(
+ const Reference<datatransfer::clipboard::XClipboardListener>& listener)
{
- m_xTransferable = xTransferable;
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+ m_aListeners.push_back(listener);
}
-OUString SAL_CALL LOKClipboard::getName() { return OUString(); }
+void LOKClipboard::removeClipboardListener(
+ const Reference<datatransfer::clipboard::XClipboardListener>& listener)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+ m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener),
+ m_aListeners.end());
+}
LOKTransferable::LOKTransferable(const char* pMimeType, const char* pData, std::size_t nSize)
: m_aMimeType(OUString::fromUtf8(pMimeType))
diff --git a/desktop/source/lib/lokclipboard.hxx b/desktop/source/lib/lokclipboard.hxx
index 5da8b3e2b63e..d917a377eb11 100644
--- a/desktop/source/lib/lokclipboard.hxx
+++ b/desktop/source/lib/lokclipboard.hxx
@@ -11,24 +11,60 @@
#define INCLUDED_DESKTOP_SOURCE_LIB_LOKCLIPBOARD_HXX
#include <vector>
+#include <unordered_map>
+#include <rtl/ref.hxx>
#include <cppuhelper/implbase.hxx>
-#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <cppuhelper/compbase.hxx>
+#include <comphelper/sequence.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/datatransfer/clipboard/XSystemClipboard.hpp>
+
+using namespace css::uno;
/// A clipboard implementation for LibreOfficeKit.
-class LOKClipboard : public cppu::WeakImplHelper<css::datatransfer::clipboard::XClipboard>
+class LOKClipboard
+ : public cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
+ css::lang::XServiceInfo>
{
- css::uno::Reference<css::datatransfer::XTransferable> m_xTransferable;
+ osl::Mutex m_aMutex;
+ css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner> m_aOwner;
+ std::vector<css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>> m_aListeners;
public:
- css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL getContents() override;
+ LOKClipboard();
+
+ /// get an XInterface easily.
+ css::uno::Reference<css::uno::XInterface> getXI()
+ {
+ return css::uno::Reference<css::uno::XInterface>(static_cast<cppu::OWeakObject*>(this));
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+ static Sequence<OUString> getSupportedServiceNames_static();
+ // XClipboard
+ css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL getContents() override;
void SAL_CALL setContents(
const css::uno::Reference<css::datatransfer::XTransferable>& xTransferable,
const css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
override;
+ OUString SAL_CALL getName() override { return OUString("CLIPBOARD"); }
+
+ // XClipboardEx
+ sal_Int8 SAL_CALL getRenderingCapabilities() override { return 0; }
- OUString SAL_CALL getName() override;
+ // XClipboardNotifier
+ void SAL_CALL addClipboardListener(
+ const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener)
+ override;
+ void SAL_CALL removeClipboardListener(
+ const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener)
+ override;
};
/// Represents the contents of LOKClipboard.
@@ -38,10 +74,8 @@ class LOKTransferable : public cppu::WeakImplHelper<css::datatransfer::XTransfer
std::vector<css::uno::Any> m_aContent;
public:
- LOKTransferable(const size_t nInCount,
- const char **pInMimeTypes,
- const size_t *pInSizes,
- const char **pInStreams);
+ LOKTransferable(const size_t nInCount, const char** pInMimeTypes, const size_t* pInSizes,
+ const char** pInStreams);
css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& rFlavor) override;
@@ -50,6 +84,27 @@ public:
sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor) override;
};
+/// Theoretically to hook into the (horrible) vcl dtranscomp.cxx code.
+class LOKClipboardFactory : public ::cppu::WeakComponentImplHelper<css::lang::XSingleServiceFactory>
+{
+ static osl::Mutex gMutex;
+ static std::unordered_map<int, rtl::Reference<LOKClipboard>> gClipboards;
+
+public:
+ LOKClipboardFactory()
+ : cppu::WeakComponentImplHelper<css::lang::XSingleServiceFactory>(gMutex)
+ {
+ }
+
+ css::uno::Reference<css::uno::XInterface> SAL_CALL createInstance() override
+ {
+ return createInstanceWithArguments(css::uno::Sequence<css::uno::Any>());
+ }
+ css::uno::Reference<css::uno::XInterface> SAL_CALL
+ createInstanceWithArguments(const css::uno::Sequence<css::uno::Any>& /* rArgs */) override;
+ static rtl::Reference<LOKClipboard> getClipboardForCurView();
+};
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index abdc9863c1f0..93b430f5da0b 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -390,8 +390,8 @@ struct _LibreOfficeKitDocumentClass
const int width, const int height);
/// Pass a nullptr terminated array of mime-type strings
- /// @see lok::Document::getSelection for more details
- int (*getSelection) (LibreOfficeKitDocument* pThis,
+ /// @see lok::Document::getClipboard for more details
+ int (*getClipboard) (LibreOfficeKitDocument* pThis,
const char **pMimeTypes,
size_t *pOutCount,
char ***pOutMimeTypes,
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index f38d2b5109f6..bd6609c321a4 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -362,7 +362,7 @@ public:
}
/**
- * Gets the selected content for the current view as a series of binary streams.
+ * Gets the content on the clipboard for the current view as a series of binary streams.
*
* NB. returns a complete set of possible selection types if nullptr is passed for pMimeTypes.
*
@@ -374,13 +374,13 @@ public:
*
* @returns: true on success, false on error.
*/
- bool getSelection(const char **pMimeTypes,
+ bool getClipboard(const char **pMimeTypes,
size_t *pOutCount,
char ***pOutMimeTypes,
size_t **pOutSizes,
char ***pOutStreams)
{
- return mpDoc->pClass->getSelection(mpDoc, pMimeTypes, pOutCount, pOutMimeTypes, pOutSizes, pOutStreams);
+ return mpDoc->pClass->getClipboard(mpDoc, pMimeTypes, pOutCount, pOutMimeTypes, pOutSizes, pOutStreams);
}
/**