summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-11-29 10:21:11 +0000
committerCaolán McNamara <caolanm@redhat.com>2019-12-01 20:51:12 +0100
commit19d17a739cc61341ca74cfa485e919c6012fe28c (patch)
treebe3823e68681d796275149d08059872dde680534 /vcl
parentb1f9e704cb9148b6e211005dab0cd153957a1b2b (diff)
weld FmFieldWin
needs drag source support fixes a leak of ColumnInfo data as well Change-Id: I671834726aed3fd4de096b56baaa592f51a9e73e Reviewed-on: https://gerrit.libreoffice.org/84147 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/treeglue.hxx7
-rw-r--r--vcl/inc/unx/gtk/gtkinst.hxx7
-rw-r--r--vcl/source/app/salvtables.cxx14
-rw-r--r--vcl/source/treelist/treelistbox.cxx27
-rw-r--r--vcl/unx/gtk3/gtk3gtkframe.cxx34
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx98
6 files changed, 161 insertions, 26 deletions
diff --git a/vcl/inc/treeglue.hxx b/vcl/inc/treeglue.hxx
index 69975035bbcc..9de3a9d4222a 100644
--- a/vcl/inc/treeglue.hxx
+++ b/vcl/inc/treeglue.hxx
@@ -56,7 +56,7 @@ public:
class LclTabListBox final : public SvTabListBox
{
Link<SvTreeListBox*, void> m_aModelChangedHdl;
- Link<SvTreeListBox*, void> m_aStartDragHdl;
+ Link<SvTreeListBox*, bool> m_aStartDragHdl;
Link<SvTreeListBox*, void> m_aEndDragHdl;
Link<SvTreeListEntry*, bool> m_aEditingEntryHdl;
Link<std::pair<SvTreeListEntry*, OUString>, bool> m_aEditedEntryHdl;
@@ -68,7 +68,7 @@ public:
}
void SetModelChangedHdl(const Link<SvTreeListBox*, void>& rLink) { m_aModelChangedHdl = rLink; }
- void SetStartDragHdl(const Link<SvTreeListBox*, void>& rLink) { m_aStartDragHdl = rLink; }
+ void SetStartDragHdl(const Link<SvTreeListBox*, bool>& rLink) { m_aStartDragHdl = rLink; }
void SetEndDragHdl(const Link<SvTreeListBox*, void>& rLink) { m_aEndDragHdl = rLink; }
void SetEditingEntryHdl(const Link<SvTreeListEntry*, bool>& rLink)
{
@@ -86,7 +86,8 @@ public:
virtual void StartDrag(sal_Int8 nAction, const Point& rPosPixel) override
{
- m_aStartDragHdl.Call(this);
+ if (m_aStartDragHdl.Call(this))
+ return;
SvTabListBox::StartDrag(nAction, rPosPixel);
}
diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
index 74409d3cb51f..b4a516b3a28a 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -150,6 +150,13 @@ public:
{
}
+ void set_datatransfer(const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
+ const css::uno::Reference<css::datatransfer::dnd::XDragSourceListener>& rListener);
+
+ std::vector<GtkTargetEntry> FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats);
+
+ void setActiveDragSource();
+
virtual ~GtkDragSource() override;
// XDragSource
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index b7e974e02195..3bfc4e1e92a7 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -3438,7 +3438,7 @@ private:
DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void);
DECL_LINK(ToggleHdl, SvLBoxButtonData*, void);
DECL_LINK(ModelChangedHdl, SvTreeListBox*, void);
- DECL_LINK(StartDragHdl, SvTreeListBox*, void);
+ DECL_LINK(StartDragHdl, SvTreeListBox*, bool);
DECL_STATIC_LINK(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void);
DECL_LINK(EditingEntryHdl, SvTreeListEntry*, bool);
typedef std::pair<SvTreeListEntry*, OUString> IterString;
@@ -4350,6 +4350,11 @@ public:
set_id(rVclIter.iter, rId);
}
+ virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants) override
+ {
+ m_xTreeView->SetDragHelper(rHelper, eDNDConstants);
+ }
+
virtual void set_selection_mode(SelectionMode eMode) override
{
m_xTreeView->SetSelectionMode(eMode);
@@ -4582,7 +4587,7 @@ public:
else
{
static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(Link<SvTreeListBox*, void>());
- static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, void>());
+ static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, bool>());
static_cast<LclTabListBox&>(*m_xTreeView).SetModelChangedHdl(Link<SvTreeListBox*, void>());
}
m_xTreeView->SetPopupMenuHdl(Link<const CommandEvent&, bool>());
@@ -4651,9 +4656,12 @@ IMPL_LINK_NOARG(SalInstanceTreeView, ModelChangedHdl, SvTreeListBox*, void)
signal_model_changed();
}
-IMPL_LINK_NOARG(SalInstanceTreeView, StartDragHdl, SvTreeListBox*, void)
+IMPL_LINK_NOARG(SalInstanceTreeView, StartDragHdl, SvTreeListBox*, bool)
{
+ if (m_aDragBeginHdl.Call(*this))
+ return true;
g_DragSource = this;
+ return false;
}
IMPL_STATIC_LINK_NOARG(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void)
diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx
index 601574b95d23..fc73a389bfb2 100644
--- a/vcl/source/treelist/treelistbox.cxx
+++ b/vcl/source/treelist/treelistbox.cxx
@@ -373,6 +373,7 @@ SvTreeListBox::SvTreeListBox(vcl::Window* pParent, WinBits nWinStyle) :
mbQuickSearch(false),
eSelMode(SelectionMode::NONE),
nMinWidthInChars(0),
+ mnDragAction(DND_ACTION_COPYMOVE | DND_ACTION_LINK),
mbCenterAndClipText(false)
{
nImpFlags = SvTreeListBoxFlags::NONE;
@@ -1152,7 +1153,6 @@ void SvTreeListBox::SetupDragOrigin()
void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
{
-
Point aEventPos( rPosPixel );
MouseEvent aMouseEvt( aEventPos, 1, MouseEventModifiers::SELECT, MOUSE_LEFT );
MouseButtonUp( aMouseEvt );
@@ -1170,8 +1170,17 @@ void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
return;
}
- rtl::Reference<TransferDataContainer> pContainer = new TransferDataContainer;
- nDragDropMode = NotifyStartDrag( *pContainer, pEntry );
+ rtl::Reference<TransferDataContainer> xContainer = m_xTransferHelper;
+
+ if (!xContainer)
+ {
+ xContainer.set(new TransferDataContainer);
+ // apparently some (unused) content is needed
+ xContainer->CopyAnyData( SotClipboardFormatId::TREELISTBOX,
+ "unused", SAL_N_ELEMENTS("unused") );
+ }
+
+ nDragDropMode = NotifyStartDrag( *xContainer, pEntry );
if( nDragDropMode == DragDropMode::NONE || 0 == GetSelectionCount() )
{
nDragDropMode = nOldDragMode;
@@ -1181,10 +1190,6 @@ void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
SetupDragOrigin();
- // apparently some (unused) content is needed
- pContainer->CopyAnyData( SotClipboardFormatId::TREELISTBOX,
- "unused", SAL_N_ELEMENTS("unused") );
-
bool bOldUpdateMode = Control::IsUpdateMode();
Control::SetUpdateMode( true );
Update();
@@ -1196,7 +1201,13 @@ void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
// (GetSourceListBox()->EnableSelectionAsDropTarget( true, true );)
EnableSelectionAsDropTarget( false );
- pContainer->StartDrag( this, DND_ACTION_COPYMOVE | DND_ACTION_LINK, GetDragFinishedHdl() );
+ xContainer->StartDrag(this, mnDragAction, GetDragFinishedHdl());
+}
+
+void SvTreeListBox::SetDragHelper(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants)
+{
+ m_xTransferHelper = rHelper;
+ mnDragAction = eDNDConstants;
}
void SvTreeListBox::DragFinished( sal_Int8
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index 91df150c26cf..8483304923e9 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -4231,18 +4231,38 @@ sal_uIntPtr GtkSalFrame::GetNativeWindowHandle()
return GetNativeWindowHandle(m_pWindow);
}
+void GtkDragSource::set_datatransfer(const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
+ const css::uno::Reference<css::datatransfer::dnd::XDragSourceListener>& rListener)
+{
+ m_xListener = rListener;
+ m_xTrans = rTrans;
+}
+
+void GtkDragSource::setActiveDragSource()
+{
+ // For LibreOffice internal D&D we provide the Transferable without Gtk
+ // intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this
+ g_ActiveDragSource = this;
+ g_DropSuccessSet = false;
+ g_DropSuccess = false;
+}
+
+std::vector<GtkTargetEntry> GtkDragSource::FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats)
+{
+ return m_aConversionHelper.FormatsToGtk(rFormats);
+}
+
void GtkDragSource::startDrag(const datatransfer::dnd::DragGestureEvent& rEvent,
sal_Int8 sourceActions, sal_Int32 /*cursor*/, sal_Int32 /*image*/,
const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
const css::uno::Reference<css::datatransfer::dnd::XDragSourceListener>& rListener)
{
- m_xListener = rListener;
- m_xTrans = rTrans;
+ set_datatransfer(rTrans, rListener);
if (m_pFrame)
{
- css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = rTrans->getTransferDataFlavors();
- std::vector<GtkTargetEntry> aGtkTargets(m_aConversionHelper.FormatsToGtk(aFormats));
+ auto aFormats = m_xTrans->getTransferDataFlavors();
+ std::vector<GtkTargetEntry> aGtkTargets(FormatsToGtk(aFormats));
GtkTargetList *pTargetList = gtk_target_list_new(aGtkTargets.data(), aGtkTargets.size());
gint nDragButton = 1; // default to left button
@@ -4257,11 +4277,7 @@ void GtkDragSource::startDrag(const datatransfer::dnd::DragGestureEvent& rEvent,
nDragButton = 2;
}
- // For LibreOffice internal D&D we provide the Transferable without Gtk
- // intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this
- g_ActiveDragSource = this;
- g_DropSuccessSet = false;
- g_DropSuccess = false;
+ setActiveDragSource();
m_pFrame->startDrag(nDragButton, rEvent.DragOriginX, rEvent.DragOriginY,
VclToGdk(sourceActions), pTargetList);
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 976ed97be496..39b3357fe4a2 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -22,6 +22,7 @@
#include <headless/svpvd.hxx>
#include <headless/svpbmp.hxx>
#include <vcl/inputtypes.hxx>
+#include <vcl/transfer.hxx>
#include <unx/genpspgraphics.h>
#include <rtl/strbuf.hxx>
#include <sal/log.hxx>
@@ -7945,6 +7946,18 @@ namespace
return -1;
}
+ GdkDragAction VclToGdk(sal_Int8 dragOperation)
+ {
+ GdkDragAction eRet(static_cast<GdkDragAction>(0));
+ if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_COPY)
+ eRet = static_cast<GdkDragAction>(eRet | GDK_ACTION_COPY);
+ if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_MOVE)
+ eRet = static_cast<GdkDragAction>(eRet | GDK_ACTION_MOVE);
+ if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_LINK)
+ eRet = static_cast<GdkDragAction>(eRet | GDK_ACTION_LINK);
+ return eRet;
+ }
+
struct GtkInstanceTreeIter : public weld::TreeIter
{
GtkInstanceTreeIter(const GtkInstanceTreeIter* pOrig)
@@ -7993,6 +8006,7 @@ private:
std::vector<int> m_aSavedSortColumns;
std::vector<int> m_aViewColToModelCol;
std::vector<int> m_aModelColToViewCol;
+ rtl::Reference<GtkDragSource> m_xDragSource;
bool m_bWorkAroundBadDragRegion;
bool m_bInDrag;
gint m_nTextCol;
@@ -8008,6 +8022,9 @@ private:
gulong m_nPopupMenuSignalId;
gulong m_nDragBeginSignalId;
gulong m_nDragEndSignalId;
+ gulong m_nDragFailedSignalId;
+ gulong m_nDragDataDeleteignalId;
+ gulong m_nDragGetSignalId;
gulong m_nKeyPressSignalId;
ImplSVEvent* m_pChangeEvent;
@@ -8392,15 +8409,63 @@ private:
return default_sort_func(pModel, a, b, m_xSorter.get());
}
- static void signalDragBegin(GtkWidget*, GdkDragContext*, gpointer widget)
+ static void signalDragBegin(GtkWidget*, GdkDragContext* context, gpointer widget)
{
GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
- g_DragSource = pThis;
+ pThis->signal_drag_begin(context);
+ }
+
+ void ensure_drag_source()
+ {
+ if (!m_xDragSource)
+ {
+ m_xDragSource.set(new GtkDragSource);
+
+ m_nDragFailedSignalId = g_signal_connect(m_pWidget, "drag-failed", G_CALLBACK(signalDragFailed), this);
+ m_nDragDataDeleteignalId = g_signal_connect(m_pWidget, "drag-data-delete", G_CALLBACK(signalDragDelete), this);
+ m_nDragGetSignalId = g_signal_connect(m_pWidget, "drag-data-get", G_CALLBACK(signalDragDataGet), this);
+ }
}
- static void signalDragEnd(GtkWidget*, GdkDragContext*, gpointer)
+ void signal_drag_begin(GdkDragContext* context)
+ {
+ if (m_aDragBeginHdl.Call(*this))
+ {
+ gtk_drag_cancel(context);
+ return;
+ }
+ g_DragSource = this;
+ if (!m_xDragSource)
+ return;
+ m_xDragSource->setActiveDragSource();
+ }
+
+ static void signalDragEnd(GtkWidget* /*widget*/, GdkDragContext* context, gpointer widget)
{
g_DragSource = nullptr;
+ GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ if (pThis->m_xDragSource.is())
+ pThis->m_xDragSource->dragEnd(context);
+ }
+
+ static gboolean signalDragFailed(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkDragResult /*result*/, gpointer widget)
+ {
+ GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ pThis->m_xDragSource->dragFailed();
+ return false;
+ }
+
+ static void signalDragDelete(GtkWidget* /*widget*/, GdkDragContext* /*context*/, gpointer widget)
+ {
+ GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ pThis->m_xDragSource->dragDelete();
+ }
+
+ static void signalDragDataGet(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkSelectionData *data, guint info,
+ guint /*time*/, gpointer widget)
+ {
+ GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ pThis->m_xDragSource->dragDataGet(data, info);
}
bool signal_key_press(GdkEventKey* pEvent)
@@ -8463,6 +8528,9 @@ public:
, m_nPopupMenuSignalId(g_signal_connect(pTreeView, "popup-menu", G_CALLBACK(signalPopupMenu), this))
, m_nDragBeginSignalId(g_signal_connect(pTreeView, "drag-begin", G_CALLBACK(signalDragBegin), this))
, m_nDragEndSignalId(g_signal_connect(pTreeView, "drag-end", G_CALLBACK(signalDragEnd), this))
+ , m_nDragFailedSignalId(0)
+ , m_nDragDataDeleteignalId(0)
+ , m_nDragGetSignalId(0)
, m_nKeyPressSignalId(g_signal_connect(pTreeView, "key-press-event", G_CALLBACK(signalKeyPress), this))
, m_pChangeEvent(nullptr)
{
@@ -9649,6 +9717,24 @@ public:
gtk_widget_hide(m_pWidget);
}
+ virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants) override
+ {
+ css::uno::Reference<css::datatransfer::XTransferable> xTrans(rHelper.get());
+ css::uno::Reference<css::datatransfer::dnd::XDragSourceListener> xListener(rHelper.get());
+
+ ensure_drag_source();
+
+ auto aFormats = xTrans->getTransferDataFlavors();
+ std::vector<GtkTargetEntry> aGtkTargets(m_xDragSource->FormatsToGtk(aFormats));
+
+ gtk_tree_view_enable_model_drag_source(m_pTreeView, GDK_BUTTON1_MASK, aGtkTargets.data(), aGtkTargets.size(), VclToGdk(eDNDConstants));
+
+ for (auto &a : aGtkTargets)
+ g_free(a.target);
+
+ m_xDragSource->set_datatransfer(xTrans, xListener);
+ }
+
virtual void set_selection_mode(SelectionMode eMode) override
{
disable_notify_events();
@@ -9876,6 +9962,12 @@ public:
g_signal_handler_disconnect(m_pTreeView, m_nKeyPressSignalId);
g_signal_handler_disconnect(m_pTreeView, m_nDragEndSignalId);
g_signal_handler_disconnect(m_pTreeView, m_nDragBeginSignalId);
+ if (m_nDragFailedSignalId)
+ g_signal_handler_disconnect(m_pTreeView, m_nDragFailedSignalId);
+ if (m_nDragDataDeleteignalId)
+ g_signal_handler_disconnect(m_pTreeView, m_nDragDataDeleteignalId);
+ if (m_nDragGetSignalId)
+ g_signal_handler_disconnect(m_pTreeView, m_nDragGetSignalId);
g_signal_handler_disconnect(m_pTreeView, m_nPopupMenuSignalId);
GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore);
g_signal_handler_disconnect(pModel, m_nRowDeletedSignalId);