summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-01-24 09:36:46 +0100
committerMiklos Vajna <vmiklos@collabora.com>2019-01-24 12:48:24 +0100
commite14fafaafb3500d65be9c1b69fcb86b31d36468c (patch)
treea308d8f2adf477aef41f25fbf9d0cb600627cf41
parentb473896d31e4c198100fde582f5b4d12d8e2a1d7 (diff)
sw: make it possible to listen to paste events
The use-case is that the user pastes content and custom postprocessing is necessary for the pasted content. This is not easy by default, since the cursor is at the end of the pasted content, so the start is not known -- even if you intercept the paste UNO command. Precisely tracking the start is possible when using the internal API, SwReader::Read() does something similar already to track the undo range. Only expose the text selection after paste (as a start), but design the API in a way so that other pasted content type (e.g. image) can be added in a backwards-compatible way later. Change-Id: If35bda4244cc417e4858124fb75f7608b95fc556 Reviewed-on: https://gerrit.libreoffice.org/66807 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--offapi/UnoApi_offapi.mk2
-rw-r--r--offapi/com/sun/star/text/XPasteBroadcaster.idl42
-rw-r--r--offapi/com/sun/star/text/XPasteListener.idl42
-rw-r--r--sw/inc/fesh.hxx4
-rw-r--r--sw/inc/unotxdoc.hxx10
-rw-r--r--sw/qa/extras/unowriter/unowriter.cxx77
-rw-r--r--sw/source/core/frmedt/fecopy.cxx2
-rw-r--r--sw/source/core/frmedt/fews.cxx14
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx121
-rw-r--r--sw/source/uibase/inc/swdtflvr.hxx6
-rw-r--r--sw/source/uibase/uno/unotxdoc.cxx17
11 files changed, 327 insertions, 10 deletions
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 9934fff83b8c..f120c550e8e2 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -3784,6 +3784,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/text,\
XPagePrintable \
XParagraphAppend \
XParagraphCursor \
+ XPasteBroadcaster \
+ XPasteListener \
XRedline \
XReferenceMarksSupplier \
XRelativeTextContentInsert \
diff --git a/offapi/com/sun/star/text/XPasteBroadcaster.idl b/offapi/com/sun/star/text/XPasteBroadcaster.idl
new file mode 100644
index 000000000000..faddd99b6c34
--- /dev/null
+++ b/offapi/com/sun/star/text/XPasteBroadcaster.idl
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#ifndef __com_sun_star_text_XPasteBroadcaster_idl__
+#define __com_sun_star_text_XPasteBroadcaster_idl__
+
+#include <com/sun/star/uno/XInterface.idl>
+#include <com/sun/star/text/XPasteListener.idl>
+
+module com { module sun { module star { module text {
+
+/** allows for adding/removing of paste event listeners.
+
+ @since LibreOffice 6.3
+*/
+interface XPasteBroadcaster : com::sun::star::uno::XInterface
+{
+ /** Adds an entry to the list of paste listeners.
+
+ @param xListener
+ The listener to be added.
+ */
+ void addPasteEventListener([in] com::sun::star::text::XPasteListener xListener);
+
+ /** Removes an entry to the list of paste listeners.
+
+ @param xListener
+ The listener to be removed.
+ */
+ void removePasteEventListener( [in] com::sun::star::text::XPasteListener xListener );
+};
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/offapi/com/sun/star/text/XPasteListener.idl b/offapi/com/sun/star/text/XPasteListener.idl
new file mode 100644
index 000000000000..ce5d663f4ccd
--- /dev/null
+++ b/offapi/com/sun/star/text/XPasteListener.idl
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+#ifndef __com_sun_star_text_XPasteListener_idl__
+#define __com_sun_star_text_XPasteListener_idl__
+
+#include <com/sun/star/beans/PropertyValue.idl>
+#include <com/sun/star/uno/XInterface.idl>
+
+module com { module sun { module star { module text {
+
+/** used to notify listeners about paste events.
+
+ @since LibreOffice 6.3
+*/
+interface XPasteListener : com::sun::star::uno::XInterface
+{
+ /** Notifies the listener about paste events.
+
+ @param aEvent
+ The event containing details about the paste.
+
+ <p>The following keys may be used:
+ <ul>
+ <li>TextRange</li>
+ </ul></p>
+ */
+ void notifyPasteEvent([in] sequence< ::com::sun::star::beans::PropertyValue > aEvent);
+};
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index 97feecbeeeab..886cb2d7bf39 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -30,6 +30,7 @@
#include <sot/formats.hxx>
#include <rtl/ustring.hxx>
#include <o3tl/typed_flags_set.hxx>
+#include <comphelper/interfacecontainer2.hxx>
#include <vector>
#include <memory>
@@ -204,6 +205,7 @@ private:
std::unique_ptr<SdrDropMarkerOverlay> m_pChainTo;
std::unique_ptr<SdrDropMarkerOverlay> m_pChainFrom;
bool m_bCheckForOLEInCaption;
+ comphelper::OInterfaceContainerHelper2 m_aPasteListeners;
SAL_DLLPRIVATE SwFlyFrame *FindFlyFrame( const css::uno::Reference < css::embed::XEmbeddedObject >& ) const;
@@ -561,6 +563,8 @@ public:
void Paste( SvStream& rStm, SwPasteSdr nAction, const Point* pPt );
bool Paste( const Graphic &rGrf, const OUString& rURL );
+ comphelper::OInterfaceContainerHelper2& GetPasteListeners();
+
bool IsAlignPossible() const;
void SetCalcFieldValueHdl(Outliner* pOutliner);
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index bc4d7176fd8a..ae3fb79aa936 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -62,6 +62,7 @@
#include <cppuhelper/implbase.hxx>
#include <vcl/ITiledRenderable.hxx>
#include <com/sun/star/tiledrendering/XTiledRenderable.hpp>
+#include <com/sun/star/text/XPasteBroadcaster.hpp>
#include "unobaseclass.hxx"
#include "viewopt.hxx"
@@ -122,7 +123,8 @@ typedef cppu::WeakImplHelper
css::xforms::XFormsSupplier,
css::text::XFlatParagraphIteratorProvider,
css::document::XDocumentLanguages,
- css::util::XCloneable
+ css::util::XCloneable,
+ css::text::XPasteBroadcaster
>
SwXTextDocumentBaseClass;
@@ -379,6 +381,12 @@ public:
// css::util::XCloneable
virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+ // css::text::XPasteBroadcaster
+ void SAL_CALL addPasteEventListener(
+ const ::css::uno::Reference<::css::text::XPasteListener>& xListener) override;
+ void SAL_CALL removePasteEventListener(
+ const ::css::uno::Reference<::css::text::XPasteListener>& xListener) override;
+
/// @see vcl::ITiledRenderable::paintTile().
virtual void paintTile( VirtualDevice &rDevice,
int nOutputWidth,
diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx
index a0e093dc35d5..77186c1d9350 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -20,6 +20,7 @@
#include <toolkit/helper/vclunohelper.hxx>
#include <wrtsh.hxx>
#include <ndtxt.hxx>
+#include <swdtflvr.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
@@ -28,6 +29,31 @@ using namespace ::com::sun::star::text;
namespace
{
char const DATA_DIRECTORY[] = "/sw/qa/extras/unowriter/data/";
+
+/// Listener implementation for testPasteListener.
+class PasteListener : public cppu::WeakImplHelper<text::XPasteListener>
+{
+ OUString m_aString;
+
+public:
+ void SAL_CALL notifyPasteEvent(const uno::Sequence<beans::PropertyValue>& rEvent) override;
+
+ OUString& GetString();
+};
+
+void PasteListener::notifyPasteEvent(const uno::Sequence<beans::PropertyValue>& rEvent)
+{
+ comphelper::SequenceAsHashMap aMap(rEvent);
+ auto it = aMap.find("TextRange");
+ if (it != aMap.end())
+ {
+ auto xTextRange = it->second.get<uno::Reference<text::XTextRange>>();
+ if (xTextRange.is())
+ m_aString = xTextRange->getString();
+ }
+}
+
+OUString& PasteListener::GetString() { return m_aString; }
}
/// Test to assert UNO API call results of Writer.
@@ -463,6 +489,57 @@ DECLARE_UNOAPI_TEST_FILE(testRenderablePagePosition, "renderable-page-position.o
CPPUNIT_ASSERT_GREATER(aPosition1.Y, aPosition2.Y);
}
+DECLARE_UNOAPI_TEST(testPasteListener)
+{
+ loadURL("private:factory/swriter", nullptr);
+
+ // Insert initial string.
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XSimpleText> xBodyText(xTextDocument->getText(), uno::UNO_QUERY);
+ xBodyText->insertString(xBodyText->getStart(), "ABCDEF", false);
+
+ // Add paste listener.
+ uno::Reference<text::XPasteBroadcaster> xBroadcaster(mxComponent, uno::UNO_QUERY);
+ uno::Reference<text::XPasteListener> xListener(new PasteListener);
+ auto pListener = static_cast<PasteListener*>(xListener.get());
+ xBroadcaster->addPasteEventListener(xListener);
+
+ // Cut "DE" and then paste it.
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 3, /*bBasicCall=*/false);
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 2, /*bBasicCall=*/false);
+ rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell);
+ pTransfer->Cut();
+ TransferableDataHelper aHelper(pTransfer.get());
+ SwTransferable::Paste(*pWrtShell, aHelper);
+ // Without working listener registration in place, this test would have
+ // failed with 'Expected: DE; Actual:', i.e. the paste listener was not
+ // invoked.
+ CPPUNIT_ASSERT_EQUAL(OUString("DE"), pListener->GetString());
+
+ // Make sure that paste did not overwrite anything.
+ CPPUNIT_ASSERT_EQUAL(OUString("ABCDEF"), xBodyText->getString());
+
+ // Paste again, this time overwriting "BC".
+ pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, /*bBasicCall=*/false);
+ pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 2, /*bBasicCall=*/false);
+ pListener->GetString().clear();
+ SwTransferable::Paste(*pWrtShell, aHelper);
+ CPPUNIT_ASSERT_EQUAL(OUString("DE"), pListener->GetString());
+
+ // Make sure that paste overwrote "BC".
+ CPPUNIT_ASSERT_EQUAL(OUString("ADEDEF"), xBodyText->getString());
+
+ // Deregister paste listener, make sure it's not invoked.
+ xBroadcaster->removePasteEventListener(xListener);
+ pListener->GetString().clear();
+ SwTransferable::Paste(*pWrtShell, aHelper);
+ CPPUNIT_ASSERT(pListener->GetString().isEmpty());
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 430871b0657b..209c93e50c38 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -1178,6 +1178,8 @@ void SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt1
EndAllAction();
}
+comphelper::OInterfaceContainerHelper2& SwFEShell::GetPasteListeners() { return m_aPasteListeners; }
+
bool SwFEShell::GetDrawObjGraphic( SotClipboardFormatId nFormat, Graphic& rGrf ) const
{
OSL_ENSURE( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" );
diff --git a/sw/source/core/frmedt/fews.cxx b/sw/source/core/frmedt/fews.cxx
index 00b5a0a12512..d6108875560c 100644
--- a/sw/source/core/frmedt/fews.cxx
+++ b/sw/source/core/frmedt/fews.cxx
@@ -55,6 +55,18 @@
using namespace com::sun::star;
+namespace
+{
+/**
+ * This mutex is only used for the paste listeners, where the solar mutex can't
+ * be used.
+ */
+osl::Mutex& GetPasteMutex()
+{
+ static osl::Mutex aMutex;
+ return aMutex;
+}
+}
void SwFEShell::EndAllActionAndCall()
{
@@ -694,12 +706,14 @@ sal_uInt16 SwFEShell::GetCurOutColNum() const
SwFEShell::SwFEShell( SwDoc& rDoc, vcl::Window *pWindow, const SwViewOption *pOptions )
: SwEditShell( rDoc, pWindow, pOptions )
, m_bCheckForOLEInCaption(false)
+ , m_aPasteListeners(GetPasteMutex())
{
}
SwFEShell::SwFEShell( SwEditShell& rShell, vcl::Window *pWindow )
: SwEditShell( rShell, pWindow )
, m_bCheckForOLEInCaption(false)
+ , m_aPasteListeners(GetPasteMutex())
{
}
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index 67c7d3f30866..c7aa43238729 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -24,6 +24,7 @@
#include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp>
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
#include <com/sun/star/embed/MSOLEObjectSystemCreator.hpp>
+#include <com/sun/star/text/XPasteListener.hpp>
#include <svtools/embedtransfer.hxx>
#include <svtools/insdlg.hxx>
@@ -124,6 +125,7 @@
#include <fmtmeta.hxx>
#include <itabenum.hxx>
#include <iodetect.hxx>
+#include <unotextrange.hxx>
#include <vcl/GraphicNativeTransform.hxx>
#include <vcl/GraphicNativeMetadata.hxx>
@@ -178,17 +180,39 @@ public:
void Disconnect( bool bRemoveDataAdvise );
};
+/// Tracks the boundaries of pasted content and notifies listeners.
+class SwPasteContext
+{
+public:
+ SwPasteContext(SwWrtShell& rWrtShell);
+ ~SwPasteContext();
+
+ void remember();
+ void forget();
+
+private:
+ SwWrtShell& m_rWrtShell;
+ std::unique_ptr<SwPaM> m_pPaM;
+ sal_Int32 m_nStartContent = 0;
+};
+
// helper class for Action and Undo enclosing
class SwTrnsfrActionAndUndo
{
SwWrtShell *pSh;
public:
- SwTrnsfrActionAndUndo( SwWrtShell *pS, bool bDelSel = false)
+ SwTrnsfrActionAndUndo( SwWrtShell *pS, bool bDelSel = false, SwPasteContext* pContext = nullptr)
: pSh( pS )
{
pSh->StartUndo( SwUndoId::PASTE_CLIPBOARD );
if( bDelSel )
+ {
+ if (pContext)
+ pContext->forget();
pSh->DelRight();
+ if (pContext)
+ pContext->remember();
+ }
pSh->StartAllAction();
}
~SwTrnsfrActionAndUndo() COVERITY_NOEXCEPT_FALSE
@@ -1071,6 +1095,82 @@ static uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::Referenc
return &xRef;
}
+SwPasteContext::SwPasteContext(SwWrtShell& rWrtShell)
+ : m_rWrtShell(rWrtShell)
+{
+ remember();
+}
+
+void SwPasteContext::remember()
+{
+ if (m_rWrtShell.GetPasteListeners().getLength() == 0)
+ return;
+
+ SwPaM* pCursor = m_rWrtShell.GetCursor();
+ if (!pCursor)
+ return;
+
+ // Set point to the previous node, so it is not moved.
+ const SwNodeIndex& rNodeIndex = pCursor->GetPoint()->nNode;
+ m_pPaM.reset(new SwPaM(rNodeIndex, rNodeIndex, 0, -1));
+ m_nStartContent = pCursor->GetPoint()->nContent.GetIndex();
+}
+
+void SwPasteContext::forget() { m_pPaM.reset(nullptr); }
+
+SwPasteContext::~SwPasteContext()
+{
+ try
+ {
+ if (m_rWrtShell.GetPasteListeners().getLength() == 0)
+ return;
+
+ if (!m_pPaM)
+ return;
+
+ SwPaM* pCursor = m_rWrtShell.GetCursor();
+ if (!pCursor)
+ return;
+
+ if (!pCursor->GetPoint()->nNode.GetNode().IsTextNode())
+ // Non-text was pasted.
+ return;
+
+ // Update mark after paste.
+ *m_pPaM->GetMark() = *pCursor->GetPoint();
+
+ // Restore point.
+ ++m_pPaM->GetPoint()->nNode;
+ SwNode& rNode = m_pPaM->GetNode();
+ if (!rNode.IsTextNode())
+ // Starting point is no longer text.
+ return;
+
+ m_pPaM->GetPoint()->nContent.Assign(static_cast<SwContentNode*>(&rNode), m_nStartContent);
+
+ // Invoke the listeners.
+ beans::PropertyValue aPropertyValue;
+ aPropertyValue.Name = "TextRange";
+ const uno::Reference<text::XTextRange> xTextRange = SwXTextRange::CreateXTextRange(
+ *m_pPaM->GetDoc(), *m_pPaM->GetPoint(), m_pPaM->GetMark());
+ aPropertyValue.Value <<= xTextRange;
+ uno::Sequence<beans::PropertyValue> aEvent{ aPropertyValue };
+
+ comphelper::OInterfaceIteratorHelper2 it(m_rWrtShell.GetPasteListeners());
+ while (it.hasMoreElements())
+ {
+ uno::Reference<text::XPasteListener> xListener(it.next(), UNO_QUERY);
+ if (xListener.is())
+ xListener->notifyPasteEvent(aEvent);
+ }
+ }
+ catch (const uno::Exception& rException)
+ {
+ SAL_WARN("sw",
+ "SwPasteContext::~SwPasteContext: uncaught exception: " << rException.Message);
+ }
+}
+
bool SwTransferable::IsPaste( const SwWrtShell& rSh,
const TransferableDataHelper& rData )
{
@@ -1114,6 +1214,8 @@ bool SwTransferable::IsPaste( const SwWrtShell& rSh,
bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType)
{
+ SwPasteContext aPasteContext(rSh);
+
sal_uInt8 nEventAction, nAction=0;
SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
@@ -1189,7 +1291,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt
if (bInsertOleTableInTable && EXCHG_OUT_ACTION_INSERT_STRING == nAction)
{
bool bPasted = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
- nDestination, false, false, nullptr, 0, false, nAnchorType );
+ nDestination, false, false, nullptr, 0, false, nAnchorType, &aPasteContext );
if (bPasted && rSh.DoesUndo())
{
SfxDispatcher* pDispatch = rSh.GetView().GetViewFrame()->GetDispatcher();
@@ -1204,7 +1306,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt
return EXCHG_INOUT_ACTION_NONE != nAction &&
SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
- nDestination, false, false, nullptr, 0, false, nAnchorType );
+ nDestination, false, false, nullptr, 0, false, nAnchorType, &aPasteContext );
}
bool SwTransferable::PasteData( TransferableDataHelper& rData,
@@ -1213,7 +1315,8 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
SotExchangeDest nDestination, bool bIsPasteFormat,
bool bIsDefault,
const Point* pPt, sal_Int8 nDropAction,
- bool bPasteSelection, RndStdIds nAnchorType )
+ bool bPasteSelection, RndStdIds nAnchorType,
+ SwPasteContext* pContext )
{
SwWait aWait( *rSh.GetView().GetDocShell(), false );
std::unique_ptr<SwTrnsfrActionAndUndo, o3tl::default_delete<SwTrnsfrActionAndUndo>> pAction;
@@ -1272,7 +1375,7 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
if( bDelSel )
// #i34830#
- pAction.reset(new SwTrnsfrActionAndUndo( &rSh, true ));
+ pAction.reset(new SwTrnsfrActionAndUndo(&rSh, true, pContext));
}
SwTransferable *pTrans=nullptr, *pTunneledTrans=GetSwTransferable( rData );
@@ -1319,7 +1422,7 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction )
{
// then internal paste
- bRet = pTunneledTrans->PrivatePaste( rSh );
+ bRet = pTunneledTrans->PrivatePaste(rSh, pContext);
}
else if( EXCHG_INOUT_ACTION_NONE != nAction )
{
@@ -3276,7 +3379,7 @@ bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
}
-bool SwTransferable::PrivatePaste( SwWrtShell& rShell )
+bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext)
{
// first, ask for the SelectionType, then action-bracketing !!!!
// (otherwise it's not pasted into a TableSelection!!!)
@@ -3295,7 +3398,11 @@ bool SwTransferable::PrivatePaste( SwWrtShell& rShell )
{
bKillPaMs = true;
rShell.SetRetainSelection( true );
+ if (pContext)
+ pContext->forget();
rShell.DelRight();
+ if (pContext)
+ pContext->remember();
// when a Fly was selected, a valid cursor position has to be found now
// (parked Cursor!)
if( ( SelectionType::Frame | SelectionType::Graphic |
diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx
index f9dc71623477..c8015d1955c8 100644
--- a/sw/source/uibase/inc/swdtflvr.hxx
+++ b/sw/source/uibase/inc/swdtflvr.hxx
@@ -41,6 +41,7 @@ class SwWrtShell;
class SvxClipboardFormatItem;
class SwFrameShell;
class SwView_Impl;
+class SwPasteContext;
enum class SwPasteSdr;
enum class TransferBufferType : sal_uInt16
@@ -133,7 +134,7 @@ class SW_DLLPUBLIC SwTransferable : public TransferableHelper
bool PrivateDrop( SwWrtShell& rSh, const Point& rDragPt, bool bMove,
bool bIsXSelection );
- bool PrivatePaste( SwWrtShell& rShell );
+ bool PrivatePaste( SwWrtShell& rShell, SwPasteContext* pContext = nullptr );
void SetDataForDragAndDrop( const Point& rSttPos );
@@ -181,7 +182,8 @@ public:
SotExchangeDest nDestination, bool bIsPasteFormat,
bool bIsDefault,
const Point* pDDPos = nullptr, sal_Int8 nDropAction = 0,
- bool bPasteSelection = false, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA );
+ bool bPasteSelection = false, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA,
+ SwPasteContext* pContext = nullptr );
static bool IsPasteSpecial( const SwWrtShell& rWrtShell,
const TransferableDataHelper& );
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index a1324b36422d..9f2e45c766f8 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3183,6 +3183,23 @@ uno::Reference< util::XCloneable > SwXTextDocument::createClone( )
return uno::Reference< util::XCloneable >( xNewModel, UNO_QUERY );
}
+void SwXTextDocument::addPasteEventListener(const uno::Reference<text::XPasteListener>& xListener)
+{
+ SolarMutexGuard aGuard;
+
+ if (IsValid() && xListener.is())
+ pDocShell->GetWrtShell()->GetPasteListeners().addInterface(xListener);
+}
+
+void SwXTextDocument::removePasteEventListener(
+ const uno::Reference<text::XPasteListener>& xListener)
+{
+ SolarMutexGuard aGuard;
+
+ if (IsValid() && xListener.is())
+ pDocShell->GetWrtShell()->GetPasteListeners().removeInterface(xListener);
+}
+
void SwXTextDocument::paintTile( VirtualDevice &rDevice,
int nOutputWidth, int nOutputHeight,
int nTilePosX, int nTilePosY,