Blame 0001-Resolves-rhbz-1289394-gtk3-implement-tooltips-native.patch

824672b
From 420af7714706fe4199388879c0b749d19d1bbc15 Mon Sep 17 00:00:00 2001
824672b
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
824672b
Date: Mon, 14 Dec 2015 14:05:53 +0000
824672b
Subject: [PATCH] Resolves: rhbz#1289394 gtk3: implement tooltips natively
824672b
824672b
side step the whole pile of misery by using native gtk tooltips
824672b
824672b
also gets transparency and native themeing too by default
824672b
824672b
Related: rhbz#1289394 always provide the screen area the tip applies to
824672b
824672b
this will make it easier to implement native help tips
824672b
824672b
Change-Id: I984dfadaf02e9b7bf542ba82cf070911c89cb699
824672b
(cherry picked from commit 01ef12d173fb2c54a49186c8eb4fa40288b82945)
824672b
824672b
Change-Id: I59552661cd9dc18a563341885bc40fcdadc5264f
824672b
(cherry picked from commit c96eeb5bf2ef428e7d147258d69825ff97acb226)
824672b
---
824672b
 cui/source/customize/acccfg.cxx           |  2 +-
824672b
 cui/source/customize/selector.cxx         | 10 +++--
824672b
 include/vcl/help.hxx                      |  3 --
824672b
 sfx2/source/dialog/dinfdlg.cxx            |  2 +-
824672b
 sw/source/core/draw/dpage.cxx             |  6 +--
824672b
 sw/source/uibase/docvw/edtwin2.cxx        | 17 +++----
824672b
 vcl/inc/helpwin.hxx                       |  4 +-
824672b
 vcl/inc/salframe.hxx                      |  7 +++
824672b
 vcl/inc/unx/gtk/gtkframe.hxx              |  6 +++
824672b
 vcl/source/app/help.cxx                   | 75 ++++++++++++++-----------------
824672b
 vcl/source/window/menuwindow.cxx          |  2 +-
824672b
 vcl/source/window/window.cxx              |  9 +++-
824672b
 vcl/unx/gtk3/gtk3gtkframe.cxx             | 28 ++++++++++++
824672b
 vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx |  3 --
824672b
 14 files changed, 106 insertions(+), 68 deletions(-)
824672b
824672b
diff --git a/cui/source/customize/acccfg.cxx b/cui/source/customize/acccfg.cxx
824672b
index 2d42b3c..ee07d7e 100644
824672b
--- a/cui/source/customize/acccfg.cxx
824672b
+++ b/cui/source/customize/acccfg.cxx
824672b
@@ -1108,7 +1108,7 @@ IMPL_LINK_NOARG_TYPED(SfxAcceleratorConfigPage, RemoveHdl, Button*, void)
824672b
 IMPL_LINK_TYPED( SfxAcceleratorConfigPage, SelectHdl, SvTreeListBox*, pListBox, void )
824672b
 {
824672b
     // disable help
824672b
-    Help::ShowBalloon( this, Point(), OUString() );
824672b
+    Help::ShowBalloon( this, Point(), Rectangle(), OUString() );
824672b
     if (pListBox == m_pEntriesBox)
824672b
     {
824672b
         sal_uLong nPos = SvTreeList::GetRelPos( m_pEntriesBox->FirstSelected() );
824672b
diff --git a/cui/source/customize/selector.cxx b/cui/source/customize/selector.cxx
824672b
index 7f4c65e..28fbd87 100644
824672b
--- a/cui/source/customize/selector.cxx
824672b
+++ b/cui/source/customize/selector.cxx
824672b
@@ -131,7 +131,8 @@ void SvxConfigFunctionListBox::MouseMove( const MouseEvent& rMEvt )
824672b
         aTimer.Start();
824672b
     else
824672b
     {
824672b
-        Help::ShowBalloon( this, aMousePos, OUString() );
824672b
+        Rectangle aRect(GetPosPixel(), GetSizePixel());
824672b
+        Help::ShowBalloon( this, aMousePos, aRect, OUString() );
824672b
         aTimer.Stop();
824672b
     }
824672b
 }
824672b
@@ -143,7 +144,10 @@ IMPL_LINK_NOARG_TYPED(SvxConfigFunctionListBox, TimerHdl, Timer *, void)
824672b
     Point aMousePos = GetPointerPosPixel();
824672b
     SvTreeListEntry *pEntry = GetCurEntry();
824672b
     if ( pEntry && GetEntry( aMousePos ) == pEntry && pCurEntry == pEntry )
824672b
-        Help::ShowBalloon( this, OutputToScreenPixel( aMousePos ), GetHelpText( pEntry ) );
824672b
+    {
824672b
+        Rectangle aRect(GetPosPixel(), GetSizePixel());
824672b
+        Help::ShowBalloon( this, OutputToScreenPixel(aMousePos), aRect, GetHelpText( pEntry ) );
824672b
+    }
824672b
 }
824672b
 
824672b
 void SvxConfigFunctionListBox::ClearAll()
824672b
@@ -178,7 +182,7 @@ OUString SvxConfigFunctionListBox::GetHelpText( SvTreeListEntry *pEntry )
824672b
 
824672b
 void SvxConfigFunctionListBox::FunctionSelected()
824672b
 {
824672b
-    Help::ShowBalloon( this, Point(), OUString() );
824672b
+    Help::ShowBalloon( this, Point(), Rectangle(), OUString() );
824672b
 }
824672b
 
824672b
 // drag and drop support
824672b
diff --git a/include/vcl/help.hxx b/include/vcl/help.hxx
824672b
index 40dfcf2..4d226a8 100644
824672b
--- a/include/vcl/help.hxx
824672b
+++ b/include/vcl/help.hxx
824672b
@@ -86,9 +86,6 @@ public:
824672b
     static bool         IsBalloonHelpEnabled();
824672b
     static bool         ShowBalloon( vcl::Window* pParent,
824672b
                                      const Point& rScreenPos,
824672b
-                                     const OUString& rHelpText );
824672b
-    static bool         ShowBalloon( vcl::Window* pParent,
824672b
-                                     const Point& rScreenPos,
824672b
                                      const Rectangle&,
824672b
                                      const OUString& rHelpText );
824672b
 
824672b
diff --git a/sfx2/source/dialog/dinfdlg.cxx b/sfx2/source/dialog/dinfdlg.cxx
824672b
index 0577ad4..bc3fa4b 100644
824672b
--- a/sfx2/source/dialog/dinfdlg.cxx
824672b
+++ b/sfx2/source/dialog/dinfdlg.cxx
824672b
@@ -1366,7 +1366,7 @@ void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt )
824672b
         Size aSize( GetSizePixel() );
824672b
         Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize );
824672b
         if (Help::IsBalloonHelpEnabled())
824672b
-            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), GetText() );
824672b
+            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aItemRect, GetText() );
824672b
         else
824672b
             Help::ShowQuickHelp( this, aItemRect, GetText(),
824672b
                 QuickHelpFlags::Left|QuickHelpFlags::VCenter );
824672b
diff --git a/sw/source/core/draw/dpage.cxx b/sw/source/core/draw/dpage.cxx
824672b
index f8ad9f6..c8773e8 100644
824672b
--- a/sw/source/core/draw/dpage.cxx
824672b
+++ b/sw/source/core/draw/dpage.cxx
824672b
@@ -237,14 +237,14 @@ bool SwDPage::RequestHelp( vcl::Window* pWindow, SdrView* pView,
824672b
                         sText = SwViewShell::GetShellRes()->aLinkClick + ": " + sText;
824672b
                 }
824672b
 
824672b
+                // then display the help:
824672b
+                Rectangle aRect( rEvt.GetMousePosPixel(), Size(1,1) );
824672b
                 if( rEvt.GetMode() & HelpEventMode::BALLOON )
824672b
                 {
824672b
-                    Help::ShowBalloon( pWindow, rEvt.GetMousePosPixel(), sText );
824672b
+                    Help::ShowBalloon( pWindow, rEvt.GetMousePosPixel(), aRect, sText );
824672b
                 }
824672b
                 else
824672b
                 {
824672b
-                    // then display the help:
824672b
-                    Rectangle aRect( rEvt.GetMousePosPixel(), Size(1,1) );
824672b
                     Help::ShowQuickHelp( pWindow, aRect, sText );
824672b
                 }
824672b
                 bContinue = false;
824672b
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx
824672b
index ba05744..a15a681 100644
824672b
--- a/sw/source/uibase/docvw/edtwin2.cxx
824672b
+++ b/sw/source/uibase/docvw/edtwin2.cxx
824672b
@@ -364,18 +364,19 @@ void SwEditWin::RequestHelp(const HelpEvent &rEvt)
824672b
             }
824672b
             if (!sText.isEmpty())
824672b
             {
824672b
+                Rectangle aRect( aFieldRect.SVRect() );
824672b
+                Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
824672b
+                aRect.Left()   = aPt.X();
824672b
+                aRect.Top()    = aPt.Y();
824672b
+                aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
824672b
+                aRect.Right()  = aPt.X();
824672b
+                aRect.Bottom() = aPt.Y();
824672b
+
824672b
                 if( bBalloon )
824672b
-                    Help::ShowBalloon( this, rEvt.GetMousePosPixel(), sText );
824672b
+                    Help::ShowBalloon( this, rEvt.GetMousePosPixel(), aRect, sText );
824672b
                 else
824672b
                 {
824672b
                     // the show the help
824672b
-                    Rectangle aRect( aFieldRect.SVRect() );
824672b
-                    Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
824672b
-                    aRect.Left()   = aPt.X();
824672b
-                    aRect.Top()    = aPt.Y();
824672b
-                    aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
824672b
-                    aRect.Right()  = aPt.X();
824672b
-                    aRect.Bottom() = aPt.Y();
824672b
                     OUString sDisplayText(ClipLongToolTip(sText));
824672b
                     Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle);
824672b
                 }
824672b
diff --git a/vcl/inc/helpwin.hxx b/vcl/inc/helpwin.hxx
824672b
index e372962..cf35423 100644
824672b
--- a/vcl/inc/helpwin.hxx
824672b
+++ b/vcl/inc/helpwin.hxx
824672b
@@ -75,10 +75,10 @@ public:
824672b
 
824672b
 void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
824672b
         const OUString& rHelpText, const OUString& rStatusText,
824672b
-        const Point& rScreenPos, const Rectangle* pHelpArea = nullptr );
824672b
+        const Point& rScreenPos, const Rectangle& rHelpArea );
824672b
 void ImplDestroyHelpWindow( bool bUpdateHideTime );
824672b
 void ImplSetHelpWindowPos( vcl::Window* pHelpWindow, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
824672b
-                            const Point& rPos, const Rectangle* pHelpArea );
824672b
+                            const Point& rPos, const Rectangle& rHelpArea );
824672b
 
824672b
 #endif // INCLUDED_VCL_INC_HELPWIN_HXX
824672b
 
824672b
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
824672b
index a9c11e4..4c7a1bd 100644
824672b
--- a/vcl/inc/salframe.hxx
824672b
+++ b/vcl/inc/salframe.hxx
824672b
@@ -243,6 +243,13 @@ public:
824672b
     {
824672b
     }
824672b
 
824672b
+    // return true to indicate tooltips are shown natively, false otherwise
824672b
+    virtual bool            ShowTooltip(const OUString& /*rHelpText*/, const Rectangle& /*rHelpArea*/ )
824672b
+    {
824672b
+        return false;
824672b
+    }
824672b
+
824672b
+
824672b
     // Callbacks (indepent part in vcl/source/window/winproc.cxx)
824672b
     // for default message handling return 0
824672b
     void                    SetCallback( vcl::Window* pWindow, SALFRAMEPROC pProc );
824672b
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
824672b
index dc5cd19..ba6eded 100644
824672b
--- a/vcl/inc/unx/gtk/gtkframe.hxx
824672b
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
824672b
@@ -199,6 +199,8 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
824672b
     Rectangle                       m_aRestorePosSize;
824672b
 
824672b
 #if GTK_CHECK_VERSION(3,0,0)
824672b
+    OUString                        m_aTooltip;
824672b
+    Rectangle                       m_aHelpArea;
824672b
     guint32                         m_nLastScrollEventTime;
824672b
     long                            m_nWidthRequest;
824672b
     long                            m_nHeightRequest;
824672b
@@ -231,6 +233,9 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
824672b
 #if GTK_CHECK_VERSION(3,0,0)
824672b
     static gboolean     signalDraw( GtkWidget*, cairo_t *cr, gpointer );
824672b
     static void         sizeAllocated(GtkWidget*, GdkRectangle *pAllocation, gpointer frame);
824672b
+    static gboolean     signalTooltipQuery(GtkWidget*, gint x, gint y,
824672b
+                                     gboolean keyboard_mode, GtkTooltip *tooltip,
824672b
+                                     gpointer frame);
824672b
 #if GTK_CHECK_VERSION(3,14,0)
824672b
     static void         gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame);
824672b
     static void         gestureLongPress(GtkGestureLongPress* gesture, gpointer frame);
824672b
@@ -449,6 +454,7 @@ public:
824672b
 
824672b
 #if GTK_CHECK_VERSION(3,0,0)
824672b
     virtual void                SetModal(bool bModal) override;
824672b
+    virtual bool                ShowTooltip(const OUString& rHelpText, const Rectangle& rHelpArea) override;
824672b
 #endif
824672b
 
824672b
     static GtkSalFrame         *getFromWindow( GtkWindow *pWindow );
824672b
diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx
824672b
index 912607d..19570ce 100644
824672b
--- a/vcl/source/app/help.cxx
824672b
+++ b/vcl/source/app/help.cxx
824672b
@@ -31,6 +31,7 @@
824672b
 #include "vcl/settings.hxx"
824672b
 
824672b
 #include "helpwin.hxx"
824672b
+#include "salframe.hxx"
824672b
 #include "svdata.hxx"
824672b
 
824672b
 #define HELPWINSTYLE_QUICK      0
824672b
@@ -147,21 +148,11 @@ bool Help::IsBalloonHelpEnabled()
824672b
 }
824672b
 
824672b
 bool Help::ShowBalloon( vcl::Window* pParent,
824672b
-                        const Point& rScreenPos,
824672b
-                        const OUString& rHelpText )
824672b
-{
824672b
-    ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
824672b
-                        rHelpText, OUString(), rScreenPos );
824672b
-
824672b
-    return true;
824672b
-}
824672b
-
824672b
-bool Help::ShowBalloon( vcl::Window* pParent,
824672b
                         const Point& rScreenPos, const Rectangle& rRect,
824672b
                         const OUString& rHelpText )
824672b
 {
824672b
     ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
824672b
-                        rHelpText, OUString(), rScreenPos, &rRect );
824672b
+                        rHelpText, OUString(), rScreenPos, rRect );
824672b
 
824672b
     return true;
824672b
 }
824672b
@@ -189,7 +180,7 @@ bool Help::ShowQuickHelp( vcl::Window* pParent,
824672b
 {
824672b
     ImplShowHelpWindow( pParent, HELPWINSTYLE_QUICK, nStyle,
824672b
                         rHelpText, rLongHelpText,
824672b
-                        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
824672b
+                        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), rScreenRect );
824672b
     return true;
824672b
 }
824672b
 
824672b
@@ -221,7 +212,7 @@ void Help::UpdateTip( sal_uIntPtr nId, vcl::Window* pParent, const Rectangle& rS
824672b
     Size aSz = pHelpWin->CalcOutSize();
824672b
     pHelpWin->SetOutputSizePixel( aSz );
824672b
     ImplSetHelpWindowPos( pHelpWin, pHelpWin->GetWinStyle(), pHelpWin->GetStyle(),
824672b
-        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
824672b
+        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), rScreenRect );
824672b
 
824672b
     pHelpWin->SetHelpText( rText );
824672b
     pHelpWin->Invalidate();
824672b
@@ -470,8 +461,14 @@ OUString HelpTextWindow::GetText() const
824672b
 
824672b
 void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
824672b
                          const OUString& rHelpText, const OUString& rStatusText,
824672b
-                         const Point& rScreenPos, const Rectangle* pHelpArea )
824672b
+                         const Point& rScreenPos, const Rectangle& rHelpArea )
824672b
 {
824672b
+    if (pParent->ImplGetFrame()->ShowTooltip(rHelpText, rHelpArea))
824672b
+    {
824672b
+        //tooltips are handled natively, return early
824672b
+        return;
824672b
+    }
824672b
+
824672b
     ImplSVData* pSVData = ImplGetSVData();
824672b
 
824672b
     if (rHelpText.isEmpty() && !pSVData->maHelpData.mbRequestingHelp)
824672b
@@ -485,9 +482,7 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
824672b
 
824672b
         if  (   (   ( pHelpWin->GetHelpText() != rHelpText )
824672b
                 ||  ( pHelpWin->GetWinStyle() != nHelpWinStyle )
824672b
-                ||  (   pHelpArea
824672b
-                    &&  ( pHelpWin->GetHelpArea() != *pHelpArea )
824672b
-                    )
824672b
+                ||  ( pHelpWin->GetHelpArea() != rHelpArea )
824672b
                 )
824672b
             &&  pSVData->maHelpData.mbRequestingHelp
824672b
             )
824672b
@@ -512,7 +507,7 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
824672b
 
824672b
                 pHelpWin->SetHelpText( rHelpText );
824672b
                 // approach mouse position
824672b
-                ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
824672b
+                ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, rHelpArea );
824672b
                 if( pHelpWin->IsVisible() )
824672b
                     pHelpWin->Invalidate();
824672b
             }
824672b
@@ -531,13 +526,12 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
824672b
         pHelpWin = VclPtr<HelpTextWindow>::Create( pParent, rHelpText, nHelpWinStyle, nStyle );
824672b
         pSVData->maHelpData.mpHelpWin = pHelpWin;
824672b
         pHelpWin->SetStatusText( rStatusText );
824672b
-        if ( pHelpArea )
824672b
-            pHelpWin->SetHelpArea( *pHelpArea );
824672b
+        pHelpWin->SetHelpArea( rHelpArea );
824672b
 
824672b
         //  positioning
824672b
         Size aSz = pHelpWin->CalcOutSize();
824672b
         pHelpWin->SetOutputSizePixel( aSz );
824672b
-        ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
824672b
+        ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, rHelpArea );
824672b
         // if not called from Window::RequestHelp, then without delay...
824672b
         if ( !pSVData->maHelpData.mbRequestingHelp )
824672b
             nDelayMode = HELPDELAY_NONE;
824672b
@@ -566,7 +560,7 @@ void ImplDestroyHelpWindow( bool bUpdateHideTime )
824672b
 }
824672b
 
824672b
 void ImplSetHelpWindowPos( vcl::Window* pHelpWin, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
824672b
-                           const Point& rPos, const Rectangle* pHelpArea )
824672b
+                           const Point& rPos, const Rectangle& rHelpArea )
824672b
 {
824672b
     Point       aPos = rPos;
824672b
     Size        aSz = pHelpWin->GetSizePixel();
824672b
@@ -601,26 +595,23 @@ void ImplSetHelpWindowPos( vcl::Window* pHelpWin, sal_uInt16 nHelpWinStyle, Quic
824672b
 
824672b
     if ( nStyle & QuickHelpFlags::NoAutoPos )
824672b
     {
824672b
-        if ( pHelpArea )
824672b
-        {
824672b
-            // convert help area to screen coords
824672b
-            Rectangle devHelpArea(
824672b
-                pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->TopLeft() ),
824672b
-                pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->BottomRight() ) );
824672b
-
824672b
-            // Welche Position vom Rechteck?
824672b
-            aPos = devHelpArea.Center();
824672b
-
824672b
-            if ( nStyle & QuickHelpFlags::Left )
824672b
-                aPos.X() = devHelpArea.Left();
824672b
-            else if ( nStyle & QuickHelpFlags::Right )
824672b
-                aPos.X() = devHelpArea.Right();
824672b
-
824672b
-            if ( nStyle & QuickHelpFlags::Top )
824672b
-                aPos.Y() = devHelpArea.Top();
824672b
-            else if ( nStyle & QuickHelpFlags::Bottom )
824672b
-                aPos.Y() = devHelpArea.Bottom();
824672b
-        }
824672b
+        // convert help area to screen coords
824672b
+        Rectangle devHelpArea(
824672b
+            pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( rHelpArea.TopLeft() ),
824672b
+            pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( rHelpArea.BottomRight() ) );
824672b
+
824672b
+        // Welche Position vom Rechteck?
824672b
+        aPos = devHelpArea.Center();
824672b
+
824672b
+        if ( nStyle & QuickHelpFlags::Left )
824672b
+            aPos.X() = devHelpArea.Left();
824672b
+        else if ( nStyle & QuickHelpFlags::Right )
824672b
+            aPos.X() = devHelpArea.Right();
824672b
+
824672b
+        if ( nStyle & QuickHelpFlags::Top )
824672b
+            aPos.Y() = devHelpArea.Top();
824672b
+        else if ( nStyle & QuickHelpFlags::Bottom )
824672b
+            aPos.Y() = devHelpArea.Bottom();
824672b
 
824672b
         // which direction?
824672b
         if ( nStyle & QuickHelpFlags::Left )
824672b
diff --git a/vcl/source/window/menuwindow.cxx b/vcl/source/window/menuwindow.cxx
824672b
index 72a1bae..83ca0b6 100644
824672b
--- a/vcl/source/window/menuwindow.cxx
824672b
+++ b/vcl/source/window/menuwindow.cxx
824672b
@@ -63,7 +63,7 @@ bool MenuWindow::ImplHandleHelpEvent(vcl::Window* pMenuWindow, Menu* pMenu, sal_
824672b
 
824672b
         Rectangle aRect( aPos, Size() );
824672b
         if (!pMenu->GetHelpText(nId).isEmpty())
824672b
-            Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
824672b
+            Help::ShowBalloon( pMenuWindow, aPos, aRect, pMenu->GetHelpText( nId ) );
824672b
         else
824672b
         {
824672b
             // give user a chance to read the full filename
824672b
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
824672b
index 48be717..800c3f0 100644
824672b
--- a/vcl/source/window/window.cxx
824672b
+++ b/vcl/source/window/window.cxx
824672b
@@ -2007,7 +2007,14 @@ void Window::RequestHelp( const HelpEvent& rHEvt )
824672b
         if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
824672b
             ImplGetParent()->RequestHelp( rHEvt );
824672b
         else
824672b
-            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), rStr );
824672b
+        {
824672b
+            Point aPos = GetPosPixel();
824672b
+            if ( ImplGetParent() && !ImplIsOverlapWindow() )
824672b
+                aPos = ImplGetParent()->OutputToScreenPixel( aPos );
824672b
+            Rectangle   aRect( aPos, GetSizePixel() );
824672b
+
824672b
+            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
824672b
+        }
824672b
     }
824672b
     else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
824672b
     {
824672b
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
824672b
index 23393d0..c7ea97f 100644
824672b
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
824672b
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
824672b
@@ -972,6 +972,8 @@ void GtkSalFrame::InitCommon()
824672b
 
824672b
     // connect signals
824672b
     g_signal_connect( G_OBJECT(m_pWindow), "style-set", G_CALLBACK(signalStyleSet), this );
824672b
+    gtk_widget_set_has_tooltip(pEventWidget, true);
824672b
+    m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "query-tooltip", G_CALLBACK(signalTooltipQuery), this ));
824672b
     m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-press-event", G_CALLBACK(signalButton), this ));
824672b
     m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "motion-notify-event", G_CALLBACK(signalMotion), this ));
824672b
     m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-release-event", G_CALLBACK(signalButton), this ));
824672b
@@ -2350,6 +2352,32 @@ void GtkSalFrame::SetModal(bool bModal)
824672b
     gtk_window_set_modal(GTK_WINDOW(m_pWindow), bModal);
824672b
 }
824672b
 
824672b
+gboolean GtkSalFrame::signalTooltipQuery(GtkWidget*, gint /*x*/, gint /*y*/,
824672b
+                                     gboolean /*keyboard_mode*/, GtkTooltip *tooltip,
824672b
+                                     gpointer frame)
824672b
+{
824672b
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
824672b
+    if (pThis->m_aTooltip.isEmpty())
824672b
+        return false;
824672b
+    gtk_tooltip_set_text(tooltip,
824672b
+        OUStringToOString(pThis->m_aTooltip, RTL_TEXTENCODING_UTF8).getStr());
824672b
+    GdkRectangle aHelpArea;
824672b
+    aHelpArea.x = pThis->m_aHelpArea.Left();
824672b
+    aHelpArea.y = pThis->m_aHelpArea.Top();
824672b
+    aHelpArea.width = pThis->m_aHelpArea.GetWidth();
824672b
+    aHelpArea.height = pThis->m_aHelpArea.GetHeight();
824672b
+    gtk_tooltip_set_tip_area(tooltip, &aHelpArea);
824672b
+    return true;
824672b
+}
824672b
+
824672b
+bool GtkSalFrame::ShowTooltip(const OUString& rHelpText, const Rectangle& rHelpArea)
824672b
+{
824672b
+    m_aTooltip = rHelpText;
824672b
+    m_aHelpArea = rHelpArea;
824672b
+    gtk_widget_trigger_tooltip_query(getMouseEventWidget());
824672b
+    return true;
824672b
+}
824672b
+
824672b
 gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer frame )
824672b
 {
824672b
     GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
824672b
diff --git a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
824672b
index e0cc8d5..a28938e 100644
824672b
--- a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
824672b
+++ b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx
824672b
@@ -1812,9 +1812,6 @@ bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nP
824672b
 {
824672b
     switch(nType)
824672b
     {
824672b
-        case CTRL_TOOLTIP:
824672b
-            return false;   //shaped, punt that problem for now
824672b
-
824672b
         case CTRL_PUSHBUTTON:
824672b
         case CTRL_RADIOBUTTON:
824672b
         case CTRL_CHECKBOX:
824672b
-- 
824672b
2.5.0
824672b