[Libreoffice-commits] core.git: vcl/inc vcl/unx
Caolán McNamara (via logerrit)
logerrit at kemper.freedesktop.org
Thu Jun 24 19:39:27 UTC 2021
vcl/inc/unx/gtk/gtkframe.hxx | 6
vcl/inc/unx/gtk/gtkinst.hxx | 18 +-
vcl/unx/gtk3/gtkframe.cxx | 330 ++++++++++++++++++++++++++++++++++++++++---
vcl/unx/gtk3/gtkinst.cxx | 9 -
4 files changed, 331 insertions(+), 32 deletions(-)
New commits:
commit 8c276412c9cd8e12d88f4349f5fba19651161886
Author: Caolán McNamara <caolanm at redhat.com>
AuthorDate: Mon Jun 21 20:50:06 2021 +0100
Commit: Caolán McNamara <caolanm at redhat.com>
CommitDate: Thu Jun 24 21:38:33 2021 +0200
gtk4: get dnd drop into LibreOffice from another app working
Change-Id: I9519af009b479e51a3da556f26f3950c4930d618
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117611
Tested-by: Caolán McNamara <caolanm at redhat.com>
Reviewed-by: Caolán McNamara <caolanm at redhat.com>
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 248b841dc07e..7d612f077d3f 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -260,7 +260,11 @@ class GtkSalFrame final : public SalFrame
static gboolean signalTooltipQuery(GtkWidget*, gint x, gint y,
gboolean keyboard_mode, GtkTooltip *tooltip,
gpointer frame);
-#if !GTK_CHECK_VERSION(4, 0, 0)
+#if GTK_CHECK_VERSION(4, 0, 0)
+ static GdkDragAction signalDragMotion(GtkDropTargetAsync *dest, GdkDrop *drop, double x, double y, gpointer frame);
+ static void signalDragLeave(GtkDropTargetAsync *dest, GdkDrop *drop, gpointer frame);
+ static gboolean signalDragDrop(GtkDropTargetAsync* context, GdkDrop* drop, double x, double y, gpointer frame);
+#else
static gboolean signalDragMotion(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
guint time, gpointer frame);
static gboolean signalDragDrop(GtkWidget* widget, GdkDragContext *context, gint x, gint y,
diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
index e13524d8c54e..141a2a209ab0 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -64,8 +64,11 @@ struct text_transfer_result
struct read_transfer_result
{
- css::uno::Sequence<sal_Int8> aSeq;
+ enum { BlockSize = 8192 };
+ size_t nRead = 0;
bool bDone = false;
+
+ std::vector<sal_Int8> aVector;
};
#endif
@@ -131,9 +134,7 @@ class GtkInstDropTarget final : public cppu::WeakComponentImplHelper<css::datatr
GtkSalFrame* m_pFrame;
GtkDnDTransferable* m_pFormatConversionRequest;
bool m_bActive;
-#if !GTK_CHECK_VERSION(4, 0, 0)
bool m_bInDrag;
-#endif
sal_Int8 m_nDefaultActions;
std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> m_aListeners;
public:
@@ -169,10 +170,17 @@ public:
}
#if !GTK_CHECK_VERSION(4, 0, 0)
- gboolean signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time);
gboolean signalDragMotion(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time);
+ gboolean signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time);
+#else
+ GdkDragAction signalDragMotion(GtkWidget *pWidget, GtkDropTargetAsync *context, GdkDrop *drop, double x, double y);
+ gboolean signalDragDrop(GtkDropTargetAsync *context, GdkDrop *drop, double x, double y);
+#endif
+
+ void signalDragLeave(GtkWidget* pWidget);
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
void signalDragDropReceived(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint ttype, guint time);
- void signalDragLeave(GtkWidget* pWidget, GdkDragContext* context, guint time);
#endif
};
diff --git a/vcl/unx/gtk3/gtkframe.cxx b/vcl/unx/gtk3/gtkframe.cxx
index b32eb14ad5e7..aab7f40fc603 100644
--- a/vcl/unx/gtk3/gtkframe.cxx
+++ b/vcl/unx/gtk3/gtkframe.cxx
@@ -975,17 +975,26 @@ void GtkSalFrame::InitCommon()
GtkEventController* pScrollController = gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES);
g_signal_connect(pScrollController, "scroll", G_CALLBACK(signalScroll), this);
gtk_widget_add_controller(pEventWidget, pScrollController);
-
#endif
-#if !GTK_CHECK_VERSION(4,0,0)
+
//Drop Target Stuff
+#if GTK_CHECK_VERSION(4,0,0)
+ GtkDropTargetAsync* pDropTarget = gtk_drop_target_async_new(nullptr, GdkDragAction(GDK_ACTION_ALL));
+ g_signal_connect(G_OBJECT(pDropTarget), "drag-enter", G_CALLBACK(signalDragMotion), this);
+ g_signal_connect(G_OBJECT(pDropTarget), "drag-motion", G_CALLBACK(signalDragMotion), this);
+ g_signal_connect(G_OBJECT(pDropTarget), "drag-leave", G_CALLBACK(signalDragLeave), this);
+ g_signal_connect(G_OBJECT(pDropTarget), "drop", G_CALLBACK(signalDragDrop), this);
+ gtk_widget_add_controller(pEventWidget, GTK_EVENT_CONTROLLER(pDropTarget));
+#else
gtk_drag_dest_set(GTK_WIDGET(pEventWidget), GtkDestDefaults(0), nullptr, 0, GdkDragAction(0));
gtk_drag_dest_set_track_motion(GTK_WIDGET(pEventWidget), true);
m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-motion", G_CALLBACK(signalDragMotion), this ));
m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-drop", G_CALLBACK(signalDragDrop), this ));
m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-data-received", G_CALLBACK(signalDragDropReceived), this ));
m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-leave", G_CALLBACK(signalDragLeave), this ));
+#endif
+#if !GTK_CHECK_VERSION(4,0,0)
//Drag Source Stuff
m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-end", G_CALLBACK(signalDragEnd), this ));
m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-failed", G_CALLBACK(signalDragFailed), this ));
@@ -4163,9 +4172,9 @@ gboolean GtkSalFrame::signalWindowState( GtkWidget*, GdkEvent* pEvent, gpointer
}
#endif
-#if !GTK_CHECK_VERSION(4, 0, 0)
namespace
{
+#if !GTK_CHECK_VERSION(4,0,0)
GdkDragAction VclToGdk(sal_Int8 dragOperation)
{
GdkDragAction eRet(static_cast<GdkDragAction>(0));
@@ -4177,6 +4186,7 @@ namespace
eRet = static_cast<GdkDragAction>(eRet | GDK_ACTION_LINK);
return eRet;
}
+#endif
sal_Int8 GdkToVcl(GdkDragAction dragOperation)
{
@@ -4207,39 +4217,124 @@ namespace
return eAct;
}
}
-#endif
static bool g_DropSuccessSet = false;
static bool g_DropSuccess = false;
-#if !GTK_CHECK_VERSION(4, 0, 0)
namespace {
+#if GTK_CHECK_VERSION(4, 0, 0)
+
+void read_async_completed(GObject* source, GAsyncResult* res, gpointer user_data)
+{
+ GInputStream* stream = G_INPUT_STREAM(source);
+ read_transfer_result* pRes = static_cast<read_transfer_result*>(user_data);
+
+ gsize bytes_read = g_input_stream_read_finish(stream, res, nullptr);
+
+ bool bFinished = bytes_read == 0;
+
+ if (bFinished)
+ {
+ pRes->aVector.resize(pRes->nRead);
+ pRes->bDone = true;
+ g_main_context_wakeup(nullptr);
+ return;
+ }
+
+ pRes->nRead += bytes_read;
+
+ pRes->aVector.resize(pRes->nRead + read_transfer_result::BlockSize);
+
+ g_input_stream_read_async(stream,
+ pRes->aVector.data() + pRes->nRead,
+ read_transfer_result::BlockSize,
+ G_PRIORITY_DEFAULT,
+ nullptr,
+ read_async_completed,
+ user_data);
+}
+
+void read_drop_async_completed(GObject* source, GAsyncResult* res, gpointer user_data)
+{
+ GdkDrop* drop = GDK_DROP(source);
+ read_transfer_result* pRes = static_cast<read_transfer_result*>(user_data);
+
+ GInputStream* pResult = gdk_drop_read_finish(drop, res, nullptr, nullptr);
+
+ if (!pResult)
+ {
+ pRes->bDone = true;
+ g_main_context_wakeup(nullptr);
+ return;
+ }
+
+ pRes->aVector.resize(read_transfer_result::BlockSize);
+
+ g_input_stream_read_async(pResult,
+ pRes->aVector.data(),
+ pRes->aVector.size(),
+ G_PRIORITY_DEFAULT,
+ nullptr,
+ read_async_completed,
+ user_data);
+}
+#endif
+
class GtkDropTargetDropContext : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDropContext>
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
GdkDragContext *m_pContext;
guint m_nTime;
+#else
+ GtkDropTargetAsync* m_pContext;
+ GdkDrop* m_pDrop;
+#endif
public:
- GtkDropTargetDropContext(GdkDragContext *pContext, guint nTime)
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ GtkDropTargetDropContext(GdkDragContext* pContext, guint nTime)
: m_pContext(pContext)
, m_nTime(nTime)
+#else
+ GtkDropTargetDropContext(GtkDropTargetAsync* pContext, GdkDrop* pDrop)
+ : m_pContext(pContext)
+ , m_pDrop(pDrop)
+#endif
{
}
// XDropTargetDropContext
virtual void SAL_CALL acceptDrop(sal_Int8 dragOperation) override
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
gdk_drag_status(m_pContext, getPreferredDragAction(dragOperation), m_nTime);
+#else
+ GdkDragAction eDragAction = getPreferredDragAction(dragOperation);
+ gdk_drop_status(m_pDrop,
+ static_cast<GdkDragAction>(eDragAction | gdk_drop_get_actions(m_pDrop)),
+ eDragAction);
+#endif
}
virtual void SAL_CALL rejectDrop() override
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
gdk_drag_status(m_pContext, static_cast<GdkDragAction>(0), m_nTime);
+#else
+ gtk_drop_target_async_reject_drop(m_pContext, m_pDrop);
+#endif
}
virtual void SAL_CALL dropComplete(sal_Bool bSuccess) override
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
gtk_drag_finish(m_pContext, bSuccess, false, m_nTime);
+#else
+ // should we do something better here
+ gdk_drop_finish(m_pDrop, bSuccess
+ ? gdk_drop_get_actions(m_pDrop)
+ : static_cast<GdkDragAction>(0));
+#endif
if (GtkInstDragSource::g_ActiveDragSource)
{
g_DropSuccessSet = true;
@@ -4249,25 +4344,36 @@ public:
};
}
-#endif
-#if !GTK_CHECK_VERSION(4, 0, 0)
class GtkDnDTransferable : public GtkTransferable
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
GdkDragContext *m_pContext;
guint m_nTime;
GtkWidget *m_pWidget;
GtkInstDropTarget* m_pDropTarget;
+#else
+ GdkDrop* m_pDrop;
+#endif
+#if !GTK_CHECK_VERSION(4, 0, 0)
GMainLoop *m_pLoop;
GtkSelectionData *m_pData;
+#endif
public:
+#if !GTK_CHECK_VERSION(4, 0, 0)
GtkDnDTransferable(GdkDragContext *pContext, guint nTime, GtkWidget *pWidget, GtkInstDropTarget *pDropTarget)
: m_pContext(pContext)
, m_nTime(nTime)
, m_pWidget(pWidget)
, m_pDropTarget(pDropTarget)
+#else
+ GtkDnDTransferable(GdkDrop *pDrop)
+ : m_pDrop(pDrop)
+#endif
+#if !GTK_CHECK_VERSION(4, 0, 0)
, m_pLoop(nullptr)
, m_pData(nullptr)
+#endif
{
}
@@ -4281,6 +4387,9 @@ public:
if (it == m_aMimeTypeToGtkType.end())
return css::uno::Any();
+ css::uno::Any aRet;
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
/* like gtk_clipboard_wait_for_contents run a sub loop
* waiting for drag-data-received triggered from
* gtk_drag_get_data
@@ -4299,8 +4408,6 @@ public:
m_pDropTarget->SetFormatConversionRequest(nullptr);
}
- css::uno::Any aRet;
-
if (aFlavor.MimeType == "text/plain;charset=utf-8")
{
OUString aStr;
@@ -4324,31 +4431,107 @@ public:
}
gtk_selection_data_free(m_pData);
+#else
+ SalInstance* pInstance = GetSalData()->m_pInstance;
+ read_transfer_result aRes;
+ const char *mime_types[] = { it->second.getStr(), nullptr };
+ gdk_drop_read_async(m_pDrop,
+ mime_types,
+ G_PRIORITY_DEFAULT,
+ nullptr,
+ read_drop_async_completed,
+ &aRes);
+
+ while (!aRes.bDone)
+ pInstance->DoYield(true, false);
+
+ if (aFlavor.MimeType == "text/plain;charset=utf-8")
+ {
+ const char* pStr = reinterpret_cast<const char*>(aRes.aVector.data());
+ OUString aStr(pStr, aRes.aVector.size(), RTL_TEXTENCODING_UTF8);
+ aRet <<= aStr.replaceAll("\r\n", "\n");
+ }
+ else
+ {
+ auto aSeq = css::uno::Sequence<sal_Int8>(aRes.aVector.data(), aRes.aVector.size());
+ aRet <<= aSeq;
+ }
+#endif
return aRet;
}
virtual std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector() override
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
std::vector<GdkAtom> targets;
for (GList* l = gdk_drag_context_list_targets(m_pContext); l; l = l->next)
targets.push_back(static_cast<GdkAtom>(l->data));
return GtkTransferable::getTransferDataFlavorsAsVector(targets.data(), targets.size());
+#else
+ GdkContentFormats* pFormats = gdk_drop_get_formats(m_pDrop);
+ gsize n_targets;
+ const char * const *targets = gdk_content_formats_get_mime_types(pFormats, &n_targets);
+ return GtkTransferable::getTransferDataFlavorsAsVector(targets, n_targets);
+#endif
}
+#if !GTK_CHECK_VERSION(4, 0, 0)
void LoopEnd(GtkSelectionData *pData)
{
m_pData = pData;
g_main_loop_quit(m_pLoop);
}
-};
#endif
+};
// For LibreOffice internal D&D we provide the Transferable without Gtk
// intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this
GtkInstDragSource* GtkInstDragSource::g_ActiveDragSource;
-#if !GTK_CHECK_VERSION(4, 0, 0)
+#if GTK_CHECK_VERSION(4, 0, 0)
+
+struct GrabBag
+{
+ GtkInstDropTarget* m_pDropTarget;
+ GtkDropTargetAsync* m_pContext;
+ GdkDrop* m_pDrop;
+ double m_nX;
+ double m_nY;
+
+ GrabBag(GtkInstDropTarget* pDropTarget,
+ GtkDropTargetAsync* pContext,
+ GdkDrop* pDrop,
+ double nX,
+ double nY)
+ : m_pDropTarget(pDropTarget)
+ , m_pContext(pContext)
+ , m_pDrop(pDrop)
+ , m_nX(nX)
+ , m_nY(nY)
+ {
+ }
+};
+
+static gboolean lcl_deferred_dragDrop(gpointer user_data)
+{
+ GrabBag* pGrabBag = static_cast<GrabBag*>(user_data);
+ pGrabBag->m_pDropTarget->signalDragDrop(pGrabBag->m_pContext, pGrabBag->m_pDrop, pGrabBag->m_nX, pGrabBag->m_nY);
+ g_object_unref(pGrabBag->m_pDrop);
+ return false;
+}
+
+gboolean GtkSalFrame::signalDragDrop(GtkDropTargetAsync* context, GdkDrop* drop, double x, double y, gpointer frame)
+{
+ GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+ if (!pThis->m_pDropTarget)
+ return false;
+ g_object_ref(drop);
+ g_idle_add(lcl_deferred_dragDrop, new GrabBag(pThis->m_pDropTarget, context, drop, x, y));
+// return pThis->m_pDropTarget->signalDragDrop(context, drop, x, y);
+ return true;
+}
+#else
gboolean GtkSalFrame::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time, gpointer frame)
{
GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
@@ -4356,22 +4539,39 @@ gboolean GtkSalFrame::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context
return false;
return pThis->m_pDropTarget->signalDragDrop(pWidget, context, x, y, time);
}
+#endif
+#if !GTK_CHECK_VERSION(4, 0, 0)
gboolean GtkInstDropTarget::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time)
+#else
+gboolean GtkInstDropTarget::signalDragDrop(GtkDropTargetAsync* context, GdkDrop* drop, double x, double y)
+#endif
{
// remove the deferred dragExit, as we'll do a drop
#ifndef NDEBUG
bool res =
#endif
g_idle_remove_by_data(this);
+#if !GTK_CHECK_VERSION(4, 0, 0)
assert(res);
+#else
+ (void)res;
+#endif
css::datatransfer::dnd::DropTargetDropEvent aEvent;
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(this);
+#if !GTK_CHECK_VERSION(4, 0, 0)
aEvent.Context = new GtkDropTargetDropContext(context, time);
+#else
+ aEvent.Context = new GtkDropTargetDropContext(context, drop);
+#endif
aEvent.LocationX = x;
aEvent.LocationY = y;
+#if !GTK_CHECK_VERSION(4, 0, 0)
aEvent.DropAction = GdkToVcl(gdk_drag_context_get_selected_action(context));
+#else
+ aEvent.DropAction = GdkToVcl(getPreferredDragAction(GdkToVcl(gtk_drop_target_async_get_actions(context))));
+#endif
// ACTION_DEFAULT is documented as...
// 'This means the user did not press any key during the Drag and Drop operation
// and the action that was combined with ACTION_DEFAULT is the system default action'
@@ -4380,53 +4580,81 @@ gboolean GtkInstDropTarget::signalDragDrop(GtkWidget* pWidget, GdkDragContext* c
// there is a deprecated 'GDK_ACTION_DEFAULT Means nothing, and should not be used'
// possible equivalent in gtk.
// So (tdf#109227) set ACTION_DEFAULT if no modifier key is held down
+#if !GTK_CHECK_VERSION(4,0,0)
+ aEvent.SourceActions = GdkToVcl(gdk_drag_context_get_actions(context));
GdkModifierType mask;
gdk_window_get_pointer(widget_get_surface(pWidget), nullptr, nullptr, &mask);
+#else
+ aEvent.SourceActions = GdkToVcl(gtk_drop_target_async_get_actions(context));
+ GdkModifierType mask = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(context));
+#endif
if (!(mask & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)))
aEvent.DropAction |= css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT;
- aEvent.SourceActions = GdkToVcl(gdk_drag_context_get_actions(context));
+
css::uno::Reference<css::datatransfer::XTransferable> xTransferable;
// For LibreOffice internal D&D we provide the Transferable without Gtk
// intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this
if (GtkInstDragSource::g_ActiveDragSource)
xTransferable = GtkInstDragSource::g_ActiveDragSource->GetTransferrable();
else
+ {
+#if GTK_CHECK_VERSION(4,0,0)
+ xTransferable = new GtkDnDTransferable(drop);
+#else
xTransferable = new GtkDnDTransferable(context, time, pWidget, this);
+#endif
+ }
aEvent.Transferable = xTransferable;
fire_drop(aEvent);
return true;
}
-#endif
-#if !GTK_CHECK_VERSION(4, 0, 0)
namespace {
class GtkDropTargetDragContext : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDragContext>
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
GdkDragContext *m_pContext;
guint m_nTime;
+#else
+ GtkDropTargetAsync* m_pContext;
+ GdkDrop* m_pDrop;
+#endif
public:
+#if !GTK_CHECK_VERSION(4, 0, 0)
GtkDropTargetDragContext(GdkDragContext *pContext, guint nTime)
: m_pContext(pContext)
, m_nTime(nTime)
+#else
+ GtkDropTargetDragContext(GtkDropTargetAsync* pContext, GdkDrop* pDrop)
+ : m_pContext(pContext)
+ , m_pDrop(pDrop)
+#endif
{
}
virtual void SAL_CALL acceptDrag(sal_Int8 dragOperation) override
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
gdk_drag_status(m_pContext, getPreferredDragAction(dragOperation), m_nTime);
+#else
+ gdk_drop_status(m_pDrop, gdk_drop_get_actions(m_pDrop), getPreferredDragAction(dragOperation));
+#endif
}
virtual void SAL_CALL rejectDrag() override
{
+#if !GTK_CHECK_VERSION(4, 0, 0)
gdk_drag_status(m_pContext, static_cast<GdkDragAction>(0), m_nTime);
+#else
+ gtk_drop_target_async_reject_drop(m_pContext, m_pDrop);
+#endif
}
};
}
-#endif
#if !GTK_CHECK_VERSION(4, 0, 0)
void GtkSalFrame::signalDragDropReceived(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint ttype, guint time, gpointer frame)
@@ -4451,7 +4679,18 @@ void GtkInstDropTarget::signalDragDropReceived(GtkWidget* /*pWidget*/, GdkDragCo
m_pFormatConversionRequest->LoopEnd(gtk_selection_data_copy(data));
}
+#endif
+#if GTK_CHECK_VERSION(4,0,0)
+GdkDragAction GtkSalFrame::signalDragMotion(GtkDropTargetAsync *dest, GdkDrop *drop, double x, double y, gpointer frame)
+{
+ GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+ if (!pThis->m_pDropTarget)
+ return GdkDragAction(0);
+ GtkWidget *pEventWidget = pThis->getMouseEventWidget();
+ return pThis->m_pDropTarget->signalDragMotion(pEventWidget, dest, drop, x, y);
+}
+#else
gboolean GtkSalFrame::signalDragMotion(GtkWidget *pWidget, GdkDragContext *context, gint x, gint y, guint time, gpointer frame)
{
GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
@@ -4459,22 +4698,41 @@ gboolean GtkSalFrame::signalDragMotion(GtkWidget *pWidget, GdkDragContext *conte
return false;
return pThis->m_pDropTarget->signalDragMotion(pWidget, context, x, y, time);
}
+#endif
-
+#if !GTK_CHECK_VERSION(4,0,0)
gboolean GtkInstDropTarget::signalDragMotion(GtkWidget *pWidget, GdkDragContext *context, gint x, gint y, guint time)
+#else
+GdkDragAction GtkInstDropTarget::signalDragMotion(GtkWidget *pWidget, GtkDropTargetAsync *context, GdkDrop *drop, double x, double y)
+#endif
{
if (!m_bInDrag)
+ {
+#if !GTK_CHECK_VERSION(4,0,0)
gtk_drag_highlight(pWidget);
+#else
+ gtk_widget_set_state_flags(pWidget, GTK_STATE_FLAG_DROP_ACTIVE, false);
+#endif
+ }
css::datatransfer::dnd::DropTargetDragEnterEvent aEvent;
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(this);
+#if !GTK_CHECK_VERSION(4,0,0)
rtl::Reference<GtkDropTargetDragContext> pContext = new GtkDropTargetDragContext(context, time);
+#else
+ rtl::Reference<GtkDropTargetDragContext> pContext = new GtkDropTargetDragContext(context, drop);
+#endif
//preliminary accept the Drag and select the preferred action, the fire_* will
//inform the original caller of our choice and the callsite can decide
//to overrule this choice. i.e. typically here we default to ACTION_MOVE
+#if !GTK_CHECK_VERSION(4,0,0)
sal_Int8 nSourceActions = GdkToVcl(gdk_drag_context_get_actions(context));
GdkModifierType mask;
gdk_window_get_pointer(widget_get_surface(pWidget), nullptr, nullptr, &mask);
+#else
+ sal_Int8 nSourceActions = GdkToVcl(gtk_drop_target_async_get_actions(context));
+ GdkModifierType mask = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(context));
+#endif
// tdf#124411 default to move if drag originates within LO itself, default
// to copy if it comes from outside, this is similar to srcAndDestEqual
@@ -4500,7 +4758,9 @@ gboolean GtkInstDropTarget::signalDragMotion(GtkWidget *pWidget, GdkDragContext
else
eAction = getPreferredDragAction(nNewDropAction);
+#if !GTK_CHECK_VERSION(4,0,0)
gdk_drag_status(context, eAction, time);
+#endif
aEvent.Context = pContext;
aEvent.LocationX = x;
aEvent.LocationY = y;
@@ -4519,7 +4779,13 @@ gboolean GtkInstDropTarget::signalDragMotion(GtkWidget *pWidget, GdkDragContext
if (GtkInstDragSource::g_ActiveDragSource)
xTransferable = GtkInstDragSource::g_ActiveDragSource->GetTransferrable();
else
+ {
+#if !GTK_CHECK_VERSION(4,0,0)
xTransferable = new GtkDnDTransferable(context, time, pWidget, this);
+#else
+ xTransferable = new GtkDnDTransferable(drop);
+#endif
+ }
css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = xTransferable->getTransferDataFlavors();
aEvent.SupportedDataFlavors = aFormats;
fire_dragEnter(aEvent);
@@ -4530,16 +4796,31 @@ gboolean GtkInstDropTarget::signalDragMotion(GtkWidget *pWidget, GdkDragContext
fire_dragOver(aEvent);
}
+#if !GTK_CHECK_VERSION(4,0,0)
return true;
+#else
+ return eAction;
+#endif
}
-void GtkSalFrame::signalDragLeave(GtkWidget *pWidget, GdkDragContext *context, guint time, gpointer frame)
+#if GTK_CHECK_VERSION(4,0,0)
+void GtkSalFrame::signalDragLeave(GtkDropTargetAsync* /*dest*/, GdkDrop* /*drop*/, gpointer frame)
+{
+ GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+ if (!pThis->m_pDropTarget)
+ return;
+ GtkWidget *pEventWidget = pThis->getMouseEventWidget();
+ pThis->m_pDropTarget->signalDragLeave(pEventWidget);
+}
+#else
+void GtkSalFrame::signalDragLeave(GtkWidget *pWidget, GdkDragContext* /*context*/, guint /*time*/, gpointer frame)
{
GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
if (!pThis->m_pDropTarget)
return;
- pThis->m_pDropTarget->signalDragLeave(pWidget, context, time);
+ pThis->m_pDropTarget->signalDragLeave(pWidget);
}
+#endif
static gboolean lcl_deferred_dragExit(gpointer user_data)
{
@@ -4547,20 +4828,25 @@ static gboolean lcl_deferred_dragExit(gpointer user_data)
css::datatransfer::dnd::DropTargetEvent aEvent;
aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pThis);
pThis->fire_dragExit(aEvent);
- return FALSE;
+ return false;
}
-void GtkInstDropTarget::signalDragLeave(GtkWidget* pWidget, GdkDragContext* /*context*/, guint /*time*/)
+void GtkInstDropTarget::signalDragLeave(GtkWidget* pWidget)
{
m_bInDrag = false;
+
+#if !GTK_CHECK_VERSION(4,0,0)
gtk_drag_unhighlight(pWidget);
+#else
+ gtk_widget_unset_state_flags(pWidget, GTK_STATE_FLAG_DROP_ACTIVE);
+#endif
+
// defer fire_dragExit, since gtk also sends a drag-leave before the drop, while
// LO expect to either handle the drop or the exit... at least in Writer.
// but since we don't know there will be a drop following the leave, defer the
// exit handling to an idle.
g_idle_add(lcl_deferred_dragExit, this);
}
-#endif
void GtkSalFrame::signalDestroy( GtkWidget* pObj, gpointer frame )
{
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 4d02d6da480e..92df2f48d516 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -716,7 +716,7 @@ void read_async_completed(GObject* source, GAsyncResult* res, gpointer data)
aVector.resize(aVector.size() + nBlockSize);
}
- pRes->aSeq = Sequence<sal_Int8>(aVector.data(), total);
+ pRes->aVector.resize(total);
g_object_unref(pResult);
}
@@ -781,7 +781,8 @@ public:
&aRes);
while (!aRes.bDone)
pInstance->DoYield(true, false);
- aRet <<= aRes.aSeq;
+ Sequence<sal_Int8> aSeq(aRes.aVector.data(), aRes.aVector.size());
+ aRet <<= aSeq;
#else
GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard,
it->second);
@@ -3057,10 +3058,10 @@ private:
}
#if !GTK_CHECK_VERSION(4, 0, 0)
- static void signalDragLeave(GtkWidget *pWidget, GdkDragContext *context, guint time, gpointer widget)
+ static void signalDragLeave(GtkWidget *pWidget, GdkDragContext* /*context*/, guint /*time*/, gpointer widget)
{
GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget);
- pThis->m_xDropTarget->signalDragLeave(pWidget, context, time);
+ pThis->m_xDropTarget->signalDragLeave(pWidget);
if (pThis->m_bDraggedOver)
{
pThis->m_bDraggedOver = false;
More information about the Libreoffice-commits
mailing list