[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - include/vcl vcl/inc vcl/source vcl/unx
Szymon KÅos (via logerrit)
logerrit at kemper.freedesktop.org
Sat Dec 19 16:54:36 UTC 2020
include/vcl/salvtables.hxx | 5 +
include/vcl/transfer.hxx | 2
include/vcl/treelistbox.hxx | 6 ++
include/vcl/weld.hxx | 10 +++
vcl/inc/treeglue.hxx | 7 +-
vcl/inc/unx/gtk/gtkinst.hxx | 7 ++
vcl/source/app/salvtables.cxx | 12 +++-
vcl/source/treelist/treelistbox.cxx | 27 +++++++---
vcl/unx/gtk3/gtk3gtkframe.cxx | 34 +++++++++----
vcl/unx/gtk3/gtk3gtkinst.cxx | 92 ++++++++++++++++++++++++++++++++++++
10 files changed, 178 insertions(+), 24 deletions(-)
New commits:
commit d4268144906ef261c6a7e32502925edd5c6dc16b
Author: Szymon Kłos <szymon.klos at collabora.com>
AuthorDate: Sat Dec 19 15:52:33 2020 +0100
Commit: Szymon Kłos <szymon.klos at collabora.com>
CommitDate: Sat Dec 19 17:54:01 2020 +0100
Start Drag event support
part of 19d17a7
Change-Id: I1a1b5fd4f4aedbf79f64fdb4334aadc014b4eabb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108026
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
diff --git a/include/vcl/salvtables.hxx b/include/vcl/salvtables.hxx
index 401cbb0702a3..b96d02f0a5a8 100644
--- a/include/vcl/salvtables.hxx
+++ b/include/vcl/salvtables.hxx
@@ -1138,7 +1138,7 @@ protected:
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;
@@ -1373,6 +1373,9 @@ public:
virtual void set_id(const weld::TreeIter& rIter, const OUString& rId) override;
+ virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper,
+ sal_uInt8 eDNDConstants) override;
+
virtual void set_selection_mode(SelectionMode eMode) override;
virtual void all_foreach(const std::function<bool(weld::TreeIter&)>& func) override;
diff --git a/include/vcl/transfer.hxx b/include/vcl/transfer.hxx
index 75af922a007c..a0b773984d3b 100644
--- a/include/vcl/transfer.hxx
+++ b/include/vcl/transfer.hxx
@@ -483,7 +483,7 @@ public:
struct TransferDataContainer_Impl;
-class VCL_DLLPUBLIC TransferDataContainer final : public TransferableHelper
+class VCL_DLLPUBLIC TransferDataContainer : public TransferableHelper
{
std::unique_ptr<TransferDataContainer_Impl> pImpl;
diff --git a/include/vcl/treelistbox.hxx b/include/vcl/treelistbox.hxx
index d0fcfabd9e01..537e4abc7a8d 100644
--- a/include/vcl/treelistbox.hxx
+++ b/include/vcl/treelistbox.hxx
@@ -227,9 +227,13 @@ class VCL_DLLPUBLIC SvTreeListBox
SelectionMode eSelMode;
sal_Int32 nMinWidthInChars;
+ sal_Int8 mnDragAction;
+
SvTreeListEntry* pEdEntry;
SvLBoxItem* pEdItem;
+ rtl::Reference<TransferDataContainer> m_xTransferHelper;
+
protected:
std::unique_ptr<SvImpLBox> pImpl;
short nColumns;
@@ -736,6 +740,8 @@ public:
void SetForceMakeVisible(bool bEnable);
virtual FactoryFunction GetUITestFactory() const override;
+
+ void SetDragHelper(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants);
};
class SvInplaceEdit2
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 496f1e718f7c..3acf96b1fcf7 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -63,6 +63,7 @@ enum class PointerStyle;
class SvNumberFormatter;
class KeyEvent;
class MouseEvent;
+class TransferDataContainer;
class OutputDevice;
class VirtualDevice;
struct SystemEnvData;
@@ -709,7 +710,10 @@ protected:
Link<const TreeIter&, bool> m_aCollapsingHdl;
Link<TreeView&, void> m_aVisibleRangeChangedHdl;
Link<TreeView&, void> m_aModelChangedHdl;
+ // if handler returns true, then menu has been show and event is consumed
Link<const CommandEvent&, bool> m_aPopupMenuHdl;
+ // if handler returns true, drag is disallowed
+ Link<TreeView&, bool> m_aDragBeginHdl;
std::function<int(const weld::TreeIter&, const weld::TreeIter&)> m_aCustomSort;
std::vector<int> m_aRadioIndexes;
@@ -978,6 +982,12 @@ public:
m_aPopupMenuHdl = rLink;
}
+ virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rTransferrable,
+ sal_uInt8 eDNDConstants)
+ = 0;
+
+ void connect_drag_begin(const Link<TreeView&, bool>& rLink) { m_aDragBeginHdl = rLink; }
+
//all of them
void select_all() { unselect(-1); }
void unselect_all() { select(-1); }
diff --git a/vcl/inc/treeglue.hxx b/vcl/inc/treeglue.hxx
index 69641906aa17..49eccdbca4d5 100644
--- a/vcl/inc/treeglue.hxx
+++ b/vcl/inc/treeglue.hxx
@@ -56,7 +56,7 @@ public:
class LclTabListBox : 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 4cf7369c7992..f2d049448a5c 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 4285b037c880..ee0e074bad2e 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -4294,6 +4294,11 @@ void SalInstanceTreeView::set_id(const weld::TreeIter& rIter, const OUString& rI
set_id(rVclIter.iter, rId);
}
+void SalInstanceTreeView::enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants)
+{
+ m_xTreeView->SetDragHelper(rHelper, eDNDConstants);
+}
+
void SalInstanceTreeView::set_selection_mode(SelectionMode eMode)
{
m_xTreeView->SetSelectionMode(eMode);
@@ -4538,7 +4543,7 @@ SalInstanceTreeView::~SalInstanceTreeView()
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>());
@@ -4604,9 +4609,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 6c91289f019d..f6653c7b508d 100644
--- a/vcl/source/treelist/treelistbox.cxx
+++ b/vcl/source/treelist/treelistbox.cxx
@@ -373,6 +373,7 @@ SvTreeListBox::SvTreeListBox(vcl::Window* pParent, WinBits nWinStyle) :
mbHoverSelection(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 4651f81a0830..4156316a7c3c 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -4227,18 +4227,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
@@ -4253,11 +4273,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 8850c8f87c88..b5251c2cd90f 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -8168,6 +8168,7 @@ private:
o3tl::sorted_vector<GtkTreePath*, CompareGtkTreePath> m_aExpandingPlaceHolderParents;
std::vector<GtkSortType> m_aSavedSortTypes;
std::vector<int> m_aSavedSortColumns;
+ rtl::Reference<GtkDragSource> m_xDragSource;
bool m_bWorkAroundBadDragRegion;
bool m_bInDrag;
gint m_nTextCol;
@@ -8186,6 +8187,9 @@ private:
gulong m_nPopupMenuSignalId;
gulong m_nDragBeginSignalId;
gulong m_nDragEndSignalId;
+ gulong m_nDragFailedSignalId;
+ gulong m_nDragDataDeleteignalId;
+ gulong m_nDragGetSignalId;
gulong m_nKeyPressSignalId;
GtkAdjustment* m_pVAdjustment;
ImplSVEvent* m_pChangeEvent;
@@ -8643,6 +8647,65 @@ private:
return default_sort_func(pModel, a, b, m_xSorter.get());
}
+ static void signalDragBegin(GtkWidget*, GdkDragContext* context, gpointer widget)
+ {
+ GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ 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);
+ }
+ }
+
+ 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)
{
if (pEvent->keyval != GDK_KEY_Left && pEvent->keyval != GDK_KEY_Right)
@@ -8749,6 +8812,11 @@ public:
, m_nTestCollapseRowSignalId(g_signal_connect(pTreeView, "test-collapse-row", G_CALLBACK(signalTestCollapseRow), this))
, m_nVAdjustmentChangedSignalId(0)
, 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_pVAdjustment(gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(pTreeView)))
, m_pChangeEvent(nullptr)
@@ -9980,6 +10048,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();
@@ -10228,6 +10314,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);
g_signal_handler_disconnect(m_pTreeModel, m_nRowDeletedSignalId);
g_signal_handler_disconnect(m_pTreeModel, m_nRowInsertedSignalId);
More information about the Libreoffice-commits
mailing list