diff options
author | Caolán McNamara <caolanm@redhat.com> | 2016-01-27 10:16:39 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2016-01-27 13:15:00 +0000 |
commit | a5b4f6e456bfb735385e8d3d6945ea8f3be1ba94 (patch) | |
tree | af86e52f278beb9eeace70f24a6ef04acef7324b /vcl | |
parent | 626702aa39798715fd252ae8f484233cae8a829f (diff) |
Resolves: tdf#93054 gtk3: implement drag and drop
Change-Id: Ib644ea36b8a9e68e023e465ef159b9a4890e5d37
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/unx/gtk/gtkframe.hxx | 27 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkinst.hxx | 46 | ||||
-rw-r--r-- | vcl/source/window/mouse.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkframe.cxx | 178 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 161 |
5 files changed, 364 insertions, 49 deletions
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index 584a2ab96922..6c7058a6c784 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -40,6 +40,9 @@ #include "tools/link.hxx" #include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/datatransfer/dnd/XDragSource.hpp> +#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> #include <list> #include <vector> @@ -55,6 +58,7 @@ typedef ::Window GdkNativeWindow; #define gdk_set_sm_client_id(i) gdk_x11_set_sm_client_id(i) #define gdk_window_foreign_new_for_display(a,b) gdk_x11_window_foreign_new_for_display(a,b) class GtkDropTarget; +class GtkDragSource; class GtkDnDTransferable; #endif @@ -209,6 +213,7 @@ class GtkSalFrame : public SalFrame long m_nHeightRequest; cairo_region_t* m_pRegion; GtkDropTarget* m_pDropTarget; + GtkDragSource* m_pDragSource; bool m_bInDrag; GtkDnDTransferable* m_pFormatConversionRequest; #else @@ -249,6 +254,13 @@ class GtkSalFrame : public SalFrame static void signalDragDropReceived(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint ttype, guint time, gpointer frame); static void signalDragLeave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer frame); + + static gboolean signalDragFailed(GtkWidget *widget, GdkDragContext *context, GtkDragResult result, gpointer frame); + static void signalDragDelete(GtkWidget *widget, GdkDragContext *context, gpointer frame); + static void signalDragEnd(GtkWidget *widget, GdkDragContext *context, gpointer frame); + static void signalDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData *data, guint info, + guint time, gpointer frame); + #if GTK_CHECK_VERSION(3,14,0) static void gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame); static void gestureLongPress(GtkGestureLongPress* gesture, gpointer frame); @@ -385,11 +397,26 @@ public: m_pDropTarget = nullptr; } + void registerDragSource(GtkDragSource* pDragSource) + { + assert(!m_pDragSource); + m_pDragSource = pDragSource; + } + + void deregisterDragSource(GtkDragSource* pDragSource) + { + assert(m_pDragSource == pDragSource); (void)pDragSource; + m_pDragSource = nullptr; + } + void SetFormatConversionRequest(GtkDnDTransferable *pRequest) { m_pFormatConversionRequest = pRequest; } + void startDrag(gint nButton, gint nDragOriginX, gint nDragOriginY, + GdkDragAction sourceActions, GtkTargetList* pTargetList); + #endif virtual ~GtkSalFrame(); diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx index a649f620e223..93a041b7982a 100644 --- a/vcl/inc/unx/gtk/gtkinst.hxx +++ b/vcl/inc/unx/gtk/gtkinst.hxx @@ -24,6 +24,7 @@ #include <unx/gensys.h> #include <headless/svpinst.hxx> #include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/datatransfer/dnd/XDragSource.hpp> #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> @@ -56,6 +57,8 @@ struct VclToGtkHelper { std::vector<css::datatransfer::DataFlavor> aInfoToFlavor; std::vector<GtkTargetEntry> FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats); + void setSelectionData(const css::uno::Reference<css::datatransfer::XTransferable> &rTrans, + GtkSelectionData *selection_data, guint info); private: GtkTargetEntry makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor); }; @@ -123,6 +126,48 @@ public: void fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde); void fire_dragExit(const css::datatransfer::dnd::DropTargetEvent& dte); }; + +class GtkDragSource : public cppu::WeakComponentImplHelper<css::datatransfer::dnd::XDragSource, + css::lang::XInitialization, + css::lang::XServiceInfo> +{ + osl::Mutex m_aMutex; + GtkSalFrame* m_pFrame; + css::uno::Reference<css::datatransfer::dnd::XDragSourceListener> m_xListener; + css::uno::Reference<css::datatransfer::XTransferable> m_xTrans; + VclToGtkHelper m_aConversionHelper; +public: + GtkDragSource() : WeakComponentImplHelper( m_aMutex ) {} + virtual ~GtkDragSource(); + + // XDragSource + virtual sal_Bool SAL_CALL isDragImageSupported() throw(std::exception) override; + virtual sal_Int32 SAL_CALL getDefaultCursor(sal_Int8 dragAction) throw(std::exception) override; + virtual void SAL_CALL startDrag( + const css::datatransfer::dnd::DragGestureEvent& trigger, sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image, + const css::uno::Reference< css::datatransfer::XTransferable >& transferable, + const css::uno::Reference< css::datatransfer::dnd::XDragSourceListener >& listener) throw(std::exception) override; + + // XInitialization + virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any >& rArguments) + throw (css::uno::Exception, std::exception) override; + void deinitialize(); + + OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException, std::exception) override; + + sal_Bool SAL_CALL supportsService(OUString const & ServiceName) + throw (css::uno::RuntimeException, std::exception) override; + + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() + throw (css::uno::RuntimeException, std::exception) override; + + void dragFailed(); + void dragDelete(); + void dragEnd(GdkDragContext* context); + void dragDataGet(GtkSelectionData *data, guint info); +}; + #endif class GtkSalTimer; @@ -175,6 +220,7 @@ public: #if GTK_CHECK_VERSION(3,0,0) virtual css::uno::Reference< css::uno::XInterface > CreateClipboard( const css::uno::Sequence< css::uno::Any >& i_rArguments ) override; + virtual css::uno::Reference< css::uno::XInterface > CreateDragSource() override; virtual css::uno::Reference< css::uno::XInterface > CreateDropTarget() override; #endif diff --git a/vcl/source/window/mouse.cxx b/vcl/source/window/mouse.cxx index 3c9475950334..7adc5bbe7e23 100644 --- a/vcl/source/window/mouse.cxx +++ b/vcl/source/window/mouse.cxx @@ -751,6 +751,7 @@ Reference< css::datatransfer::dnd::XDragSource > Window::GetDragSource() aDropTargetSN = "com.sun.star.datatransfer.dnd.X11DropTarget"; aDragSourceAL[ 0 ] = makeAny( Application::GetDisplayConnection() ); + aDragSourceAL[ 1 ] = makeAny( (sal_Size)(pEnvData->aShellWindow) ); aDropTargetAL[ 0 ] = makeAny( Application::GetDisplayConnection() ); aDropTargetAL[ 1 ] = makeAny( (sal_Size)(pEnvData->aShellWindow) ); #endif diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx index b5677a1e2cc7..d98b3be28816 100644 --- a/vcl/unx/gtk3/gtk3gtkframe.cxx +++ b/vcl/unx/gtk3/gtk3gtkframe.cxx @@ -74,6 +74,7 @@ #include <com/sun/star/accessibility/XAccessibleStateSet.hpp> #include <com/sun/star/accessibility/AccessibleStateType.hpp> #include <com/sun/star/accessibility/XAccessibleEditableText.hpp> +#include <com/sun/star/awt/MouseButton.hpp> #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp> #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/frame/ModuleManager.hpp> @@ -790,6 +791,12 @@ GtkSalFrame::~GtkSalFrame() m_pDropTarget = nullptr; } + if (m_pDragSource) + { + m_pDragSource->deinitialize(); + m_pDragSource= nullptr; + } + InvalidateGraphics(); if( m_pParent ) @@ -991,12 +998,21 @@ void GtkSalFrame::InitCommon() m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-press-event", G_CALLBACK(signalButton), this )); m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "motion-notify-event", G_CALLBACK(signalMotion), this )); m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-release-event", G_CALLBACK(signalButton), this )); + + //Drop Target Stuff 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 )); + + //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 )); + m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-data-delete", G_CALLBACK(signalDragDelete), this )); + m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "drag-data-get", G_CALLBACK(signalDragDataGet), this )); + g_signal_connect( G_OBJECT(m_pFixedContainer), "draw", G_CALLBACK(signalDraw), this ); g_signal_connect( G_OBJECT(m_pFixedContainer), "size-allocate", G_CALLBACK(sizeAllocated), this ); #if GTK_CHECK_VERSION(3,14,0) @@ -1041,6 +1057,7 @@ void GtkSalFrame::InitCommon() m_nExtStyle = 0; m_pRegion = nullptr; m_pDropTarget = nullptr; + m_pDragSource = nullptr; m_bInDrag = false; m_pFormatConversionRequest = nullptr; m_ePointerStyle = static_cast<PointerStyle>(0xffff); @@ -3068,7 +3085,16 @@ public: // XDropTargetDropContext virtual void SAL_CALL acceptDrop(sal_Int8 dragOperation) throw(std::exception) override { - gdk_drag_status(m_pContext, VclToGdk(dragOperation), m_nTime); + GdkDragAction eAct(static_cast<GdkDragAction>(0)); + + if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_MOVE) + eAct = GDK_ACTION_MOVE; + else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_COPY) + eAct = GDK_ACTION_COPY; + else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_LINK) + eAct = GDK_ACTION_LINK; + + gdk_drag_status(m_pContext, eAct, m_nTime); } virtual void SAL_CALL rejectDrop() throw(std::exception) override @@ -3188,7 +3214,7 @@ gboolean GtkSalFrame::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context aEvent.Context = new GtkDropTargetDropContext(context, time); aEvent.LocationX = x; aEvent.LocationY = y; - aEvent.DropAction = GdkToVcl(gdk_drag_context_get_suggested_action(context)); + aEvent.DropAction = GdkToVcl(gdk_drag_context_get_selected_action(context)); aEvent.SourceActions = GdkToVcl(gdk_drag_context_get_actions(context)); css::uno::Reference<css::datatransfer::XTransferable> xTransferable(new GtkDnDTransferable(context, time, pWidget, pThis)); aEvent.Transferable = xTransferable; @@ -3211,7 +3237,16 @@ public: virtual void SAL_CALL acceptDrag(sal_Int8 dragOperation) throw(std::exception) override { - gdk_drag_status(m_pContext, VclToGdk(dragOperation), m_nTime); + GdkDragAction eAct(static_cast<GdkDragAction>(0)); + + if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_MOVE) + eAct = GDK_ACTION_MOVE; + else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_COPY) + eAct = GDK_ACTION_COPY; + else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_LINK) + eAct = GDK_ACTION_LINK; + + gdk_drag_status(m_pContext, eAct, m_nTime); } virtual void SAL_CALL rejectDrag() throw(std::exception) override @@ -3249,10 +3284,15 @@ gboolean GtkSalFrame::signalDragMotion(GtkWidget *widget, GdkDragContext *contex css::datatransfer::dnd::DropTargetDragEnterEvent aEvent; aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pThis->m_pDropTarget); - aEvent.Context = new GtkDropTargetDragContext(context, time); + 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 + //to overrule this choice. i.e. typically here we default to ACTION_MOVE + pContext->acceptDrag(GdkToVcl(gdk_drag_context_get_actions(context))); + aEvent.Context = pContext; aEvent.LocationX = x; aEvent.LocationY = y; - aEvent.DropAction = GdkToVcl(gdk_drag_context_get_suggested_action(context)); + aEvent.DropAction = GdkToVcl(gdk_drag_context_get_selected_action(context)); aEvent.SourceActions = GdkToVcl(gdk_drag_context_get_actions(context)); if (!pThis->m_bInDrag) @@ -3871,4 +3911,132 @@ Window GtkSalFrame::GetX11Window() return widget_get_xid(m_pWindow); } +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) throw(std::exception) +{ + m_xListener = rListener; + m_xTrans = rTrans; + + if (m_pFrame) + { + css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = rTrans->getTransferDataFlavors(); + std::vector<GtkTargetEntry> aGtkTargets(m_aConversionHelper.FormatsToGtk(aFormats)); + GtkTargetList *pTargetList = gtk_target_list_new(aGtkTargets.data(), aGtkTargets.size()); + + gint nDragButton = 1; // default to left button + css::awt::MouseEvent aEvent; + if (rEvent.Event >>= aEvent) + { + if (aEvent.Buttons & css::awt::MouseButton::LEFT ) + nDragButton = 1; + else if (aEvent.Buttons & css::awt::MouseButton::RIGHT) + nDragButton = 3; + else if (aEvent.Buttons & css::awt::MouseButton::MIDDLE) + nDragButton = 2; + } + + m_pFrame->startDrag(nDragButton, rEvent.DragOriginX, rEvent.DragOriginY, + VclToGdk(sourceActions), pTargetList); + gtk_target_list_unref(pTargetList); + for (auto &a : aGtkTargets) + g_free(a.target); + } + else + dragFailed(); +} + +void GtkSalFrame::startDrag(gint nButton, gint nDragOriginX, gint nDragOriginY, + GdkDragAction sourceActions, GtkTargetList* pTargetList) +{ + SolarMutexGuard aGuard; + + assert(m_pDragSource); + + GdkEvent aFakeEvent; + memset(&aFakeEvent, 0, sizeof(GdkEvent)); + aFakeEvent.type = GDK_BUTTON_PRESS; + aFakeEvent.button.window = widget_get_window(getMouseEventWidget()); + aFakeEvent.button.time = GDK_CURRENT_TIME; + GdkDeviceManager* pDeviceManager = gdk_display_get_device_manager(getGdkDisplay()); + aFakeEvent.button.device = gdk_device_manager_get_client_pointer(pDeviceManager); + + + GdkDragContext *pContext = gtk_drag_begin_with_coordinates(getMouseEventWidget(), + pTargetList, + sourceActions, + nButton, + &aFakeEvent, + nDragOriginX, + nDragOriginY); + + if (!pContext) + m_pDragSource->dragFailed(); +} + +void GtkDragSource::dragFailed() +{ + datatransfer::dnd::DragSourceDropEvent aEv; + aEv.DropAction = datatransfer::dnd::DNDConstants::ACTION_NONE; + aEv.DropSuccess = false; + m_xListener->dragDropEnd(aEv); +} + +gboolean GtkSalFrame::signalDragFailed(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkDragResult /*result*/, gpointer frame) +{ + GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + if (!pThis->m_pDragSource) + return false; + pThis->m_pDragSource->dragFailed(); + return false; +} + +void GtkDragSource::dragDelete() +{ + datatransfer::dnd::DragSourceDropEvent aEv; + aEv.DropAction = datatransfer::dnd::DNDConstants::ACTION_MOVE; + aEv.DropSuccess = true; + m_xListener->dragDropEnd(aEv); +} + +void GtkSalFrame::signalDragDelete(GtkWidget* /*widget*/, GdkDragContext* /*context*/, gpointer frame) +{ + GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + if (!pThis->m_pDragSource) + return; + pThis->m_pDragSource->dragDelete(); +} + +void GtkDragSource::dragEnd(GdkDragContext* context) +{ + datatransfer::dnd::DragSourceDropEvent aEv; + aEv.DropAction = GdkToVcl(gdk_drag_context_get_selected_action(context)); + aEv.DropSuccess = gdk_drag_drop_succeeded(context); + m_xListener->dragDropEnd(aEv); +} + +void GtkSalFrame::signalDragEnd(GtkWidget* /*widget*/, GdkDragContext* context, gpointer frame) +{ + GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + if (!pThis->m_pDragSource) + return; + pThis->m_pDragSource->dragEnd(context); +} + +void GtkDragSource::dragDataGet(GtkSelectionData *data, guint info) +{ + m_aConversionHelper.setSelectionData(m_xTrans, data, info); +} + +void GtkSalFrame::signalDragDataGet(GtkWidget* /*widget*/, GdkDragContext* /*context*/, GtkSelectionData *data, guint info, + guint /*time*/, gpointer frame) +{ + GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); + if (!pThis->m_pDragSource) + return; + pThis->m_pDragSource->dragDataGet(data, info); +} + + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 5ab81acf67ed..f914e4546f6a 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -20,8 +20,6 @@ #include "com/sun/star/datatransfer/clipboard/XClipboardListener.hpp" #include "com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp" #include "com/sun/star/datatransfer/clipboard/XSystemClipboard.hpp" -#include "com/sun/star/datatransfer/dnd/XDragSource.hpp" -#include "com/sun/star/datatransfer/dnd/XDropTarget.hpp" #include "com/sun/star/datatransfer/dnd/DNDConstants.hpp" #include <comphelper/processfactory.hxx> #include <comphelper/sequence.hxx> @@ -386,12 +384,53 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData { if (!m_aContents.is()) return; + m_aConversionHelper.setSelectionData(m_aContents, selection_data, info); +} + +void VclGtkClipboard::OwnerChanged(GtkClipboard* clipboard, GdkEvent* /*event*/) +{ + if (G_OBJECT(m_pOwner) != gtk_clipboard_get_owner(clipboard)) + { + //null out m_aContents to return control to the system-one which + //will be retrieved if getContents is called again + setContents(Reference<css::datatransfer::XTransferable>(), + Reference<css::datatransfer::clipboard::XClipboardOwner>()); + } +} + +void VclGtkClipboard::ClipboardClear(GtkClipboard * /*clipboard*/) +{ + for (auto &a : m_aGtkTargets) + g_free(a.target); + m_aGtkTargets.clear(); +} - GdkAtom type(gdk_atom_intern(OUStringToOString(m_aConversionHelper.aInfoToFlavor[info].MimeType, +GtkTargetEntry VclToGtkHelper::makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor) +{ + GtkTargetEntry aEntry; + aEntry.target = + g_strdup(OUStringToOString(rFlavor.MimeType, RTL_TEXTENCODING_UTF8).getStr()); + aEntry.flags = 0; + auto it = std::find_if(aInfoToFlavor.begin(), aInfoToFlavor.end(), + DataFlavorEq(rFlavor)); + if (it != aInfoToFlavor.end()) + aEntry.info = std::distance(aInfoToFlavor.begin(), it); + else + { + aEntry.info = aInfoToFlavor.size(); + aInfoToFlavor.push_back(rFlavor); + } + return aEntry; +} + +void VclToGtkHelper::setSelectionData(const Reference<css::datatransfer::XTransferable> &rTrans, + GtkSelectionData *selection_data, guint info) +{ + GdkAtom type(gdk_atom_intern(OUStringToOString(aInfoToFlavor[info].MimeType, RTL_TEXTENCODING_UTF8).getStr(), false)); - css::datatransfer::DataFlavor aFlavor(m_aConversionHelper.aInfoToFlavor[info]); + css::datatransfer::DataFlavor aFlavor(aInfoToFlavor[info]); if (aFlavor.MimeType == "UTF8_STRING" || aFlavor.MimeType == "STRING") aFlavor.MimeType = "text/plain;charset=utf-8"; @@ -400,9 +439,9 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData try { - aValue = m_aContents->getTransferData(aFlavor); + aValue = rTrans->getTransferData(aFlavor); } - catch(...) + catch (...) { } @@ -423,9 +462,9 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData aFlavor.DataType = cppu::UnoType<OUString>::get(); try { - aValue = m_aContents->getTransferData(aFlavor); + aValue = rTrans->getTransferData(aFlavor); } - catch(...) + catch (...) { } OUString aString; @@ -442,42 +481,6 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData aData.getLength()); } -void VclGtkClipboard::OwnerChanged(GtkClipboard* clipboard, GdkEvent* /*event*/) -{ - if (G_OBJECT(m_pOwner) != gtk_clipboard_get_owner(clipboard)) - { - //null out m_aContents to return control to the system-one which - //will be retrieved if getContents is called again - setContents(Reference<css::datatransfer::XTransferable>(), - Reference<css::datatransfer::clipboard::XClipboardOwner>()); - } -} - -void VclGtkClipboard::ClipboardClear(GtkClipboard * /*clipboard*/) -{ - for (auto &a : m_aGtkTargets) - g_free(a.target); - m_aGtkTargets.clear(); -} - -GtkTargetEntry VclToGtkHelper::makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor) -{ - GtkTargetEntry aEntry; - aEntry.target = - g_strdup(OUStringToOString(rFlavor.MimeType, RTL_TEXTENCODING_UTF8).getStr()); - aEntry.flags = 0; - auto it = std::find_if(aInfoToFlavor.begin(), aInfoToFlavor.end(), - DataFlavorEq(rFlavor)); - if (it != aInfoToFlavor.end()) - aEntry.info = std::distance(aInfoToFlavor.begin(), it); - else - { - aEntry.info = aInfoToFlavor.size(); - aInfoToFlavor.push_back(rFlavor); - } - return aEntry; -} - namespace { void ClipboardGetFunc(GtkClipboard *clipboard, GtkSelectionData *selection_data, @@ -604,6 +607,10 @@ void VclGtkClipboard::setContents( ClipboardGetFunc, ClipboardClearFunc, G_OBJECT(m_pOwner)); gtk_clipboard_set_can_store(clipboard, aGtkTargets.data(), aGtkTargets.size()); } + + for (auto &a : m_aGtkTargets) + g_free(a.target); + m_aGtkTargets = aGtkTargets; } @@ -810,4 +817,70 @@ Reference< XInterface > GtkInstance::CreateDropTarget() return Reference< XInterface >( static_cast<cppu::OWeakObject *>(new GtkDropTarget()) ); } +GtkDragSource::~GtkDragSource() +{ + if (m_pFrame) + m_pFrame->deregisterDragSource(this); +} + +void GtkDragSource::deinitialize() +{ + m_pFrame = nullptr; +} + +sal_Bool GtkDragSource::isDragImageSupported() throw(std::exception) +{ + return true; +} + +sal_Int32 GtkDragSource::getDefaultCursor( sal_Int8 ) throw(std::exception) +{ + return 0; +} + +void GtkDragSource::initialize(const css::uno::Sequence<css::uno::Any >& rArguments) throw(Exception, std::exception) +{ + if (rArguments.getLength() < 2) + { + throw RuntimeException("DragSource::initialize: Cannot install window event handler", + static_cast<OWeakObject*>(this)); + } + + sal_Size nFrame = 0; + rArguments.getConstArray()[1] >>= nFrame; + + if (!nFrame) + { + throw RuntimeException("DragSource::initialize: missing SalFrame", + static_cast<OWeakObject*>(this)); + } + + m_pFrame = reinterpret_cast<GtkSalFrame*>(nFrame); + m_pFrame->registerDragSource(this); +} + +OUString SAL_CALL GtkDragSource::getImplementationName() + throw (css::uno::RuntimeException, std::exception) +{ + return OUString("com.sun.star.datatransfer.dnd.VclGtkDragSource"); +} + +sal_Bool SAL_CALL GtkDragSource::supportsService(OUString const & ServiceName) + throw (css::uno::RuntimeException, std::exception) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence<OUString> SAL_CALL GtkDragSource::getSupportedServiceNames() + throw (css::uno::RuntimeException, std::exception) +{ + Sequence<OUString> aRet { "com.sun.star.datatransfer.dnd.GtkDragSource" }; + return aRet; +} + +Reference< XInterface > GtkInstance::CreateDragSource() +{ + return Reference< XInterface >( static_cast<cppu::OWeakObject *>(new GtkDragSource()) ); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |