diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-03-14 12:51:31 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-03-15 09:57:43 +0100 |
commit | 8bddb3c77048814b370351e0eb72c31f289fb34f (patch) | |
tree | 8b081c15b1779301eee613e6f24de1371dd77265 /vcl | |
parent | f5efc3cb9d2bbcaaca95e15a03815e8f8eda7b09 (diff) |
add drop target support to welded widget
refactor the mega-widget dnd drop target to be reused at
mini-widget level
and weld SwInsertBookmarkDlg
Change-Id: I3f36e1cd902ecf166e369d0a05902d3df2b4f791
Reviewed-on: https://gerrit.libreoffice.org/69274
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/unx/gtk/gtkframe.hxx | 7 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkinst.hxx | 18 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 5 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkframe.cxx | 65 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 59 |
5 files changed, 119 insertions, 35 deletions
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index 248c896b28a1..d67046a940ae 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -219,8 +219,6 @@ class GtkSalFrame : public SalFrame cairo_region_t* m_pRegion; GtkDropTarget* m_pDropTarget; GtkDragSource* m_pDragSource; - bool m_bInDrag; - GtkDnDTransferable* m_pFormatConversionRequest; bool m_bGeometryIsProvisional; #else GdkRegion* m_pRegion; @@ -419,11 +417,6 @@ public: m_pDragSource = nullptr; } - void SetFormatConversionRequest(GtkDnDTransferable *pRequest) - { - m_pFormatConversionRequest = pRequest; - } - void startDrag(gint nButton, gint nDragOriginX, gint nDragOriginY, GdkDragAction sourceActions, GtkTargetList* pTargetList); diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx index 83e56184ddb1..c0e073cca845 100644 --- a/vcl/inc/unx/gtk/gtkinst.hxx +++ b/vcl/inc/unx/gtk/gtkinst.hxx @@ -76,23 +76,25 @@ protected: std::map<OUString, GdkAtom> m_aMimeTypeToAtom; std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector(GdkAtom *targets, gint n_targets); -public: +public: virtual css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& rFlavor) override = 0; - virtual std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector() = 0; - virtual css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override; virtual sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor) override; }; +class GtkDnDTransferable; + class GtkDropTarget : public cppu::WeakComponentImplHelper<css::datatransfer::dnd::XDropTarget, css::lang::XInitialization, css::lang::XServiceInfo> { osl::Mutex m_aMutex; GtkSalFrame* m_pFrame; + GtkDnDTransferable* m_pFormatConversionRequest; bool m_bActive; + bool m_bInDrag; sal_Int8 m_nDefaultActions; std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> m_aListeners; public: @@ -121,6 +123,16 @@ public: void fire_dragOver(const css::datatransfer::dnd::DropTargetDragEvent& dtde); void fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde); void fire_dragExit(const css::datatransfer::dnd::DropTargetEvent& dte); + + void SetFormatConversionRequest(GtkDnDTransferable *pRequest) + { + m_pFormatConversionRequest = pRequest; + } + + gboolean signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time); + gboolean signalDragMotion(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time); + void signalDragDropReceived(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint ttype, guint time); + void signalDragLeave(GtkWidget* pWidget, GdkDragContext* context, guint time); }; class GtkDragSource : public cppu::WeakComponentImplHelper<css::datatransfer::dnd::XDragSource, diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 7c0dd9c85cef..de75da50d37b 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -621,6 +621,11 @@ public: return VclPtr<VirtualDevice>::Create(*Application::GetDefaultDevice(), DeviceFormat::DEFAULT, DeviceFormat::DEFAULT); } + virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> get_drop_target() override + { + return m_xWidget->GetDropTarget(); + } + SystemWindow* getSystemWindow() { return m_xWidget->GetSystemWindow(); diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx index 33c4b5e7b071..8de0b605b916 100644 --- a/vcl/unx/gtk3/gtk3gtkframe.cxx +++ b/vcl/unx/gtk3/gtk3gtkframe.cxx @@ -1074,8 +1074,6 @@ void GtkSalFrame::InitCommon() m_pRegion = nullptr; m_pDropTarget = nullptr; m_pDragSource = nullptr; - m_bInDrag = false; - m_pFormatConversionRequest = nullptr; m_bGeometryIsProvisional = false; m_ePointerStyle = static_cast<PointerStyle>(0xffff); m_pSalMenu = nullptr; @@ -3468,15 +3466,15 @@ class GtkDnDTransferable : public GtkTransferable GdkDragContext *m_pContext; guint m_nTime; GtkWidget *m_pWidget; - GtkSalFrame *m_pFrame; + GtkDropTarget* m_pDropTarget; GMainLoop *m_pLoop; GtkSelectionData *m_pData; public: - GtkDnDTransferable(GdkDragContext *pContext, guint nTime, GtkWidget *pWidget, GtkSalFrame *pFrame) + GtkDnDTransferable(GdkDragContext *pContext, guint nTime, GtkWidget *pWidget, GtkDropTarget *pDropTarget) : m_pContext(pContext) , m_nTime(nTime) , m_pWidget(pWidget) - , m_pFrame(pFrame) + , m_pDropTarget(pDropTarget) , m_pLoop(nullptr) , m_pData(nullptr) { @@ -3498,7 +3496,7 @@ public: */ { m_pLoop = g_main_loop_new(nullptr, true); - m_pFrame->SetFormatConversionRequest(this); + m_pDropTarget->SetFormatConversionRequest(this); gtk_drag_get_data(m_pWidget, m_pContext, it->second, m_nTime); @@ -3511,7 +3509,7 @@ public: g_main_loop_unref(m_pLoop); m_pLoop = nullptr; - m_pFrame->SetFormatConversionRequest(nullptr); + m_pDropTarget->SetFormatConversionRequest(nullptr); } css::uno::Any aRet; @@ -3561,12 +3559,15 @@ GtkDragSource* GtkDragSource::g_ActiveDragSource; gboolean GtkSalFrame::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time, gpointer frame) { GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); - if (!pThis->m_pDropTarget) return false; + return pThis->m_pDropTarget->signalDragDrop(pWidget, context, x, y, time); +} +gboolean GtkDropTarget::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time) +{ css::datatransfer::dnd::DropTargetDropEvent aEvent; - aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pThis->m_pDropTarget); + aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(this); aEvent.Context = new GtkDropTargetDropContext(context, time); aEvent.LocationX = x; aEvent.LocationY = y; @@ -3590,14 +3591,15 @@ gboolean GtkSalFrame::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context if (GtkDragSource::g_ActiveDragSource) xTransferable = GtkDragSource::g_ActiveDragSource->GetTransferrable(); else - xTransferable = new GtkDnDTransferable(context, time, pWidget, pThis); + xTransferable = new GtkDnDTransferable(context, time, pWidget, this); aEvent.Transferable = xTransferable; - pThis->m_pDropTarget->fire_drop(aEvent); + fire_drop(aEvent); return true; } + class GtkDropTargetDragContext : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDragContext> { GdkDragContext *m_pContext; @@ -3620,10 +3622,16 @@ public: } }; -void GtkSalFrame::signalDragDropReceived(GtkWidget* /*pWidget*/, GdkDragContext * /*context*/, gint /*x*/, gint /*y*/, GtkSelectionData* data, guint /*ttype*/, guint /*time*/, gpointer frame) +void GtkSalFrame::signalDragDropReceived(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint ttype, guint time, gpointer frame) { GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + if (!pThis->m_pDropTarget) + return; + pThis->m_pDropTarget->signalDragDropReceived(pWidget, context, x, y, data, ttype, time); +} +void GtkDropTarget::signalDragDropReceived(GtkWidget* /*pWidget*/, GdkDragContext * /*context*/, gint /*x*/, gint /*y*/, GtkSelectionData* data, guint /*ttype*/, guint /*time*/) +{ /* * If we get a drop, then we will call like gtk_clipboard_wait_for_contents * with a loop inside a loop to get the right format, so if this is the @@ -3631,24 +3639,28 @@ void GtkSalFrame::signalDragDropReceived(GtkWidget* /*pWidget*/, GdkDragContext * * don't look at me like that. */ - if (!pThis->m_pFormatConversionRequest) + if (!m_pFormatConversionRequest) return; - pThis->m_pFormatConversionRequest->LoopEnd(gtk_selection_data_copy(data)); + m_pFormatConversionRequest->LoopEnd(gtk_selection_data_copy(data)); } gboolean GtkSalFrame::signalDragMotion(GtkWidget *pWidget, GdkDragContext *context, gint x, gint y, guint time, gpointer frame) { GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); - if (!pThis->m_pDropTarget) return false; + return pThis->m_pDropTarget->signalDragMotion(pWidget, context, x, y, time); +} - if (!pThis->m_bInDrag) + +gboolean GtkDropTarget::signalDragMotion(GtkWidget *pWidget, GdkDragContext *context, gint x, gint y, guint time) +{ + if (!m_bInDrag) gtk_drag_highlight(pWidget); css::datatransfer::dnd::DropTargetDragEnterEvent aEvent; - aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pThis->m_pDropTarget); + aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(this); GtkDropTargetDragContext* pContext = new GtkDropTargetDragContext(context, time); //preliminary accept the Drag and select the preferred action, the fire_* will //inform the original caller of our choice and the callsite can decide @@ -3686,7 +3698,7 @@ gboolean GtkSalFrame::signalDragMotion(GtkWidget *pWidget, GdkDragContext *conte aEvent.DropAction = GdkToVcl(eAction); aEvent.SourceActions = nSourceActions; - if (!pThis->m_bInDrag) + if (!m_bInDrag) { css::uno::Reference<css::datatransfer::XTransferable> xTransferable; // For LibreOffice internal D&D we provide the Transferable without Gtk @@ -3694,26 +3706,31 @@ gboolean GtkSalFrame::signalDragMotion(GtkWidget *pWidget, GdkDragContext *conte if (GtkDragSource::g_ActiveDragSource) xTransferable = GtkDragSource::g_ActiveDragSource->GetTransferrable(); else - xTransferable = new GtkDnDTransferable(context, time, pWidget, pThis); + xTransferable = new GtkDnDTransferable(context, time, pWidget, this); css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = xTransferable->getTransferDataFlavors(); aEvent.SupportedDataFlavors = aFormats; - pThis->m_pDropTarget->fire_dragEnter(aEvent); - pThis->m_bInDrag = true; + fire_dragEnter(aEvent); + m_bInDrag = true; } else { - pThis->m_pDropTarget->fire_dragOver(aEvent); + fire_dragOver(aEvent); } return true; } -void GtkSalFrame::signalDragLeave(GtkWidget *pWidget, GdkDragContext * /*context*/, guint /*time*/, gpointer frame) +void GtkSalFrame::signalDragLeave(GtkWidget *pWidget, GdkDragContext *context, guint time, gpointer frame) { GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); if (!pThis->m_pDropTarget) return; - pThis->m_bInDrag = false; + pThis->m_pDropTarget->signalDragLeave(pWidget, context, time); +} + +void GtkDropTarget::signalDragLeave(GtkWidget* pWidget, GdkDragContext* /*context*/, guint /*time*/) +{ + m_bInDrag = false; gtk_drag_unhighlight(pWidget); } diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 49c6a64bc3f6..d15928180331 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -721,7 +721,9 @@ Reference< XInterface > GtkInstance::CreateClipboard(const Sequence< Any >& argu GtkDropTarget::GtkDropTarget() : WeakComponentImplHelper(m_aMutex) , m_pFrame(nullptr) + , m_pFormatConversionRequest(nullptr) , m_bActive(false) + , m_bInDrag(false) , m_nDefaultActions(0) { } @@ -860,7 +862,7 @@ void GtkDropTarget::setDefaultActions(sal_Int8 nDefaultActions) Reference< XInterface > GtkInstance::CreateDropTarget() { - return Reference< XInterface >( static_cast<cppu::OWeakObject *>(new GtkDropTarget()) ); + return Reference<XInterface>(static_cast<cppu::OWeakObject*>(new GtkDropTarget)); } GtkDragSource::~GtkDragSource() @@ -1289,6 +1291,12 @@ private: gulong m_nButtonPressSignalId; gulong m_nMotionSignalId; gulong m_nButtonReleaseSignalId; + gulong m_nDragMotionSignalId; + gulong m_nDragDropSignalId; + gulong m_nDragDropReceivedSignalId; + gulong m_nDragLeaveSignalId; + + rtl::Reference<GtkDropTarget> m_xDropTarget; static void signalSizeAllocate(GtkWidget*, GdkRectangle* allocation, gpointer widget) { @@ -1422,6 +1430,30 @@ private: return true; } + static gboolean signalDragMotion(GtkWidget *pWidget, GdkDragContext *context, gint x, gint y, guint time, gpointer widget) + { + GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget); + return pThis->m_xDropTarget->signalDragMotion(pWidget, context, x, y, time); + } + + static gboolean signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time, gpointer widget) + { + GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget); + return pThis->m_xDropTarget->signalDragDrop(pWidget, context, x, y, time); + } + + static void signalDragDropReceived(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint ttype, guint time, gpointer widget) + { + GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget); + pThis->m_xDropTarget->signalDragDropReceived(pWidget, context, x, y, data, ttype, time); + } + + static void signalDragLeave(GtkWidget *pWidget, GdkDragContext *context, guint time, gpointer widget) + { + GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget); + pThis->m_xDropTarget->signalDragLeave(pWidget, context, time); + } + public: GtkInstanceWidget(GtkWidget* pWidget, GtkInstanceBuilder* pBuilder, bool bTakeOwnership) : m_pWidget(pWidget) @@ -1437,6 +1469,10 @@ public: , m_nButtonPressSignalId(0) , m_nMotionSignalId(0) , m_nButtonReleaseSignalId(0) + , m_nDragMotionSignalId(0) + , m_nDragDropSignalId(0) + , m_nDragDropReceivedSignalId(0) + , m_nDragLeaveSignalId(0) { } @@ -1816,8 +1852,29 @@ public: bool get_frozen() const { return m_bFrozen; } + virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> get_drop_target() override + { + if (!m_xDropTarget) + { + m_xDropTarget.set(new GtkDropTarget); + m_nDragMotionSignalId = g_signal_connect(m_pWidget, "drag-motion", G_CALLBACK(signalDragMotion), this); + m_nDragDropSignalId = g_signal_connect(m_pWidget, "drag-drop", G_CALLBACK(signalDragDrop), this); + m_nDragDropReceivedSignalId = g_signal_connect(m_pWidget, "drag-data-received", G_CALLBACK(signalDragDropReceived), this); + m_nDragLeaveSignalId = g_signal_connect(m_pWidget, "drag-leave", G_CALLBACK(signalDragLeave), this); + } + return m_xDropTarget.get(); + } + virtual ~GtkInstanceWidget() override { + if (m_nDragMotionSignalId) + g_signal_handler_disconnect(m_pWidget, m_nDragMotionSignalId); + if (m_nDragDropSignalId) + g_signal_handler_disconnect(m_pWidget, m_nDragDropSignalId); + if (m_nDragDropReceivedSignalId) + g_signal_handler_disconnect(m_pWidget, m_nDragDropReceivedSignalId); + if (m_nDragLeaveSignalId) + g_signal_handler_disconnect(m_pWidget, m_nDragLeaveSignalId); if (m_nKeyPressSignalId) g_signal_handler_disconnect(m_pWidget, m_nKeyPressSignalId); if (m_nKeyReleaseSignalId) |