[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - vcl/unx
Szymon KÅos (via logerrit)
logerrit at kemper.freedesktop.org
Sat Dec 19 16:54:55 UTC 2020
vcl/unx/gtk3/gtk3gtkinst.cxx | 162 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 162 insertions(+)
New commits:
commit 9dbede8084c2129582817abc8e6400e6ec59a2f8
Author: Szymon Kłos <szymon.klos at collabora.com>
AuthorDate: Sat Dec 19 15:27:29 2020 +0100
Commit: Szymon Kłos <szymon.klos at collabora.com>
CommitDate: Sat Dec 19 17:54:20 2020 +0100
Drag events support in gtk3
parts of fa8c85fa90e9565a357b247a69f930098d11ff84
Change-Id: I797d16cd5f43f7b47d613b1756483cec51ec71f1
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108025
Tested-by: Szymon Kłos <szymon.klos at collabora.com>
Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index b5251c2cd90f..8223c1235f77 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -25,6 +25,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>
@@ -1787,6 +1788,22 @@ namespace
}
}
+namespace {
+
+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;
+}
+
+}
+
class GtkInstanceWidget : public virtual weld::Widget
{
protected:
@@ -1889,6 +1906,25 @@ protected:
return AllSettings::GetLayoutRTL();
}
+ void do_enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, sal_uInt8 eDNDConstants)
+ {
+ 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));
+
+ m_eDragAction = VclToGdk(eDNDConstants);
+ drag_source_set(aGtkTargets, m_eDragAction);
+
+ for (auto &a : aGtkTargets)
+ g_free(a.target);
+
+ m_xDragSource->set_datatransfer(xTrans, xListener);
+ }
+
void localizeDecimalSeparator()
{
// tdf#128867 if localize decimal separator is active we will always
@@ -1903,9 +1939,13 @@ private:
bool m_bDraggedOver;
sal_uInt16 m_nLastMouseButton;
sal_uInt16 m_nLastMouseClicks;
+ int m_nPressedButton;
+ int m_nPressStartX;
+ int m_nPressStartY;
ImplSVEvent* m_pFocusInEvent;
ImplSVEvent* m_pFocusOutEvent;
GtkCssProvider* m_pBgCssProvider;
+ GdkDragAction m_eDragAction;
gulong m_nFocusInSignalId;
gulong m_nMnemonicActivateSignalId;
gulong m_nFocusOutSignalId;
@@ -1921,9 +1961,15 @@ private:
gulong m_nDragDropSignalId;
gulong m_nDragDropReceivedSignalId;
gulong m_nDragLeaveSignalId;
+ gulong m_nDragBeginSignalId;
+ gulong m_nDragEndSignalId;
+ gulong m_nDragFailedSignalId;
+ gulong m_nDragDataDeleteignalId;
+ gulong m_nDragGetSignalId;
rtl::Reference<GtkDropTarget> m_xDropTarget;
rtl::Reference<GtkDragSource> m_xDragSource;
+ std::vector<AtkRelation*> m_aExtraAtkRelations;
static void signalSizeAllocate(GtkWidget*, GdkRectangle* allocation, gpointer widget)
{
@@ -1959,6 +2005,8 @@ private:
bool signal_button(GdkEventButton* pEvent)
{
+ m_nPressedButton = -1;
+
Point aPos(pEvent->x, pEvent->y);
if (SwapForRTL())
aPos.setX(gtk_widget_get_allocated_width(m_pWidget) - 1 - aPos.X());
@@ -2021,6 +2069,14 @@ private:
return false;
}
+ /* Save press to possibly begin a drag */
+ if (pEvent->type != GDK_BUTTON_RELEASE)
+ {
+ m_nPressedButton = pEvent->button;
+ m_nPressStartX = pEvent->x;
+ m_nPressStartY = pEvent->y;
+ }
+
sal_uInt32 nModCode = GtkSalFrame::GetMouseModCode(pEvent->state);
sal_uInt16 nCode = m_nLastMouseButton | (nModCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2));
MouseEvent aMEvt(aPos, m_nLastMouseClicks, ImplGetMouseButtonMode(m_nLastMouseButton, nModCode), nCode, nCode);
@@ -2046,6 +2102,19 @@ private:
bool signal_motion(const GdkEventMotion* pEvent)
{
+ GtkTargetList* pDragData = (m_eDragAction != 0 && m_nPressedButton != -1 && m_xDragSource.is()) ? gtk_drag_source_get_target_list(m_pWidget) : nullptr;
+ if (pDragData && gtk_drag_check_threshold(m_pWidget, m_nPressStartX, m_nPressStartY, pEvent->x, pEvent->y) && !do_signal_drag_begin())
+ {
+ gtk_drag_begin_with_coordinates(m_pWidget,
+ pDragData,
+ m_eDragAction,
+ m_nPressedButton,
+ const_cast<GdkEvent*>(reinterpret_cast<const GdkEvent*>(pEvent)),
+ m_nPressStartX, m_nPressStartY);
+ m_nPressedButton = -1;
+ return false;
+ }
+
if (!m_aMouseMotionHdl.IsSet())
return false;
@@ -2127,6 +2196,80 @@ private:
}
}
+ static void signalDragBegin(GtkWidget*, GdkDragContext* context, gpointer widget)
+ {
+ GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(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);
+ m_nDragBeginSignalId = g_signal_connect(m_pWidget, "drag-begin", G_CALLBACK(signalDragBegin), this);
+ m_nDragEndSignalId = g_signal_connect(m_pWidget, "drag-end", G_CALLBACK(signalDragEnd), this);
+ }
+ }
+
+ virtual bool do_signal_drag_begin()
+ {
+ return false;
+ }
+
+ void signal_drag_begin(GdkDragContext* context)
+ {
+ if (do_signal_drag_begin())
+ {
+ gtk_drag_cancel(context);
+ return;
+ }
+ if (!m_xDragSource)
+ return;
+ m_xDragSource->setActiveDragSource();
+ }
+
+ virtual void do_signal_drag_end()
+ {
+ }
+
+ static void signalDragEnd(GtkWidget* /*widget*/, GdkDragContext* context, gpointer widget)
+ {
+ GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget);
+ pThis->do_signal_drag_end();
+ if (pThis->m_xDragSource.is())
+ pThis->m_xDragSource->dragEnd(context);
+ }
+
+ static gboolean signalDragFailed(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkDragResult /*result*/, gpointer widget)
+ {
+ GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget);
+ pThis->m_xDragSource->dragFailed();
+ return false;
+ }
+
+ static void signalDragDelete(GtkWidget* /*widget*/, GdkDragContext* /*context*/, gpointer widget)
+ {
+ GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget);
+ pThis->m_xDragSource->dragDelete();
+ }
+
+ static void signalDragDataGet(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkSelectionData *data, guint info,
+ guint /*time*/, gpointer widget)
+ {
+ GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget);
+ pThis->m_xDragSource->dragDataGet(data, info);
+ }
+
+ virtual void drag_source_set(const std::vector<GtkTargetEntry>& rGtkTargets, GdkDragAction eDragAction)
+ {
+ gtk_drag_source_set(m_pWidget, GDK_BUTTON1_MASK, rGtkTargets.data(), rGtkTargets.size(), eDragAction);
+ }
+
void set_background(const OUString* pColor)
{
if (!pColor && !m_pBgCssProvider)
@@ -2157,9 +2300,13 @@ public:
, m_bDraggedOver(false)
, m_nLastMouseButton(0)
, m_nLastMouseClicks(0)
+ , m_nPressedButton(-1)
+ , m_nPressStartX(-1)
+ , m_nPressStartY(-1)
, m_pFocusInEvent(nullptr)
, m_pFocusOutEvent(nullptr)
, m_pBgCssProvider(nullptr)
+ , m_eDragAction(GdkDragAction(0))
, m_nFocusInSignalId(0)
, m_nMnemonicActivateSignalId(0)
, m_nFocusOutSignalId(0)
@@ -2175,6 +2322,11 @@ public:
, m_nDragDropSignalId(0)
, m_nDragDropReceivedSignalId(0)
, m_nDragLeaveSignalId(0)
+ , m_nDragBeginSignalId(0)
+ , m_nDragEndSignalId(0)
+ , m_nDragFailedSignalId(0)
+ , m_nDragDataDeleteignalId(0)
+ , m_nDragGetSignalId(0)
{
if (!bTakeOwnership)
g_object_ref(m_pWidget);
@@ -2701,6 +2853,16 @@ public:
g_signal_handler_disconnect(m_pWidget, m_nDragDropReceivedSignalId);
if (m_nDragLeaveSignalId)
g_signal_handler_disconnect(m_pWidget, m_nDragLeaveSignalId);
+ if (m_nDragEndSignalId)
+ g_signal_handler_disconnect(m_pWidget, m_nDragEndSignalId);
+ if (m_nDragBeginSignalId)
+ g_signal_handler_disconnect(m_pWidget, m_nDragBeginSignalId);
+ if (m_nDragFailedSignalId)
+ g_signal_handler_disconnect(m_pWidget, m_nDragFailedSignalId);
+ if (m_nDragDataDeleteignalId)
+ g_signal_handler_disconnect(m_pWidget, m_nDragDataDeleteignalId);
+ if (m_nDragGetSignalId)
+ g_signal_handler_disconnect(m_pWidget, m_nDragGetSignalId);
if (m_nKeyPressSignalId)
g_signal_handler_disconnect(m_pWidget, m_nKeyPressSignalId);
if (m_nKeyReleaseSignalId)
More information about the Libreoffice-commits
mailing list