[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - 7 commits - cui/source include/tools include/vcl sd/source sfx2/source sw/source vcl/inc vcl/osx vcl/source vcl/unx vcl/win

Caolán McNamara caolanm at redhat.com
Thu Jan 28 02:42:18 PST 2016


 cui/source/customize/acccfg.cxx               |    2 
 cui/source/customize/selector.cxx             |   10 
 include/tools/wintypes.hxx                    |    1 
 include/vcl/help.hxx                          |    3 
 sd/source/ui/annotations/annotationwindow.cxx |    3 
 sfx2/source/dialog/dinfdlg.cxx                |    2 
 sw/source/core/draw/dpage.cxx                 |    6 
 sw/source/uibase/docvw/edtwin2.cxx            |   17 
 vcl/inc/helpwin.hxx                           |    4 
 vcl/inc/salframe.hxx                          |   17 
 vcl/inc/unx/gtk/gtkframe.hxx                  |   66 ++-
 vcl/inc/unx/gtk/gtkinst.hxx                   |  128 +++++
 vcl/osx/salframeview.mm                       |    2 
 vcl/source/app/help.cxx                       |   75 +--
 vcl/source/window/brdwin.cxx                  |    2 
 vcl/source/window/menuwindow.cxx              |    2 
 vcl/source/window/mouse.cxx                   |    1 
 vcl/source/window/window.cxx                  |   13 
 vcl/unx/gtk/gtkobject.cxx                     |    2 
 vcl/unx/gtk/gtksalframe.cxx                   |   11 
 vcl/unx/gtk3/gtk3gtkframe.cxx                 |  499 ++++++++++++++++++++++-
 vcl/unx/gtk3/gtk3gtkinst.cxx                  |  559 ++++++++++++++++++--------
 vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx     |    3 
 vcl/win/source/window/salframe.cxx            |    4 
 24 files changed, 1155 insertions(+), 277 deletions(-)

New commits:
commit b083afac2f0531bacd790cb3ac25353f9a02db5d
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jan 27 16:20:35 2016 +0000

    Resolves: rhbz#1294208 trackpad two finger scroll goes into reverse
    
    (cherry picked from commit e734c7f53cfffa6141e6b46c06825ee273e2136b)
    
    Change-Id: Ic576f14cae82781a93e52972513a28c4a141d1a2

diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index af284ca..3914de5 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -2557,14 +2557,12 @@ gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEvent* pEvent, gpointer frame
     {
         case GDK_SCROLL_SMOOTH:
         {
-            double delta_x, delta_y;
-            gdk_event_get_scroll_deltas(pEvent, &delta_x, &delta_y);
             //pick the bigger one I guess
-            aEvent.mbHorz = fabs(delta_x) > fabs(delta_y);
+            aEvent.mbHorz = fabs(pSEvent->delta_x) > fabs(pSEvent->delta_y);
             if (aEvent.mbHorz)
-                aEvent.mnDelta = -delta_x;
+                aEvent.mnDelta = -pSEvent->delta_x * 40;
             else
-                aEvent.mnDelta = -delta_y;
+                aEvent.mnDelta = -pSEvent->delta_y * 40;
             aEvent.mnScrollLines = 1;
             pThis->m_nLastScrollEventTime = pSEvent->time;
             break;
commit 237ebf91c17f8c20304ebd4f7cf8bd058bc6f7c7
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sat Jan 23 21:10:03 2016 +0000

    Resolves: tdf#93054 gtk3: implement drag and drop
    
    Change-Id: Ib644ea36b8a9e68e023e465ef159b9a4890e5d37
    (cherry picked from commit a5b4f6e456bfb735385e8d3d6945ea8f3be1ba94)

diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 972b241..da629b7 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -42,6 +42,9 @@
 #include <basebmp/bitmapdevice.hxx>
 #include <basebmp/scanlineformats.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>
@@ -54,6 +57,9 @@ typedef ::Window GdkNativeWindow;
 #define GDK_WINDOW_XWINDOW(o) GDK_WINDOW_XID(o)
 #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
 
 #if !(GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 26)
@@ -205,6 +211,10 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
     long                            m_nWidthRequest;
     long                            m_nHeightRequest;
     cairo_region_t*                 m_pRegion;
+    GtkDropTarget*                  m_pDropTarget;
+    GtkDragSource*                  m_pDragSource;
+    bool                            m_bInDrag;
+    GtkDnDTransferable*             m_pFormatConversionRequest;
 #else
     GdkRegion*                      m_pRegion;
 #endif
@@ -236,6 +246,20 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
     static gboolean     signalTooltipQuery(GtkWidget*, gint x, gint y,
                                      gboolean keyboard_mode, GtkTooltip *tooltip,
                                      gpointer frame);
+    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,
+                                       guint time, gpointer frame);
+    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);
@@ -357,6 +381,39 @@ public:
     // only for gtk3 ...
     cairo_t* getCairoContext() const;
     void damaged (const basegfx::B2IBox& rDamageRect);
+
+    void registerDropTarget(GtkDropTarget* pDropTarget)
+    {
+        assert(!m_pDropTarget);
+        m_pDropTarget = pDropTarget;
+    }
+
+    void deregisterDropTarget(GtkDropTarget* pDropTarget)
+    {
+        assert(m_pDropTarget == pDropTarget); (void)pDropTarget;
+        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 a7c489b..b91ec52 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -23,6 +23,12 @@
 #include <unx/salinst.h>
 #include <generic/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>
+#include <cppuhelper/compbase.hxx>
 #include <gtk/gtk.h>
 
 namespace vcl
@@ -44,6 +50,126 @@ public:
     void ThreadsLeave();
 };
 
+#if GTK_CHECK_VERSION(3,0,0)
+class GtkSalFrame;
+
+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);
+};
+
+class GtkTransferable : public cppu::WeakImplHelper<css::datatransfer::XTransferable>
+{
+protected:
+    std::map<OUString, GdkAtom> m_aMimeTypeToAtom;
+
+    std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector(GdkAtom *targets, gint n_targets);
+public:
+
+    virtual css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& rFlavor)
+        throw(css::datatransfer::UnsupportedFlavorException,
+              css::io::IOException,
+              css::uno::RuntimeException, std::exception) override = 0;
+
+    virtual std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector() = 0;
+
+    virtual css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors()
+        throw(css::uno::RuntimeException, std::exception) override;
+    virtual sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor)
+        throw(css::uno::RuntimeException, std::exception) override;
+};
+
+class GtkDropTarget : public cppu::WeakComponentImplHelper<css::datatransfer::dnd::XDropTarget,
+                                                           css::lang::XInitialization,
+                                                           css::lang::XServiceInfo>
+{
+    osl::Mutex m_aMutex;
+    GtkSalFrame* m_pFrame;
+    bool m_bActive;
+    sal_Int8 m_nDefaultActions;
+    std::list<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> m_aListeners;
+public:
+    GtkDropTarget();
+    virtual ~GtkDropTarget();
+
+    // XInitialization
+    virtual void        SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArgs)
+                                    throw (css::uno::Exception, std::exception) override;
+            void        deinitialize();
+
+    // XDropTarget
+    virtual void        SAL_CALL addDropTargetListener(const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>&)
+                                    throw (std::exception) override;
+    virtual void        SAL_CALL removeDropTargetListener(const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>&)
+                                    throw (std::exception) override;
+    virtual sal_Bool    SAL_CALL isActive() throw(std::exception) override;
+    virtual void        SAL_CALL setActive(sal_Bool active) throw(std::exception) override;
+    virtual sal_Int8    SAL_CALL getDefaultActions() throw(std::exception) override;
+    virtual void        SAL_CALL setDefaultActions(sal_Int8 actions) throw(std::exception) override;
+
+    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 fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent& dtdee);
+    void fire_dragOver(const css::datatransfer::dnd::DropTargetDragEvent& dtde);
+    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;
 #if GTK_CHECK_VERSION(3,0,0)
 class GtkInstance : public SvpSalInstance
@@ -94,6 +220,8 @@ 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
 
     virtual const cairo_font_options_t* GetCairoFontOptions() override;
diff --git a/vcl/source/window/mouse.cxx b/vcl/source/window/mouse.cxx
index 198e4cd..b55e7a0 100644
--- a/vcl/source/window/mouse.cxx
+++ b/vcl/source/window/mouse.cxx
@@ -750,6 +750,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/gtk/gtkobject.cxx b/vcl/unx/gtk/gtkobject.cxx
index 1d510a4..35084aa 100644
--- a/vcl/unx/gtk/gtkobject.cxx
+++ b/vcl/unx/gtk/gtkobject.cxx
@@ -62,8 +62,8 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
 #else
         static int nWindow = 0;
         m_aSystemData.aWindow       = nWindow;
-        m_aSystemData.aShellWindow  = pParent->GetSystemData()->aWindow;
         ++nWindow;
+        m_aSystemData.aShellWindow  = reinterpret_cast<long>(this);
 #endif
         m_aSystemData.pSalFrame     = nullptr;
         m_aSystemData.pWidget       = m_pSocket;
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index cc66428..af284ca 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -74,6 +74,8 @@
 #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>
 #include <com/sun/star/frame/XFrame.hpp>
@@ -801,6 +803,18 @@ void GtkSalFrame::InvalidateGraphics()
 
 GtkSalFrame::~GtkSalFrame()
 {
+    if (m_pDropTarget)
+    {
+        m_pDropTarget->deinitialize();
+        m_pDropTarget = nullptr;
+    }
+
+    if (m_pDragSource)
+    {
+        m_pDragSource->deinitialize();
+        m_pDragSource= nullptr;
+    }
+
     InvalidateGraphics();
 
     if( m_pParent )
@@ -985,6 +999,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)
@@ -1028,6 +1057,10 @@ void GtkSalFrame::InitCommon()
     m_hBackgroundPixmap = None;
     m_nExtStyle         = 0;
     m_pRegion           = nullptr;
+    m_pDropTarget       = nullptr;
+    m_pDragSource       = nullptr;
+    m_bInDrag           = false;
+    m_pFormatConversionRequest = nullptr;
     m_ePointerStyle     = static_cast<PointerStyle>(0xffff);
     m_bSetFocusOnMap    = false;
     m_pSalMenu          = nullptr;
@@ -1054,8 +1087,8 @@ void GtkSalFrame::InitCommon()
     m_aSystemData.nSize         = sizeof( SystemEnvData );
     static int nWindow = 0;
     m_aSystemData.aWindow       = nWindow;
-    m_aSystemData.aShellWindow  = nWindow;
     ++nWindow;
+    m_aSystemData.aShellWindow  = reinterpret_cast<long>(this);
     m_aSystemData.pSalFrame     = this;
     m_aSystemData.pWidget       = m_pWindow;
     m_aSystemData.nScreen       = m_nXScreen.getXScreen();
@@ -3033,6 +3066,288 @@ gboolean GtkSalFrame::signalVisibility( GtkWidget*, GdkEventVisibility* pEvent,
     return true;
 }
 
+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;
+    }
+
+    sal_Int8 GdkToVcl(GdkDragAction dragOperation)
+    {
+        sal_Int8 nRet(0);
+        if (dragOperation & GDK_ACTION_COPY)
+            nRet |= css::datatransfer::dnd::DNDConstants::ACTION_COPY;
+        if (dragOperation & GDK_ACTION_MOVE)
+            nRet |= css::datatransfer::dnd::DNDConstants::ACTION_MOVE;
+        if (dragOperation & GDK_ACTION_LINK)
+            nRet |= css::datatransfer::dnd::DNDConstants::ACTION_LINK;
+        return nRet;
+    }
+}
+
+class GtkDropTargetDropContext : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDropContext>
+{
+    GdkDragContext *m_pContext;
+    guint m_nTime;
+public:
+    GtkDropTargetDropContext(GdkDragContext *pContext, guint nTime)
+        : m_pContext(pContext)
+        , m_nTime(nTime)
+    {
+    }
+
+    // XDropTargetDropContext
+    virtual void SAL_CALL acceptDrop(sal_Int8 dragOperation) throw(std::exception) override
+    {
+        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
+    {
+        gdk_drag_status(m_pContext, static_cast<GdkDragAction>(0), m_nTime);
+    }
+
+    virtual void SAL_CALL dropComplete(sal_Bool bSuccess) throw(std::exception) override
+    {
+        gtk_drag_finish(m_pContext, bSuccess, false, m_nTime);
+    }
+};
+
+class GtkDnDTransferable : public GtkTransferable
+{
+    GdkDragContext *m_pContext;
+    guint m_nTime;
+    GtkWidget *m_pWidget;
+    GtkSalFrame *m_pFrame;
+    GMainLoop *m_pLoop;
+    GtkSelectionData *m_pData;
+public:
+    GtkDnDTransferable(GdkDragContext *pContext, guint nTime, GtkWidget *pWidget, GtkSalFrame *pFrame)
+        : m_pContext(pContext)
+        , m_nTime(nTime)
+        , m_pWidget(pWidget)
+        , m_pFrame(pFrame)
+        , m_pLoop(nullptr)
+        , m_pData(nullptr)
+    {
+    }
+
+    virtual css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& rFlavor)
+        throw(css::datatransfer::UnsupportedFlavorException,
+              css::io::IOException,
+              css::uno::RuntimeException, std::exception) override
+    {
+        css::datatransfer::DataFlavor aFlavor(rFlavor);
+        if (aFlavor.MimeType == "text/plain;charset=utf-16")
+            aFlavor.MimeType = "text/plain;charset=utf-8";
+
+        auto it = m_aMimeTypeToAtom.find(aFlavor.MimeType);
+        if (it == m_aMimeTypeToAtom.end())
+            return css::uno::Any();
+
+        /* like gtk_clipboard_wait_for_contents run a sub loop
+         * waiting for drag-data-received triggered from
+         * gtk_drag_get_data
+         */
+        {
+            m_pLoop = g_main_loop_new(nullptr, true);
+            m_pFrame->SetFormatConversionRequest(this);
+
+            gtk_drag_get_data(m_pWidget, m_pContext, it->second, m_nTime);
+
+            if (g_main_loop_is_running(m_pLoop))
+            {
+                gdk_threads_leave();
+                g_main_loop_run(m_pLoop);
+                gdk_threads_enter();
+            }
+
+            g_main_loop_unref(m_pLoop);
+            m_pLoop = nullptr;
+            m_pFrame->SetFormatConversionRequest(nullptr);
+        }
+
+        css::uno::Any aRet;
+
+        if (aFlavor.MimeType == "text/plain;charset=utf-8")
+        {
+            OUString aStr;
+            gchar *pText = reinterpret_cast<gchar*>(gtk_selection_data_get_text(m_pData));
+            if (pText)
+                aStr = OUString(pText, rtl_str_getLength(pText), RTL_TEXTENCODING_UTF8);
+            g_free(pText);
+            aRet <<= aStr.replaceAll("\r\n", "\n");
+        }
+        else
+        {
+            gint length(0);
+            const guchar *rawdata = gtk_selection_data_get_data_with_length(m_pData,
+                                                                            &length);
+            css::uno::Sequence<sal_Int8> aSeq(reinterpret_cast<const sal_Int8*>(rawdata), length);
+            aRet <<= aSeq;
+        }
+
+        gtk_selection_data_free(m_pData);
+
+        return aRet;
+    }
+
+    virtual std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector() override
+    {
+        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());
+    }
+
+    void LoopEnd(GtkSelectionData *pData)
+    {
+        m_pData = pData;
+        g_main_loop_quit(m_pLoop);
+    }
+};
+
+gboolean GtkSalFrame::signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time, gpointer frame)
+{
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+
+    if (!pThis->m_pDropTarget)
+        return false;
+
+    css::datatransfer::dnd::DropTargetDropEvent aEvent;
+    aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pThis->m_pDropTarget);
+    aEvent.Context = new GtkDropTargetDropContext(context, time);
+    aEvent.LocationX = x;
+    aEvent.LocationY = y;
+    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;
+
+    pThis->m_pDropTarget->fire_drop(aEvent);
+
+    return true;
+}
+
+class GtkDropTargetDragContext : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDragContext>
+{
+    GdkDragContext *m_pContext;
+    guint m_nTime;
+public:
+    GtkDropTargetDragContext(GdkDragContext *pContext, guint nTime)
+        : m_pContext(pContext)
+        , m_nTime(nTime)
+    {
+    }
+
+    virtual void SAL_CALL acceptDrag(sal_Int8 dragOperation) throw(std::exception) override
+    {
+        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
+    {
+        gdk_drag_status(m_pContext, static_cast<GdkDragAction>(0), m_nTime);
+    }
+};
+
+void GtkSalFrame::signalDragDropReceived(GtkWidget* /*pWidget*/, GdkDragContext * /*context*/, gint /*x*/, gint /*y*/, GtkSelectionData* data, guint /*ttype*/, guint /*time*/, gpointer frame)
+{
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+
+    /*
+     * If we get a drop, then we will call like gtk_clipboard_wait_for_contents
+     * with a loop inside a loop to get the right format, so if this is the
+     * case return to the outer loop here with a copy of the desired data
+     *
+     * don't look at me like that.
+     */
+    if (!pThis->m_pFormatConversionRequest)
+        return;
+
+    pThis->m_pFormatConversionRequest->LoopEnd(gtk_selection_data_copy(data));
+}
+
+gboolean GtkSalFrame::signalDragMotion(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer frame)
+{
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+
+    if (!pThis->m_pDropTarget)
+        return false;
+
+    if (!pThis->m_bInDrag)
+        gtk_drag_highlight(widget);
+
+    css::datatransfer::dnd::DropTargetDragEnterEvent aEvent;
+    aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pThis->m_pDropTarget);
+    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_selected_action(context));
+    aEvent.SourceActions = GdkToVcl(gdk_drag_context_get_actions(context));
+
+    if (!pThis->m_bInDrag)
+    {
+        css::uno::Reference<css::datatransfer::XTransferable> xTrans(new GtkDnDTransferable(context, time, widget, pThis));
+        css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = xTrans->getTransferDataFlavors();
+        aEvent.SupportedDataFlavors = aFormats;
+        pThis->m_pDropTarget->fire_dragEnter(aEvent);
+        pThis->m_bInDrag = true;
+    }
+    else
+    {
+        pThis->m_pDropTarget->fire_dragOver(aEvent);
+    }
+
+    return true;
+}
+
+void GtkSalFrame::signalDragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint /*time*/, gpointer frame)
+{
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+    if (!pThis->m_pDropTarget)
+        return;
+    pThis->m_bInDrag = false;
+    gtk_drag_unhighlight(widget);
+
+#if 0
+    css::datatransfer::dnd::DropTargetEvent aEvent;
+    aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pThis->m_pDropTarget);
+    pThis->m_pDropTarget->fire_dragExit(aEvent);
+#endif
+}
+
 void GtkSalFrame::signalDestroy( GtkWidget* pObj, gpointer frame )
 {
     GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
@@ -3618,4 +3933,141 @@ 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);
+
+#if GTK_CHECK_VERSION(3,10,0)
+    GdkDragContext *pContext = gtk_drag_begin_with_coordinates(getMouseEventWidget(),
+                                                               pTargetList,
+                                                               sourceActions,
+                                                               nButton,
+                                                               &aFakeEvent,
+                                                               nDragOriginX,
+                                                               nDragOriginY);
+#else
+    GdkDragContext *pContext = gtk_drag_begin(getMouseEventWidget(),
+                                              pTargetList,
+                                              sourceActions,
+                                              nButton,
+                                              &aFakeEvent);
+    (void)nDragOriginX;
+    (void)nDragOriginY;
+#endif
+
+    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 a3f3068..f914e45 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>
@@ -93,15 +91,87 @@ namespace
     };
 }
 
-class GtkTransferable : public ::cppu::WeakImplHelper <
-    css::datatransfer::XTransferable >
+std::vector<css::datatransfer::DataFlavor> GtkTransferable::getTransferDataFlavorsAsVector(GdkAtom *targets, gint n_targets)
+{
+    std::vector<css::datatransfer::DataFlavor> aVector;
+
+    bool bHaveText = false, bHaveUTF16 = false;
+
+    for (gint i = 0; i < n_targets; ++i)
+    {
+        gchar* pName = gdk_atom_name(targets[i]);
+        const char* pFinalName = pName;
+        css::datatransfer::DataFlavor aFlavor;
+
+        for (size_t j = 0; j < SAL_N_ELEMENTS(aConversionTab); ++j)
+        {
+            if (rtl_str_compare(pName, aConversionTab[j].pNativeType) == 0)
+            {
+                pFinalName = aConversionTab[j].pType;
+                break;
+            }
+        }
+
+        aFlavor.MimeType = OUString(pFinalName,
+                                    rtl_str_getLength(pFinalName),
+                                    RTL_TEXTENCODING_UTF8);
+
+        m_aMimeTypeToAtom[aFlavor.MimeType] = targets[i];
+
+        aFlavor.DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
+
+        sal_Int32 nIndex(0);
+        if (aFlavor.MimeType.getToken(0, ';', nIndex) == "text/plain")
+        {
+            bHaveText = true;
+            OUString aToken(aFlavor.MimeType.getToken(0, ';', nIndex));
+            if (aToken == "charset=utf-16")
+            {
+                bHaveUTF16 = true;
+                aFlavor.DataType = cppu::UnoType<OUString>::get();
+            }
+        }
+        aVector.push_back(aFlavor);
+        g_free(pName);
+    }
+
+    //If we have text, but no UTF-16 format which is basically the only
+    //text-format LibreOffice supports for cnp then claim we do and we
+    //will convert on demand
+    if (bHaveText && !bHaveUTF16)
+    {
+        css::datatransfer::DataFlavor aFlavor;
+        aFlavor.MimeType = "text/plain;charset=utf-16";
+        aFlavor.DataType = cppu::UnoType<OUString>::get();
+        aVector.push_back(aFlavor);
+    }
+
+    return aVector;
+}
+
+
+css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL GtkTransferable::getTransferDataFlavors()
+        throw(css::uno::RuntimeException, std::exception)
+{
+    return comphelper::containerToSequence(getTransferDataFlavorsAsVector());
+}
+
+sal_Bool SAL_CALL GtkTransferable::isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor)
+        throw(css::uno::RuntimeException, std::exception)
+{
+    const std::vector<css::datatransfer::DataFlavor> aAll =
+        getTransferDataFlavorsAsVector();
+
+    return std::find_if(aAll.begin(), aAll.end(), DataFlavorEq(rFlavor)) != aAll.end();
+}
+
+class GtkClipboardTransferable : public GtkTransferable
 {
 private:
     GdkAtom m_nSelection;
-    std::map<OUString, GdkAtom> m_aMimeTypeToAtom;
 public:
 
-    explicit GtkTransferable(GdkAtom nSelection)
+    explicit GtkClipboardTransferable(GdkAtom nSelection)
         : m_nSelection(nSelection)
     {
     }
@@ -146,6 +216,7 @@ public:
     }
 
     std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector()
+        override
     {
         std::vector<css::datatransfer::DataFlavor> aVector;
 
@@ -155,77 +226,12 @@ public:
         gint n_targets;
         if (gtk_clipboard_wait_for_targets(clipboard, &targets, &n_targets))
         {
-            bool bHaveText = false, bHaveUTF16 = false;
-
-            for (gint i = 0; i < n_targets; ++i)
-            {
-                gchar* pName = gdk_atom_name(targets[i]);
-                const char* pFinalName = pName;
-                css::datatransfer::DataFlavor aFlavor;
-
-                for (size_t j = 0; j < SAL_N_ELEMENTS(aConversionTab); ++j)
-                {
-                    if (rtl_str_compare(pName, aConversionTab[j].pNativeType) == 0)
-                    {
-                        pFinalName = aConversionTab[j].pType;
-                        break;
-                    }
-                }
-
-                aFlavor.MimeType = OUString(pFinalName,
-                                            rtl_str_getLength(pFinalName),
-                                            RTL_TEXTENCODING_UTF8);
-
-                m_aMimeTypeToAtom[aFlavor.MimeType] = targets[i];
-
-                aFlavor.DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
-
-                sal_Int32 nIndex(0);
-                if (aFlavor.MimeType.getToken(0, ';', nIndex) == "text/plain")
-                {
-                    bHaveText = true;
-                    OUString aToken(aFlavor.MimeType.getToken(0, ';', nIndex));
-                    if (aToken == "charset=utf-16")
-                    {
-                        bHaveUTF16 = true;
-                        aFlavor.DataType = cppu::UnoType<OUString>::get();
-                    }
-                }
-                aVector.push_back(aFlavor);
-                g_free(pName);
-            }
-
+            aVector = GtkTransferable::getTransferDataFlavorsAsVector(targets, n_targets);
             g_free(targets);
-
-            //If we have text, but no UTF-16 format which is basically the only
-            //text-format LibreOffice supports for cnp then claim we do and we
-            //will convert on demand
-            if (bHaveText && !bHaveUTF16)
-            {
-                css::datatransfer::DataFlavor aFlavor;
-                aFlavor.MimeType = "text/plain;charset=utf-16";
-                aFlavor.DataType = cppu::UnoType<OUString>::get();
-                aVector.push_back(aFlavor);
-            }
         }
 
         return aVector;
     }
-
-    virtual css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors()
-        throw(css::uno::RuntimeException, std::exception) override
-    {
-        return comphelper::containerToSequence(getTransferDataFlavorsAsVector());
-    }
-
-    virtual sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor)
-        throw(css::uno::RuntimeException, std::exception) override
-    {
-        const std::vector<css::datatransfer::DataFlavor> aAll =
-            getTransferDataFlavorsAsVector();
-
-        return std::find_if(aAll.begin(), aAll.end(), DataFlavorEq(rFlavor)) != aAll.end();
-    }
 };
 
 //We want to use gtk_clipboard_get_owner own owner-change to distinguish between
@@ -286,7 +292,7 @@ class VclGtkClipboard :
     Reference<css::datatransfer::clipboard::XClipboardOwner> m_aOwner;
     std::list< Reference<css::datatransfer::clipboard::XClipboardListener> > m_aListeners;
     std::vector<GtkTargetEntry> m_aGtkTargets;
-    std::vector<css::datatransfer::DataFlavor> m_aInfoToFlavor;
+    VclToGtkHelper m_aConversionHelper;
 
 public:
 
@@ -301,9 +307,6 @@ public:
     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw( RuntimeException, std::exception ) override;
     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw( RuntimeException, std::exception ) override;
 
-    static OUString getImplementationName_static();
-    static Sequence< OUString > getSupportedServiceNames_static();
-
     /*
      * XClipboard
      */
@@ -346,29 +349,17 @@ public:
     void ClipboardGet(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info);
     void ClipboardClear(GtkClipboard *clipboard);
     void OwnerChanged(GtkClipboard *clipboard, GdkEvent *event);
-private:
-    GtkTargetEntry makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor);
 };
 
-OUString VclGtkClipboard::getImplementationName_static()
-{
-    return OUString( "com.sun.star.datatransfer.VclGtkClipboard"  );
-}
-
-Sequence< OUString > VclGtkClipboard::getSupportedServiceNames_static()
-{
-    Sequence< OUString > aRet { "com.sun.star.datatransfer.clipboard.SystemClipboard" };
-    return aRet;
-}
-
 OUString VclGtkClipboard::getImplementationName() throw( RuntimeException, std::exception )
 {
-    return getImplementationName_static();
+    return OUString("com.sun.star.datatransfer.VclGtkClipboard");
 }
 
 Sequence< OUString > VclGtkClipboard::getSupportedServiceNames() throw( RuntimeException, std::exception )
 {
-    return getSupportedServiceNames_static();
+    Sequence<OUString> aRet { "com.sun.star.datatransfer.clipboard.SystemClipboard" };
+    return aRet;
 }
 
 sal_Bool VclGtkClipboard::supportsService( const OUString& ServiceName ) throw( RuntimeException, std::exception )
@@ -383,7 +374,7 @@ Reference< css::datatransfer::XTransferable > VclGtkClipboard::getContents() thr
     {
         //tdf#93887 This is the system clipboard/selection. We fetch it when we are not
         //the owner of the clipboard and have not already fetched it.
-        m_aContents = new GtkTransferable(m_nSelection);
+        m_aContents = new GtkClipboardTransferable(m_nSelection);
     }
     return m_aContents;
 }
@@ -393,12 +384,53 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData
 {
     if (!m_aContents.is())
         return;
+    m_aConversionHelper.setSelectionData(m_aContents, selection_data, info);
+}
 
-    GdkAtom type(gdk_atom_intern(OUStringToOString(m_aInfoToFlavor[info].MimeType,
+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;
+}
+
+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_aInfoToFlavor[info]);
+    css::datatransfer::DataFlavor aFlavor(aInfoToFlavor[info]);
     if (aFlavor.MimeType == "UTF8_STRING" || aFlavor.MimeType == "STRING")
         aFlavor.MimeType = "text/plain;charset=utf-8";
 
@@ -407,9 +439,9 @@ void VclGtkClipboard::ClipboardGet(GtkClipboard* /*clipboard*/, GtkSelectionData
 
     try
     {
-        aValue = m_aContents->getTransferData(aFlavor);
+        aValue = rTrans->getTransferData(aFlavor);
     }
-    catch(...)
+    catch (...)
     {
     }
 
@@ -430,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;
@@ -449,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 VclGtkClipboard::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(m_aInfoToFlavor.begin(), m_aInfoToFlavor.end(),
-                        DataFlavorEq(rFlavor));
-    if (it != m_aInfoToFlavor.end())
-        aEntry.info = std::distance(m_aInfoToFlavor.begin(), it);
-    else
-    {
-        aEntry.info = m_aInfoToFlavor.size();
-        m_aInfoToFlavor.push_back(rFlavor);
-    }
-    return aEntry;
-}
-
 namespace
 {
     void ClipboardGetFunc(GtkClipboard *clipboard, GtkSelectionData *selection_data,
@@ -539,6 +535,47 @@ VclGtkClipboard::~VclGtkClipboard()
     ClipboardClear(nullptr);
 }
 
+std::vector<GtkTargetEntry> VclToGtkHelper::FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats)
+{
+    std::vector<GtkTargetEntry> aGtkTargets;
+
+    bool bHaveText(false), bHaveUTF8(false);
+    for (int i = 0; i < rFormats.getLength(); ++i)
+    {
+        const css::datatransfer::DataFlavor& rFlavor = rFormats[i];
+
+        sal_Int32 nIndex(0);
+        if (rFlavor.MimeType.getToken(0, ';', nIndex) == "text/plain")
+        {
+            bHaveText = true;
+            OUString aToken(rFlavor.MimeType.getToken(0, ';', nIndex));
+            if (aToken == "charset=utf-8")
+            {
+                bHaveUTF8 = true;
+            }
+        }
+        GtkTargetEntry aEntry(makeGtkTargetEntry(rFlavor));
+        aGtkTargets.push_back(aEntry);
+    }
+
+    if (bHaveText)
+    {
+        css::datatransfer::DataFlavor aFlavor;
+        aFlavor.DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
+        if (!bHaveUTF8)
+        {
+            aFlavor.MimeType = "text/plain;charset=utf-8";
+            aGtkTargets.push_back(makeGtkTargetEntry(aFlavor));
+        }
+        aFlavor.MimeType = "UTF8_STRING";
+        aGtkTargets.push_back(makeGtkTargetEntry(aFlavor));
+        aFlavor.MimeType = "STRING";
+        aGtkTargets.push_back(makeGtkTargetEntry(aFlavor));
+    }
+
+    return aGtkTargets;
+}
+
 void VclGtkClipboard::setContents(
         const Reference< css::datatransfer::XTransferable >& xTrans,
         const Reference< css::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner )
@@ -556,41 +593,7 @@ void VclGtkClipboard::setContents(
     if (m_aContents.is())
     {
         css::uno::Sequence<css::datatransfer::DataFlavor> aFormats = xTrans->getTransferDataFlavors();
-        std::vector<GtkTargetEntry> aGtkTargets;
-        bool bHaveText(false), bHaveUTF8(false);
-        for (int i = 0; i < aFormats.getLength(); ++i)
-        {
-            const css::datatransfer::DataFlavor& rFlavor = aFormats[i];
-
-            sal_Int32 nIndex(0);
-            if (rFlavor.MimeType.getToken(0, ';', nIndex) == "text/plain")
-            {
-                bHaveText = true;
-                OUString aToken(rFlavor.MimeType.getToken(0, ';', nIndex));
-                if (aToken == "charset=utf-8")
-                {
-                    bHaveUTF8 = true;
-                }
-            }
-            GtkTargetEntry aEntry(makeGtkTargetEntry(rFlavor));
-            aGtkTargets.push_back(aEntry);
-        }
-
-        if (bHaveText)
-        {
-            css::datatransfer::DataFlavor aFlavor;
-            aFlavor.DataType = cppu::UnoType<Sequence< sal_Int8 >>::get();
-            if (!bHaveUTF8)
-            {
-                aFlavor.MimeType = "text/plain;charset=utf-8";
-                aGtkTargets.push_back(makeGtkTargetEntry(aFlavor));
-            }
-            aFlavor.MimeType = "UTF8_STRING";
-            aGtkTargets.push_back(makeGtkTargetEntry(aFlavor));
-            aFlavor.MimeType = "STRING";
-            aGtkTargets.push_back(makeGtkTargetEntry(aFlavor));
-        }
-
+        std::vector<GtkTargetEntry> aGtkTargets(m_aConversionHelper.FormatsToGtk(aFormats));
         if (!aGtkTargets.empty())
         {
             //if there was a previous gtk_clipboard_set_with_data call then
@@ -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;
     }
 
@@ -662,4 +669,218 @@ Reference< XInterface > GtkInstance::CreateClipboard(const Sequence< Any >& argu
     return Reference< XInterface >( static_cast<cppu::OWeakObject *>(new VclGtkClipboard(nSelection)) );
 }
 
+GtkDropTarget::GtkDropTarget()
+    : WeakComponentImplHelper(m_aMutex)
+    , m_pFrame(nullptr)
+    , m_bActive(false)
+    , m_nDefaultActions(0)
+{
+}
+
+OUString SAL_CALL GtkDropTarget::getImplementationName()
+            throw (css::uno::RuntimeException, std::exception)
+{
+    return OUString("com.sun.star.datatransfer.dnd.VclGtkDropTarget");
+}
+
+sal_Bool SAL_CALL GtkDropTarget::supportsService(OUString const & ServiceName)
+    throw (css::uno::RuntimeException, std::exception)
+{
+    return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL GtkDropTarget::getSupportedServiceNames()
+    throw (css::uno::RuntimeException, std::exception)
+{
+    Sequence<OUString> aRet { "com.sun.star.datatransfer.dnd.GtkDropTarget" };
+    return aRet;
+}
+
+GtkDropTarget::~GtkDropTarget()
+{
+    if (m_pFrame)
+        m_pFrame->deregisterDropTarget(this);
+}
+
+void GtkDropTarget::deinitialize()
+{
+    m_pFrame = nullptr;
+    m_bActive = false;
+}
+
+void GtkDropTarget::initialize(const Sequence<Any>& rArguments) throw( Exception, std::exception )
+{
+    if (rArguments.getLength() < 2)
+    {
+        throw RuntimeException("DropTarget::initialize: Cannot install window event handler",
+                               static_cast<OWeakObject*>(this));
+    }
+
+    sal_Size nFrame = 0;
+    rArguments.getConstArray()[1] >>= nFrame;
+
+    if (!nFrame)
+    {
+        throw RuntimeException("DropTarget::initialize: missing SalFrame",
+                               static_cast<OWeakObject*>(this));
+    }
+
+    m_pFrame = reinterpret_cast<GtkSalFrame*>(nFrame);
+    m_pFrame->registerDropTarget(this);
+    m_bActive = true;
+}
+
+void GtkDropTarget::addDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& xListener) throw(std::exception)
+{
+    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
+
+    m_aListeners.push_back( xListener );
+}
+
+void GtkDropTarget::removeDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& xListener) throw(std::exception)
+{
+    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
+
+    m_aListeners.remove( xListener );
+}
+
+void GtkDropTarget::fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde)
+{
+    osl::ClearableGuard<osl::Mutex> aGuard( m_aMutex );
+    std::list<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(m_aListeners);
+    aGuard.clear();
+
+    for (auto it = aListeners.begin(); it != aListeners.end(); ++it)
+    {
+        (*it)->drop( dtde );
+    }
+}
+
+void GtkDropTarget::fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent& dtde)
+{
+    osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex );
+    std::list<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(m_aListeners);
+    aGuard.clear();
+
+    for (auto it = aListeners.begin(); it != aListeners.end(); ++it)
+    {
+        (*it)->dragEnter( dtde );
+    }
+}
+
+void GtkDropTarget::fire_dragOver(const css::datatransfer::dnd::DropTargetDragEvent& dtde)
+{
+    osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex );
+    std::list<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(m_aListeners);
+    aGuard.clear();
+
+    for (auto it = aListeners.begin(); it != aListeners.end(); ++it)
+    {
+        (*it)->dragOver( dtde );
+    }
+}
+
+void GtkDropTarget::fire_dragExit(const css::datatransfer::dnd::DropTargetEvent& dte)
+{
+    osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex );
+    std::list<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(m_aListeners);
+    aGuard.clear();
+
+    for (auto it = aListeners.begin(); it != aListeners.end(); ++it)
+    {
+        (*it)->dragExit( dte );
+    }
+}
+
+sal_Bool GtkDropTarget::isActive() throw(std::exception)
+{
+    return m_bActive;
+}
+
+void GtkDropTarget::setActive(sal_Bool bActive) throw(std::exception)
+{
+    m_bActive = bActive;
+}
+
+sal_Int8 GtkDropTarget::getDefaultActions() throw(std::exception)
+{
+    return m_nDefaultActions;
+}
+
+void GtkDropTarget::setDefaultActions(sal_Int8 nDefaultActions) throw(std::exception)
+{
+    m_nDefaultActions = nDefaultActions;
+}
+
+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: */
commit b0b8b419b249860617b12bf3e7dd233ba4f71e04
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Dec 16 21:30:22 2015 +0000

    remove newly unused WB_NEEDSFOCUS and fragile FLOAT_FOCUSABLE
    
    Change-Id: Idce03318fbc01039a6c0638879785607970993c0
    Reviewed-on: https://gerrit.libreoffice.org/20746
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 016730421e5e58415170b464bf9d9ca47d6c3b4e)

diff --git a/include/tools/wintypes.hxx b/include/tools/wintypes.hxx
index 781865d..f7ebaa2 100644
--- a/include/tools/wintypes.hxx
+++ b/include/tools/wintypes.hxx
@@ -179,7 +179,6 @@ WinBits const WB_NOSHADOW =             SAL_CONST_INT64(0x400000000);
 WinBits const WB_TOOLTIPWIN =           SAL_CONST_INT64(0x800000000);
 WinBits const WB_OWNERDRAWDECORATION =  SAL_CONST_INT64(0x2000000000);
 WinBits const WB_DEFAULTWIN =           SAL_CONST_INT64(0x4000000000);
-WinBits const WB_NEEDSFOCUS =           SAL_CONST_INT64(0x1000000000);
 WinBits const WB_POPUP =                SAL_CONST_INT64(0x20000000);
 
 WinBits const WB_HSCROLL =              WB_HORZ;
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
index dacf3fa..c08486f 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -74,8 +74,6 @@ enum class SalFrameStyleFlags
     INTRO               = 0x00000100,
     // partial fullscreen: fullscreen on one monitor of a multimonitor display
     PARTIAL_FULLSCREEN  = 0x00800000,
-    // floating window that needs to be focusable
-    FLOAT_FOCUSABLE     = 0x04000000,
     // system child window inside another SalFrame
     SYSTEMCHILD         = 0x08000000,
     // plugged system child window
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 5c59dc8..972b241 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -278,8 +278,7 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
         return
             (m_nStyle & SalFrameStyleFlags::FLOAT) &&                // only a float can be floatgrab
             !(m_nStyle & SalFrameStyleFlags::TOOLTIP) &&             // tool tips are not
-            !(m_nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) && // toolbars are also not
-            !(m_nStyle & SalFrameStyleFlags::FLOAT_FOCUSABLE);       // focusable floats are not
+            !(m_nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION);   // toolbars are also not
     }
 
     bool isChild( bool bPlug = true, bool bSysChild = true )
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index d163169..d4d37c8 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -242,8 +242,6 @@ static AquaSalFrame* getMouseContainerFrame()
         return YES;
     if( mpFrame->mbFullScreen )
         return YES;
-    if( (mpFrame->mnStyle & SalFrameStyleFlags::FLOAT_FOCUSABLE) )
-        return YES;
     return [super canBecomeKeyWindow];
 }
 
diff --git a/vcl/source/window/brdwin.cxx b/vcl/source/window/brdwin.cxx
index 1d79dd0..4cfb672 100644
--- a/vcl/source/window/brdwin.cxx
+++ b/vcl/source/window/brdwin.cxx
@@ -1736,7 +1736,7 @@ void ImplBorderWindow::ImplInit( vcl::Window* pParent,
 {
     // remove all unwanted WindowBits
     WinBits nOrgStyle = nStyle;
-    WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_PINABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW  | WB_NEEDSFOCUS | WB_POPUP);
+    WinBits nTestStyle = (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_PINABLE | WB_CLOSEABLE | WB_STANDALONE | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_SYSTEMFLOATWIN | WB_INTROWIN | WB_DEFAULTWIN | WB_TOOLTIPWIN | WB_NOSHADOW | WB_OWNERDRAWDECORATION | WB_SYSTEMCHILDWINDOW  | WB_POPUP);
     if ( nTypeStyle & BORDERWINDOW_STYLE_APP )
         nTestStyle |= WB_APP;
     nStyle &= nTestStyle;
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index d1b5bc1..bd2a662 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -913,7 +913,7 @@ void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* p
             nBorderTypeStyle |= BORDERWINDOW_STYLE_FRAME;
             nStyle |= WB_BORDER;
         }
-        VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_NEEDSFOCUS), nBorderTypeStyle );
+        VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
         static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this;
         pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
         mpWindowImpl->mpBorderWindow  = pBorderWin;
@@ -968,8 +968,6 @@ void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* p
             nFrameStyle = SalFrameStyleFlags::FLOAT;
             if( nStyle & WB_OWNERDRAWDECORATION )
                 nFrameStyle |= (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW);
-            if( nStyle & WB_NEEDSFOCUS )
-                nFrameStyle |= SalFrameStyleFlags::FLOAT_FOCUSABLE;
         }
         else if( mpWindowImpl->mbFloatWin )
             nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW;
diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx
index 2ca581c..3b6caa6 100644
--- a/vcl/unx/gtk/gtksalframe.cxx
+++ b/vcl/unx/gtk/gtksalframe.cxx
@@ -1201,8 +1201,7 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
     m_nStyle = nStyle;
 
     GtkWindowType eWinType = (  (nStyle & SalFrameStyleFlags::FLOAT) &&
-                              ! (nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION|
-                                           SalFrameStyleFlags::FLOAT_FOCUSABLE))
+                              ! (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)
                               )
         ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL;
 
@@ -1238,7 +1237,7 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
     bool bDecoHandling =
         ! isChild() &&
         ( ! (nStyle & SalFrameStyleFlags::FLOAT) ||
-          (nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION|SalFrameStyleFlags::FLOAT_FOCUSABLE) ) );
+          (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) );
 
     if( bDecoHandling )
     {
@@ -1260,10 +1259,6 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
             eType = GDK_WINDOW_TYPE_HINT_TOOLBAR;
             lcl_set_accept_focus( GTK_WINDOW(m_pWindow), false, true );
         }
-        else if( (nStyle & SalFrameStyleFlags::FLOAT_FOCUSABLE) )
-        {
-            eType = GDK_WINDOW_TYPE_HINT_UTILITY;
-        }
         if( (nStyle & SalFrameStyleFlags::PARTIAL_FULLSCREEN )
             && getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
         {
@@ -2196,7 +2191,7 @@ void GtkSalFrame::ToTop( sal_uInt16 nFlags )
              *  to our window - which it of course won't since our input hint
              *  is set to false.
              */
-            if( (m_nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION|SalFrameStyleFlags::FLOAT_FOCUSABLE)) )
+            if (m_nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)
             {
                 // sad but true: this can cause an XError, we need to catch that
                 // to do this we need to synchronize with the XServer
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index aff7aca..cc66428 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -1118,8 +1118,7 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
     m_nStyle = nStyle;
 
     GtkWindowType eWinType = (  (nStyle & SalFrameStyleFlags::FLOAT) &&
-                              ! (nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION|
-                                           SalFrameStyleFlags::FLOAT_FOCUSABLE))
+                              ! (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)
                               )
         ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL;
 
@@ -1164,7 +1163,7 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
     bool bDecoHandling =
         ! isChild() &&
         ( ! (nStyle & SalFrameStyleFlags::FLOAT) ||
-          (nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION|SalFrameStyleFlags::FLOAT_FOCUSABLE) ) );
+          (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) );
 
     if( bDecoHandling )
     {
@@ -1187,10 +1186,6 @@ void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
             gtk_window_set_accept_focus(GTK_WINDOW(m_pWindow), false);
             gtk_window_set_decorated(GTK_WINDOW(m_pWindow), false);
         }
-        else if( (nStyle & SalFrameStyleFlags::FLOAT_FOCUSABLE) )
-        {
-            eType = GDK_WINDOW_TYPE_HINT_UTILITY;
-        }
         gtk_window_set_type_hint( GTK_WINDOW(m_pWindow), eType );
         gtk_window_set_gravity( GTK_WINDOW(m_pWindow), GDK_GRAVITY_STATIC );
     }
diff --git a/vcl/win/source/window/salframe.cxx b/vcl/win/source/window/salframe.cxx
index 4b873a9..fa53572 100644
--- a/vcl/win/source/window/salframe.cxx
+++ b/vcl/win/source/window/salframe.cxx
@@ -371,11 +371,11 @@ SalFrame* ImplSalCreateFrame( WinSalInstance* pInst,
         nExSysStyle |= WS_EX_TOOLWINDOW;
         pFrame->mbFloatWin = TRUE;
 
-        if ( (pEnvTransparentFloats /* does not work remote! || (nSalFrameStyle & SalFrameStyleFlags::FLOAT_FOCUSABLE) */ )  )
+        if (pEnvTransparentFloats)
             nExSysStyle |= WS_EX_LAYERED;
 
     }
-    if( (nSalFrameStyle & SalFrameStyleFlags::TOOLTIP) || (nSalFrameStyle & SalFrameStyleFlags::FLOAT_FOCUSABLE) )
+    if (nSalFrameStyle & SalFrameStyleFlags::TOOLTIP)
         nExSysStyle |= WS_EX_TOPMOST;
 
     // init frame data
commit 3aa8c1663da6315878cf0c58ef9c19d13e2f8b06
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Dec 9 09:53:37 2015 +0000

    sort SalFrameStyleFlags
    
    Change-Id: I2caeda4e0a0b98ad09389d08fd6ccc6bb1e7aec2
    (cherry picked from commit e21a2e7a01b7d6d63038a06b6e55d8bc5ec95aa8)

diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
index 4184971..dacf3fa 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -70,20 +70,20 @@ enum class SalFrameStyleFlags
     OWNERDRAWDECORATION = 0x00000040,
     // dialogs
     DIALOG              = 0x00000080,
+    // the window containing the intro bitmap, aka splashscreen
+    INTRO               = 0x00000100,
     // partial fullscreen: fullscreen on one monitor of a multimonitor display
     PARTIAL_FULLSCREEN  = 0x00800000,
-    // plugged system child window
-    PLUG                = 0x10000000,
+    // floating window that needs to be focusable
+    FLOAT_FOCUSABLE     = 0x04000000,
     // system child window inside another SalFrame
     SYSTEMCHILD         = 0x08000000,
+    // plugged system child window
+    PLUG                = 0x10000000,
     // floating window
     FLOAT               = 0x20000000,
-    // floating window that needs to be focusable
-    FLOAT_FOCUSABLE     = 0x04000000,
     // toolwindows should be painted with a smaller decoration
     TOOLWINDOW          = 0x40000000,
-    // the window containing the intro bitmap, aka splashscreen
-    INTRO               = 0x00000100,
 };
 namespace o3tl {
     template<> struct typed_flags<SalFrameStyleFlags> : is_typed_flags<SalFrameStyleFlags, 0x7c8001ff> {};
commit 3324d9d93290339bba8660ed4ea57891c688c020
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Dec 16 21:26:15 2015 +0000

    impress's AnnotationWindow is the only user of WB_NEEDSFOCUS
    
    Here it is creating a toplevel floating system window which needs special
    hackery to function.
    
    Instead convert it to a non-system window which means that it is in reality
    only a vcl construct. The small downside is that it is now unable to leave the
    confines of the toplevel system window in which it lives. Upside is that
    all the special hackery related to it which generally doesn't work half the time
    in various window managers and now in wayland can go away.
    
    Change-Id: I7ad7c35091086f7671ff4a178c7fa04202c20e09
    Reviewed-on: https://gerrit.libreoffice.org/20745
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 3d3e95d68557e93224ebdf75a2ac56acf42e7d44)

diff --git a/sd/source/ui/annotations/annotationwindow.cxx b/sd/source/ui/annotations/annotationwindow.cxx
index eecc0e3..dcbeb22 100644
--- a/sd/source/ui/annotations/annotationwindow.cxx
+++ b/sd/source/ui/annotations/annotationwindow.cxx
@@ -272,7 +272,7 @@ Selection AnnotationTextWindow::GetSurroundingTextSelection() const
 /************** AnnotationWindow***********************************++*/
 
 AnnotationWindow::AnnotationWindow( AnnotationManagerImpl& rManager, DrawDocShell* pDocShell, vcl::Window* pParent )
-: FloatingWindow(pParent, WB_SYSTEMWINDOW|WB_BORDER|WB_NEEDSFOCUS)
+: FloatingWindow(pParent, WB_BORDER)
 , mrManager( rManager )
 , mpDocShell( pDocShell )
 , mpDoc( pDocShell->GetDoc() )
@@ -285,6 +285,7 @@ AnnotationWindow::AnnotationWindow( AnnotationManagerImpl& rManager, DrawDocShel
 , mpTextWindow(nullptr)
 , mpMeta(nullptr)
 {
+    EnableAlwaysOnTop();
 }
 
 AnnotationWindow::~AnnotationWindow()
commit 8cba787ed8d569b34da59b2ca001a6525c15e7ba
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Dec 14 14:10:11 2015 +0000

    Resolves: rhbz#1289394 gtk3: implement tooltips natively
    
    side step the whole pile of misery by using native gtk tooltips
    
    also gets transparency and native themeing too by default
    
    Change-Id: I59552661cd9dc18a563341885bc40fcdadc5264f
    (cherry picked from commit c96eeb5bf2ef428e7d147258d69825ff97acb226)

diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
index 72e61e4..4184971 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -244,6 +244,13 @@ public:
     {
     }
 
+    // return true to indicate tooltips are shown natively, false otherwise
+    virtual bool            ShowTooltip(const OUString& /*rHelpText*/, const Rectangle& /*rHelpArea*/ )
+    {
+        return false;
+    }
+
+
     // Callbacks (indepent part in vcl/source/window/winproc.cxx)
     // for default message handling return 0
     void                    SetCallback( vcl::Window* pWindow, SALFRAMEPROC pProc );
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 96c28bf..5c59dc8 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -199,6 +199,8 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
     Rectangle                       m_aRestorePosSize;
 
 #if GTK_CHECK_VERSION(3,0,0)
+    OUString                        m_aTooltip;
+    Rectangle                       m_aHelpArea;
     guint32                         m_nLastScrollEventTime;
     long                            m_nWidthRequest;
     long                            m_nHeightRequest;
@@ -231,6 +233,9 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
 #if GTK_CHECK_VERSION(3,0,0)
     static gboolean     signalDraw( GtkWidget*, cairo_t *cr, gpointer );
     static void         sizeAllocated(GtkWidget*, GdkRectangle *pAllocation, gpointer frame);
+    static gboolean     signalTooltipQuery(GtkWidget*, gint x, gint y,
+                                     gboolean keyboard_mode, GtkTooltip *tooltip,
+                                     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);
@@ -452,6 +457,7 @@ public:
 
 #if GTK_CHECK_VERSION(3,0,0)
     virtual void                SetModal(bool bModal) override;
+    virtual bool                ShowTooltip(const OUString& rHelpText, const Rectangle& rHelpArea) override;
 #endif
 
     static GtkSalFrame         *getFromWindow( GtkWindow *pWindow );
diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx
index 51a9e31f..19570ce 100644
--- a/vcl/source/app/help.cxx
+++ b/vcl/source/app/help.cxx
@@ -31,6 +31,7 @@
 #include "vcl/settings.hxx"
 
 #include "helpwin.hxx"
+#include "salframe.hxx"
 #include "svdata.hxx"
 
 #define HELPWINSTYLE_QUICK      0
@@ -462,6 +463,12 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
                          const OUString& rHelpText, const OUString& rStatusText,
                          const Point& rScreenPos, const Rectangle& rHelpArea )
 {
+    if (pParent->ImplGetFrame()->ShowTooltip(rHelpText, rHelpArea))
+    {
+        //tooltips are handled natively, return early
+        return;
+    }
+
     ImplSVData* pSVData = ImplGetSVData();
 
     if (rHelpText.isEmpty() && !pSVData->maHelpData.mbRequestingHelp)
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index aace8b3..aff7aca 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -980,6 +980,8 @@ void GtkSalFrame::InitCommon()
 
     // connect signals
     g_signal_connect( G_OBJECT(m_pWindow), "style-set", G_CALLBACK(signalStyleSet), this );
+    gtk_widget_set_has_tooltip(pEventWidget, true);
+    m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "query-tooltip", G_CALLBACK(signalTooltipQuery), this ));
     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 ));
@@ -2386,6 +2388,32 @@ void GtkSalFrame::SetModal(bool bModal)
     }
 }
 
+gboolean GtkSalFrame::signalTooltipQuery(GtkWidget*, gint /*x*/, gint /*y*/,
+                                     gboolean /*keyboard_mode*/, GtkTooltip *tooltip,
+                                     gpointer frame)
+{
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
+    if (pThis->m_aTooltip.isEmpty())
+        return false;
+    gtk_tooltip_set_text(tooltip,
+        OUStringToOString(pThis->m_aTooltip, RTL_TEXTENCODING_UTF8).getStr());
+    GdkRectangle aHelpArea;
+    aHelpArea.x = pThis->m_aHelpArea.Left();
+    aHelpArea.y = pThis->m_aHelpArea.Top();
+    aHelpArea.width = pThis->m_aHelpArea.GetWidth();
+    aHelpArea.height = pThis->m_aHelpArea.GetHeight();
+    gtk_tooltip_set_tip_area(tooltip, &aHelpArea);
+    return true;
+}
+
+bool GtkSalFrame::ShowTooltip(const OUString& rHelpText, const Rectangle& rHelpArea)
+{
+    m_aTooltip = rHelpText;
+    m_aHelpArea = rHelpArea;
+    gtk_widget_trigger_tooltip_query(getMouseEventWidget());
+    return true;
+}
+
 gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer frame )
 {
     GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
diff --git a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
index e0cc8d5..a28938e 100644
--- a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
@@ -1812,9 +1812,6 @@ bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nP
 {
     switch(nType)
     {
-        case CTRL_TOOLTIP:
-            return false;   //shaped, punt that problem for now
-
         case CTRL_PUSHBUTTON:
         case CTRL_RADIOBUTTON:
         case CTRL_CHECKBOX:
commit 77e21efcdde2589a56c029c663cd75e105edd1fd
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Dec 14 14:05:53 2015 +0000

    Related: rhbz#1289394 always provide the screen area the tip applies to
    
    this will make it easier to implement native help tips
    
    Change-Id: I984dfadaf02e9b7bf542ba82cf070911c89cb699
    (cherry picked from commit 01ef12d173fb2c54a49186c8eb4fa40288b82945)

diff --git a/cui/source/customize/acccfg.cxx b/cui/source/customize/acccfg.cxx
index 2d42b3c..ee07d7e 100644
--- a/cui/source/customize/acccfg.cxx
+++ b/cui/source/customize/acccfg.cxx
@@ -1108,7 +1108,7 @@ IMPL_LINK_NOARG_TYPED(SfxAcceleratorConfigPage, RemoveHdl, Button*, void)
 IMPL_LINK_TYPED( SfxAcceleratorConfigPage, SelectHdl, SvTreeListBox*, pListBox, void )
 {
     // disable help
-    Help::ShowBalloon( this, Point(), OUString() );
+    Help::ShowBalloon( this, Point(), Rectangle(), OUString() );
     if (pListBox == m_pEntriesBox)
     {
         sal_uLong nPos = SvTreeList::GetRelPos( m_pEntriesBox->FirstSelected() );
diff --git a/cui/source/customize/selector.cxx b/cui/source/customize/selector.cxx
index 7f4c65e..28fbd87 100644
--- a/cui/source/customize/selector.cxx
+++ b/cui/source/customize/selector.cxx
@@ -131,7 +131,8 @@ void SvxConfigFunctionListBox::MouseMove( const MouseEvent& rMEvt )
         aTimer.Start();
     else
     {
-        Help::ShowBalloon( this, aMousePos, OUString() );
+        Rectangle aRect(GetPosPixel(), GetSizePixel());
+        Help::ShowBalloon( this, aMousePos, aRect, OUString() );
         aTimer.Stop();
     }
 }
@@ -143,7 +144,10 @@ IMPL_LINK_NOARG_TYPED(SvxConfigFunctionListBox, TimerHdl, Timer *, void)
     Point aMousePos = GetPointerPosPixel();
     SvTreeListEntry *pEntry = GetCurEntry();
     if ( pEntry && GetEntry( aMousePos ) == pEntry && pCurEntry == pEntry )
-        Help::ShowBalloon( this, OutputToScreenPixel( aMousePos ), GetHelpText( pEntry ) );
+    {
+        Rectangle aRect(GetPosPixel(), GetSizePixel());
+        Help::ShowBalloon( this, OutputToScreenPixel(aMousePos), aRect, GetHelpText( pEntry ) );
+    }
 }
 
 void SvxConfigFunctionListBox::ClearAll()
@@ -178,7 +182,7 @@ OUString SvxConfigFunctionListBox::GetHelpText( SvTreeListEntry *pEntry )
 
 void SvxConfigFunctionListBox::FunctionSelected()
 {
-    Help::ShowBalloon( this, Point(), OUString() );
+    Help::ShowBalloon( this, Point(), Rectangle(), OUString() );
 }
 
 // drag and drop support
diff --git a/include/vcl/help.hxx b/include/vcl/help.hxx
index 40dfcf2..4d226a8 100644
--- a/include/vcl/help.hxx
+++ b/include/vcl/help.hxx
@@ -86,9 +86,6 @@ public:
     static bool         IsBalloonHelpEnabled();
     static bool         ShowBalloon( vcl::Window* pParent,
                                      const Point& rScreenPos,
-                                     const OUString& rHelpText );
-    static bool         ShowBalloon( vcl::Window* pParent,
-                                     const Point& rScreenPos,
                                      const Rectangle&,
                                      const OUString& rHelpText );
 
diff --git a/sfx2/source/dialog/dinfdlg.cxx b/sfx2/source/dialog/dinfdlg.cxx
index 0577ad4..bc3fa4b 100644
--- a/sfx2/source/dialog/dinfdlg.cxx
+++ b/sfx2/source/dialog/dinfdlg.cxx
@@ -1366,7 +1366,7 @@ void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt )
         Size aSize( GetSizePixel() );
         Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize );
         if (Help::IsBalloonHelpEnabled())
-            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), GetText() );
+            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aItemRect, GetText() );
         else
             Help::ShowQuickHelp( this, aItemRect, GetText(),
                 QuickHelpFlags::Left|QuickHelpFlags::VCenter );
diff --git a/sw/source/core/draw/dpage.cxx b/sw/source/core/draw/dpage.cxx
index f8ad9f6..c8773e8 100644
--- a/sw/source/core/draw/dpage.cxx
+++ b/sw/source/core/draw/dpage.cxx
@@ -237,14 +237,14 @@ bool SwDPage::RequestHelp( vcl::Window* pWindow, SdrView* pView,
                         sText = SwViewShell::GetShellRes()->aLinkClick + ": " + sText;
                 }
 
+                // then display the help:
+                Rectangle aRect( rEvt.GetMousePosPixel(), Size(1,1) );
                 if( rEvt.GetMode() & HelpEventMode::BALLOON )
                 {
-                    Help::ShowBalloon( pWindow, rEvt.GetMousePosPixel(), sText );
+                    Help::ShowBalloon( pWindow, rEvt.GetMousePosPixel(), aRect, sText );
                 }
                 else
                 {
-                    // then display the help:
-                    Rectangle aRect( rEvt.GetMousePosPixel(), Size(1,1) );
                     Help::ShowQuickHelp( pWindow, aRect, sText );
                 }
                 bContinue = false;
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx
index ba05744..a15a681 100644
--- a/sw/source/uibase/docvw/edtwin2.cxx
+++ b/sw/source/uibase/docvw/edtwin2.cxx
@@ -364,18 +364,19 @@ void SwEditWin::RequestHelp(const HelpEvent &rEvt)
             }
             if (!sText.isEmpty())
             {
+                Rectangle aRect( aFieldRect.SVRect() );
+                Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
+                aRect.Left()   = aPt.X();
+                aRect.Top()    = aPt.Y();
+                aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
+                aRect.Right()  = aPt.X();
+                aRect.Bottom() = aPt.Y();
+
                 if( bBalloon )
-                    Help::ShowBalloon( this, rEvt.GetMousePosPixel(), sText );
+                    Help::ShowBalloon( this, rEvt.GetMousePosPixel(), aRect, sText );
                 else
                 {
                     // the show the help
-                    Rectangle aRect( aFieldRect.SVRect() );
-                    Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
-                    aRect.Left()   = aPt.X();
-                    aRect.Top()    = aPt.Y();
-                    aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
-                    aRect.Right()  = aPt.X();
-                    aRect.Bottom() = aPt.Y();
                     OUString sDisplayText(ClipLongToolTip(sText));
                     Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle);
                 }
diff --git a/vcl/inc/helpwin.hxx b/vcl/inc/helpwin.hxx
index e372962..cf35423 100644
--- a/vcl/inc/helpwin.hxx
+++ b/vcl/inc/helpwin.hxx
@@ -75,10 +75,10 @@ public:
 
 void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
         const OUString& rHelpText, const OUString& rStatusText,
-        const Point& rScreenPos, const Rectangle* pHelpArea = nullptr );
+        const Point& rScreenPos, const Rectangle& rHelpArea );
 void ImplDestroyHelpWindow( bool bUpdateHideTime );
 void ImplSetHelpWindowPos( vcl::Window* pHelpWindow, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
-                            const Point& rPos, const Rectangle* pHelpArea );
+                            const Point& rPos, const Rectangle& rHelpArea );
 
 #endif // INCLUDED_VCL_INC_HELPWIN_HXX
 
diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx
index 912607d..51a9e31f 100644
--- a/vcl/source/app/help.cxx
+++ b/vcl/source/app/help.cxx
@@ -147,21 +147,11 @@ bool Help::IsBalloonHelpEnabled()
 }
 
 bool Help::ShowBalloon( vcl::Window* pParent,
-                        const Point& rScreenPos,
-                        const OUString& rHelpText )
-{
-    ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
-                        rHelpText, OUString(), rScreenPos );
-
-    return true;
-}
-
-bool Help::ShowBalloon( vcl::Window* pParent,
                         const Point& rScreenPos, const Rectangle& rRect,
                         const OUString& rHelpText )
 {
     ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
-                        rHelpText, OUString(), rScreenPos, &rRect );
+                        rHelpText, OUString(), rScreenPos, rRect );
 
     return true;
 }
@@ -189,7 +179,7 @@ bool Help::ShowQuickHelp( vcl::Window* pParent,
 {
     ImplShowHelpWindow( pParent, HELPWINSTYLE_QUICK, nStyle,
                         rHelpText, rLongHelpText,
-                        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
+                        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), rScreenRect );
     return true;
 }
 
@@ -221,7 +211,7 @@ void Help::UpdateTip( sal_uIntPtr nId, vcl::Window* pParent, const Rectangle& rS
     Size aSz = pHelpWin->CalcOutSize();
     pHelpWin->SetOutputSizePixel( aSz );
     ImplSetHelpWindowPos( pHelpWin, pHelpWin->GetWinStyle(), pHelpWin->GetStyle(),
-        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
+        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), rScreenRect );
 
     pHelpWin->SetHelpText( rText );
     pHelpWin->Invalidate();
@@ -470,7 +460,7 @@ OUString HelpTextWindow::GetText() const
 
 void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
                          const OUString& rHelpText, const OUString& rStatusText,
-                         const Point& rScreenPos, const Rectangle* pHelpArea )
+                         const Point& rScreenPos, const Rectangle& rHelpArea )
 {
     ImplSVData* pSVData = ImplGetSVData();
 
@@ -485,9 +475,7 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
 
         if  (   (   ( pHelpWin->GetHelpText() != rHelpText )
                 ||  ( pHelpWin->GetWinStyle() != nHelpWinStyle )
-                ||  (   pHelpArea
-                    &&  ( pHelpWin->GetHelpArea() != *pHelpArea )
-                    )
+                ||  ( pHelpWin->GetHelpArea() != rHelpArea )
                 )
             &&  pSVData->maHelpData.mbRequestingHelp
             )
@@ -512,7 +500,7 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
 
                 pHelpWin->SetHelpText( rHelpText );
                 // approach mouse position
-                ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
+                ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, rHelpArea );
                 if( pHelpWin->IsVisible() )
                     pHelpWin->Invalidate();
             }
@@ -531,13 +519,12 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
         pHelpWin = VclPtr<HelpTextWindow>::Create( pParent, rHelpText, nHelpWinStyle, nStyle );
         pSVData->maHelpData.mpHelpWin = pHelpWin;
         pHelpWin->SetStatusText( rStatusText );
-        if ( pHelpArea )
-            pHelpWin->SetHelpArea( *pHelpArea );
+        pHelpWin->SetHelpArea( rHelpArea );
 
         //  positioning
         Size aSz = pHelpWin->CalcOutSize();
         pHelpWin->SetOutputSizePixel( aSz );
-        ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
+        ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, rHelpArea );
         // if not called from Window::RequestHelp, then without delay...
         if ( !pSVData->maHelpData.mbRequestingHelp )
             nDelayMode = HELPDELAY_NONE;
@@ -566,7 +553,7 @@ void ImplDestroyHelpWindow( bool bUpdateHideTime )
 }
 
 void ImplSetHelpWindowPos( vcl::Window* pHelpWin, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
-                           const Point& rPos, const Rectangle* pHelpArea )
+                           const Point& rPos, const Rectangle& rHelpArea )
 {
     Point       aPos = rPos;
     Size        aSz = pHelpWin->GetSizePixel();
@@ -601,26 +588,23 @@ void ImplSetHelpWindowPos( vcl::Window* pHelpWin, sal_uInt16 nHelpWinStyle, Quic
 
     if ( nStyle & QuickHelpFlags::NoAutoPos )
     {
-        if ( pHelpArea )
-        {
-            // convert help area to screen coords
-            Rectangle devHelpArea(
-                pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->TopLeft() ),
-                pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->BottomRight() ) );
-
-            // Welche Position vom Rechteck?
-            aPos = devHelpArea.Center();
-
-            if ( nStyle & QuickHelpFlags::Left )
-                aPos.X() = devHelpArea.Left();
-            else if ( nStyle & QuickHelpFlags::Right )
-                aPos.X() = devHelpArea.Right();
-
-            if ( nStyle & QuickHelpFlags::Top )
-                aPos.Y() = devHelpArea.Top();
-            else if ( nStyle & QuickHelpFlags::Bottom )
-                aPos.Y() = devHelpArea.Bottom();
-        }
+        // convert help area to screen coords
+        Rectangle devHelpArea(
+            pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( rHelpArea.TopLeft() ),
+            pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( rHelpArea.BottomRight() ) );
+
+        // Welche Position vom Rechteck?
+        aPos = devHelpArea.Center();
+
+        if ( nStyle & QuickHelpFlags::Left )
+            aPos.X() = devHelpArea.Left();
+        else if ( nStyle & QuickHelpFlags::Right )
+            aPos.X() = devHelpArea.Right();
+
+        if ( nStyle & QuickHelpFlags::Top )
+            aPos.Y() = devHelpArea.Top();
+        else if ( nStyle & QuickHelpFlags::Bottom )
+            aPos.Y() = devHelpArea.Bottom();
 
         // which direction?
         if ( nStyle & QuickHelpFlags::Left )
diff --git a/vcl/source/window/menuwindow.cxx b/vcl/source/window/menuwindow.cxx
index 72a1bae..83ca0b6 100644
--- a/vcl/source/window/menuwindow.cxx
+++ b/vcl/source/window/menuwindow.cxx
@@ -63,7 +63,7 @@ bool MenuWindow::ImplHandleHelpEvent(vcl::Window* pMenuWindow, Menu* pMenu, sal_
 
         Rectangle aRect( aPos, Size() );
         if (!pMenu->GetHelpText(nId).isEmpty())
-            Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
+            Help::ShowBalloon( pMenuWindow, aPos, aRect, pMenu->GetHelpText( nId ) );
         else
         {
             // give user a chance to read the full filename
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index a064650..d1b5bc1 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -2007,7 +2007,14 @@ void Window::RequestHelp( const HelpEvent& rHEvt )
         if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
             ImplGetParent()->RequestHelp( rHEvt );
         else
-            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), rStr );
+        {
+            Point aPos = GetPosPixel();
+            if ( ImplGetParent() && !ImplIsOverlapWindow() )
+                aPos = ImplGetParent()->OutputToScreenPixel( aPos );
+            Rectangle   aRect( aPos, GetSizePixel() );
+
+            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
+        }
     }
     else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
     {


More information about the Libreoffice-commits mailing list