summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-03-14 12:51:31 +0000
committerCaolán McNamara <caolanm@redhat.com>2019-03-15 09:57:43 +0100
commit8bddb3c77048814b370351e0eb72c31f289fb34f (patch)
tree8b081c15b1779301eee613e6f24de1371dd77265 /vcl
parentf5efc3cb9d2bbcaaca95e15a03815e8f8eda7b09 (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.hxx7
-rw-r--r--vcl/inc/unx/gtk/gtkinst.hxx18
-rw-r--r--vcl/source/app/salvtables.cxx5
-rw-r--r--vcl/unx/gtk3/gtk3gtkframe.cxx65
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx59
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)