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

a9add1
From ee49f01f73348c9e7c822212a7ed69ab2e916946 Mon Sep 17 00:00:00 2001
a9add1
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
a9add1
Date: Mon, 14 Dec 2015 14:05:53 +0000
a9add1
Subject: [PATCH] Resolves: rhbz#1289394 gtk3: implement tooltips natively
a9add1
a9add1
side step the whole pile of misery by using native gtk tooltips
a9add1
a9add1
also gets transparency and native themeing too by default
a9add1
a9add1
Related: rhbz#1289394 always provide the screen area the tip applies to
a9add1
a9add1
this will make it easier to implement native help tips
a9add1
a9add1
Change-Id: I984dfadaf02e9b7bf542ba82cf070911c89cb699
a9add1
(cherry picked from commit 01ef12d173fb2c54a49186c8eb4fa40288b82945)
a9add1
a9add1
Change-Id: I59552661cd9dc18a563341885bc40fcdadc5264f
a9add1
(cherry picked from commit c96eeb5bf2ef428e7d147258d69825ff97acb226)
a9add1
---
a9add1
 cui/source/customize/acccfg.cxx    |  2 +-
a9add1
 cui/source/customize/selector.cxx  | 10 +++--
a9add1
 include/vcl/help.hxx               |  3 --
a9add1
 sfx2/source/dialog/dinfdlg.cxx     |  2 +-
a9add1
 sw/source/core/draw/dpage.cxx      |  6 +--
a9add1
 sw/source/uibase/docvw/edtwin2.cxx | 17 +++++----
a9add1
 vcl/inc/helpwin.hxx                |  4 +-
a9add1
 vcl/inc/salframe.hxx               |  7 ++++
a9add1
 vcl/inc/unx/gtk/gtkframe.hxx       |  6 +++
a9add1
 vcl/source/app/help.cxx            | 75 +++++++++++++++++---------------------
a9add1
 vcl/source/window/menuwindow.cxx   |  2 +-
a9add1
 vcl/source/window/window.cxx       |  9 ++++-
a9add1
 vcl/unx/gtk3/gtk3gtkframe.cxx      | 28 ++++++++++++++
a9add1
 13 files changed, 106 insertions(+), 65 deletions(-)
a9add1
a9add1
diff --git a/cui/source/customize/acccfg.cxx b/cui/source/customize/acccfg.cxx
a9add1
index b3511e9..2125990 100644
a9add1
--- a/cui/source/customize/acccfg.cxx
a9add1
+++ b/cui/source/customize/acccfg.cxx
a9add1
@@ -1117,7 +1117,7 @@ IMPL_LINK_NOARG(SfxAcceleratorConfigPage, RemoveHdl)
a9add1
 IMPL_LINK( SfxAcceleratorConfigPage, SelectHdl, Control*, pListBox )
a9add1
 {
a9add1
     // disable help
a9add1
-    Help::ShowBalloon( this, Point(), OUString() );
a9add1
+    Help::ShowBalloon( this, Point(), Rectangle(), OUString() );
a9add1
     if (pListBox == m_pEntriesBox)
a9add1
     {
a9add1
         sal_uLong nPos = SvTreeList::GetRelPos( m_pEntriesBox->FirstSelected() );
a9add1
diff --git a/cui/source/customize/selector.cxx b/cui/source/customize/selector.cxx
a9add1
index 781ddbf..2da0b77 100644
a9add1
--- a/cui/source/customize/selector.cxx
a9add1
+++ b/cui/source/customize/selector.cxx
a9add1
@@ -130,7 +130,8 @@ void SvxConfigFunctionListBox::MouseMove( const MouseEvent& rMEvt )
a9add1
         aTimer.Start();
a9add1
     else
a9add1
     {
a9add1
-        Help::ShowBalloon( this, aMousePos, OUString() );
a9add1
+        Rectangle aRect(GetPosPixel(), GetSizePixel());
a9add1
+        Help::ShowBalloon( this, aMousePos, aRect, OUString() );
a9add1
         aTimer.Stop();
a9add1
     }
a9add1
 }
a9add1
@@ -142,7 +143,10 @@ IMPL_LINK_NOARG_TYPED(SvxConfigFunctionListBox, TimerHdl, Timer *, void)
a9add1
     Point aMousePos = GetPointerPosPixel();
a9add1
     SvTreeListEntry *pEntry = GetCurEntry();
a9add1
     if ( pEntry && GetEntry( aMousePos ) == pEntry && pCurEntry == pEntry )
a9add1
-        Help::ShowBalloon( this, OutputToScreenPixel( aMousePos ), GetHelpText( pEntry ) );
a9add1
+    {
a9add1
+        Rectangle aRect(GetPosPixel(), GetSizePixel());
a9add1
+        Help::ShowBalloon( this, OutputToScreenPixel(aMousePos), aRect, GetHelpText( pEntry ) );
a9add1
+    }
a9add1
 }
a9add1
 
a9add1
 void SvxConfigFunctionListBox::ClearAll()
a9add1
@@ -177,7 +181,7 @@ OUString SvxConfigFunctionListBox::GetHelpText( SvTreeListEntry *pEntry )
a9add1
 
a9add1
 void SvxConfigFunctionListBox::FunctionSelected()
a9add1
 {
a9add1
-    Help::ShowBalloon( this, Point(), OUString() );
a9add1
+    Help::ShowBalloon( this, Point(), Rectangle(), OUString() );
a9add1
 }
a9add1
 
a9add1
 // drag and drop support
a9add1
diff --git a/include/vcl/help.hxx b/include/vcl/help.hxx
a9add1
index 40dfcf2..4d226a8 100644
a9add1
--- a/include/vcl/help.hxx
a9add1
+++ b/include/vcl/help.hxx
a9add1
@@ -86,9 +86,6 @@ public:
a9add1
     static bool         IsBalloonHelpEnabled();
a9add1
     static bool         ShowBalloon( vcl::Window* pParent,
a9add1
                                      const Point& rScreenPos,
a9add1
-                                     const OUString& rHelpText );
a9add1
-    static bool         ShowBalloon( vcl::Window* pParent,
a9add1
-                                     const Point& rScreenPos,
a9add1
                                      const Rectangle&,
a9add1
                                      const OUString& rHelpText );
a9add1
 
a9add1
diff --git a/sfx2/source/dialog/dinfdlg.cxx b/sfx2/source/dialog/dinfdlg.cxx
a9add1
index 0e47101..56d4d98 100644
a9add1
--- a/sfx2/source/dialog/dinfdlg.cxx
a9add1
+++ b/sfx2/source/dialog/dinfdlg.cxx
a9add1
@@ -1336,7 +1336,7 @@ void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt )
a9add1
         Size aSize( GetSizePixel() );
a9add1
         Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize );
a9add1
         if (Help::IsBalloonHelpEnabled())
a9add1
-            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), GetText() );
a9add1
+            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aItemRect, GetText() );
a9add1
         else
a9add1
             Help::ShowQuickHelp( this, aItemRect, GetText(),
a9add1
                 QuickHelpFlags::Left|QuickHelpFlags::VCenter );
a9add1
diff --git a/sw/source/core/draw/dpage.cxx b/sw/source/core/draw/dpage.cxx
a9add1
index db5707c..e401512 100644
a9add1
--- a/sw/source/core/draw/dpage.cxx
a9add1
+++ b/sw/source/core/draw/dpage.cxx
a9add1
@@ -237,14 +237,14 @@ bool SwDPage::RequestHelp( vcl::Window* pWindow, SdrView* pView,
a9add1
                         sText = SwViewShell::GetShellRes()->aLinkClick + ": " + sText;
a9add1
                 }
a9add1
 
a9add1
+                // then display the help:
a9add1
+                Rectangle aRect( rEvt.GetMousePosPixel(), Size(1,1) );
a9add1
                 if( rEvt.GetMode() & HelpEventMode::BALLOON )
a9add1
                 {
a9add1
-                    Help::ShowBalloon( pWindow, rEvt.GetMousePosPixel(), sText );
a9add1
+                    Help::ShowBalloon( pWindow, rEvt.GetMousePosPixel(), aRect, sText );
a9add1
                 }
a9add1
                 else
a9add1
                 {
a9add1
-                    // then display the help:
a9add1
-                    Rectangle aRect( rEvt.GetMousePosPixel(), Size(1,1) );
a9add1
                     Help::ShowQuickHelp( pWindow, aRect, sText );
a9add1
                 }
a9add1
                 bContinue = false;
a9add1
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx
a9add1
index dd78039..a7d55b3 100644
a9add1
--- a/sw/source/uibase/docvw/edtwin2.cxx
a9add1
+++ b/sw/source/uibase/docvw/edtwin2.cxx
a9add1
@@ -365,18 +365,19 @@ void SwEditWin::RequestHelp(const HelpEvent &rEvt)
a9add1
             }
a9add1
             if (!sText.isEmpty())
a9add1
             {
a9add1
+                Rectangle aRect( aFieldRect.SVRect() );
a9add1
+                Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
a9add1
+                aRect.Left()   = aPt.X();
a9add1
+                aRect.Top()    = aPt.Y();
a9add1
+                aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
a9add1
+                aRect.Right()  = aPt.X();
a9add1
+                aRect.Bottom() = aPt.Y();
a9add1
+
a9add1
                 if( bBalloon )
a9add1
-                    Help::ShowBalloon( this, rEvt.GetMousePosPixel(), sText );
a9add1
+                    Help::ShowBalloon( this, rEvt.GetMousePosPixel(), aRect, sText );
a9add1
                 else
a9add1
                 {
a9add1
                     // the show the help
a9add1
-                    Rectangle aRect( aFieldRect.SVRect() );
a9add1
-                    Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
a9add1
-                    aRect.Left()   = aPt.X();
a9add1
-                    aRect.Top()    = aPt.Y();
a9add1
-                    aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() ));
a9add1
-                    aRect.Right()  = aPt.X();
a9add1
-                    aRect.Bottom() = aPt.Y();
a9add1
                     OUString sDisplayText(ClipLongToolTip(sText));
a9add1
                     Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle);
a9add1
                 }
a9add1
diff --git a/vcl/inc/helpwin.hxx b/vcl/inc/helpwin.hxx
a9add1
index 5889a4f..7ff4072 100644
a9add1
--- a/vcl/inc/helpwin.hxx
a9add1
+++ b/vcl/inc/helpwin.hxx
a9add1
@@ -78,10 +78,10 @@ public:
a9add1
 
a9add1
 void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
a9add1
         const OUString& rHelpText, const OUString& rStatusText,
a9add1
-        const Point& rScreenPos, const Rectangle* pHelpArea = NULL );
a9add1
+        const Point& rScreenPos, const Rectangle& rHelpArea );
a9add1
 void ImplDestroyHelpWindow( bool bUpdateHideTime );
a9add1
 void ImplSetHelpWindowPos( vcl::Window* pHelpWindow, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
a9add1
-                            const Point& rPos, const Rectangle* pHelpArea );
a9add1
+                            const Point& rPos, const Rectangle& rHelpArea );
a9add1
 
a9add1
 #endif // INCLUDED_VCL_INC_HELPWIN_HXX
a9add1
 
a9add1
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
a9add1
index 484504c..cfd401d 100644
a9add1
--- a/vcl/inc/salframe.hxx
a9add1
+++ b/vcl/inc/salframe.hxx
a9add1
@@ -237,6 +237,13 @@ public:
a9add1
     {
a9add1
     }
a9add1
 
a9add1
+    // return true to indicate tooltips are shown natively, false otherwise
a9add1
+    virtual bool            ShowTooltip(const OUString& /*rHelpText*/, const Rectangle& /*rHelpArea*/ )
a9add1
+    {
a9add1
+        return false;
a9add1
+    }
a9add1
+
a9add1
+
a9add1
     // Callbacks (indepent part in vcl/source/window/winproc.cxx)
a9add1
     // for default message handling return 0
a9add1
     void                    SetCallback( vcl::Window* pWindow, SALFRAMEPROC pProc );
a9add1
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
a9add1
index ee19e6c..b779d39 100644
a9add1
--- a/vcl/inc/unx/gtk/gtkframe.hxx
a9add1
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
a9add1
@@ -211,6 +211,8 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
a9add1
     Rectangle                       m_aRestorePosSize;
a9add1
 
a9add1
 #if GTK_CHECK_VERSION(3,0,0)
a9add1
+    OUString                        m_aTooltip;
a9add1
+    Rectangle                       m_aHelpArea;
a9add1
     guint32                         m_nLastScrollEventTime;
a9add1
     long                            m_nWidthRequest;
a9add1
     long                            m_nHeightRequest;
a9add1
@@ -243,6 +245,9 @@ class GtkSalFrame : public SalFrame, public X11WindowProvider
a9add1
 #if GTK_CHECK_VERSION(3,0,0)
a9add1
     static gboolean     signalDraw( GtkWidget*, cairo_t *cr, gpointer );
a9add1
     static void         sizeAllocated(GtkWidget*, GdkRectangle *pAllocation, gpointer frame);
a9add1
+    static gboolean     signalTooltipQuery(GtkWidget*, gint x, gint y,
a9add1
+                                     gboolean keyboard_mode, GtkTooltip *tooltip,
a9add1
+                                     gpointer frame);
a9add1
 #if GTK_CHECK_VERSION(3,14,0)
a9add1
     static void         gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame);
a9add1
     static void         gestureLongPress(GtkGestureLongPress* gesture, gpointer frame);
a9add1
@@ -467,6 +472,7 @@ public:
a9add1
 
a9add1
 #if GTK_CHECK_VERSION(3,0,0)
a9add1
     virtual void                SetModal(bool bModal) override;
a9add1
+    virtual bool                ShowTooltip(const OUString& rHelpText, const Rectangle& rHelpArea) override;
a9add1
 #endif
a9add1
 
a9add1
     static GtkSalFrame         *getFromWindow( GtkWindow *pWindow );
a9add1
diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx
a9add1
index 7014a79..9a6e845 100644
a9add1
--- a/vcl/source/app/help.cxx
a9add1
+++ b/vcl/source/app/help.cxx
a9add1
@@ -31,6 +31,7 @@
a9add1
 #include "vcl/settings.hxx"
a9add1
 
a9add1
 #include "helpwin.hxx"
a9add1
+#include "salframe.hxx"
a9add1
 #include "svdata.hxx"
a9add1
 
a9add1
 #define HELPWINSTYLE_QUICK      0
a9add1
@@ -147,21 +148,11 @@ bool Help::IsBalloonHelpEnabled()
a9add1
 }
a9add1
 
a9add1
 bool Help::ShowBalloon( vcl::Window* pParent,
a9add1
-                        const Point& rScreenPos,
a9add1
-                        const OUString& rHelpText )
a9add1
-{
a9add1
-    ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
a9add1
-                        rHelpText, OUString(), rScreenPos );
a9add1
-
a9add1
-    return true;
a9add1
-}
a9add1
-
a9add1
-bool Help::ShowBalloon( vcl::Window* pParent,
a9add1
                         const Point& rScreenPos, const Rectangle& rRect,
a9add1
                         const OUString& rHelpText )
a9add1
 {
a9add1
     ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
a9add1
-                        rHelpText, OUString(), rScreenPos, &rRect );
a9add1
+                        rHelpText, OUString(), rScreenPos, rRect );
a9add1
 
a9add1
     return true;
a9add1
 }
a9add1
@@ -189,7 +180,7 @@ bool Help::ShowQuickHelp( vcl::Window* pParent,
a9add1
 {
a9add1
     ImplShowHelpWindow( pParent, HELPWINSTYLE_QUICK, nStyle,
a9add1
                         rHelpText, rLongHelpText,
a9add1
-                        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
a9add1
+                        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), rScreenRect );
a9add1
     return true;
a9add1
 }
a9add1
 
a9add1
@@ -221,7 +212,7 @@ void Help::UpdateTip( sal_uIntPtr nId, vcl::Window* pParent, const Rectangle& rS
a9add1
     Size aSz = pHelpWin->CalcOutSize();
a9add1
     pHelpWin->SetOutputSizePixel( aSz );
a9add1
     ImplSetHelpWindowPos( pHelpWin, pHelpWin->GetWinStyle(), pHelpWin->GetStyle(),
a9add1
-        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
a9add1
+        pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), rScreenRect );
a9add1
 
a9add1
     pHelpWin->SetHelpText( rText );
a9add1
     pHelpWin->Invalidate();
a9add1
@@ -475,8 +466,14 @@ OUString HelpTextWindow::GetText() const
a9add1
 
a9add1
 void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
a9add1
                          const OUString& rHelpText, const OUString& rStatusText,
a9add1
-                         const Point& rScreenPos, const Rectangle* pHelpArea )
a9add1
+                         const Point& rScreenPos, const Rectangle& rHelpArea )
a9add1
 {
a9add1
+    if (pParent->ImplGetFrame()->ShowTooltip(rHelpText, rHelpArea))
a9add1
+    {
a9add1
+        //tooltips are handled natively, return early
a9add1
+        return;
a9add1
+    }
a9add1
+
a9add1
     ImplSVData* pSVData = ImplGetSVData();
a9add1
 
a9add1
     if (rHelpText.isEmpty() && !pSVData->maHelpData.mbRequestingHelp)
a9add1
@@ -490,9 +487,7 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
a9add1
 
a9add1
         if  (   (   ( pHelpWin->GetHelpText() != rHelpText )
a9add1
                 ||  ( pHelpWin->GetWinStyle() != nHelpWinStyle )
a9add1
-                ||  (   pHelpArea
a9add1
-                    &&  ( pHelpWin->GetHelpArea() != *pHelpArea )
a9add1
-                    )
a9add1
+                ||  ( pHelpWin->GetHelpArea() != rHelpArea )
a9add1
                 )
a9add1
             &&  pSVData->maHelpData.mbRequestingHelp
a9add1
             )
a9add1
@@ -517,7 +512,7 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
a9add1
 
a9add1
                 pHelpWin->SetHelpText( rHelpText );
a9add1
                 // approach mouse position
a9add1
-                ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
a9add1
+                ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, rHelpArea );
a9add1
                 if( pHelpWin->IsVisible() )
a9add1
                     pHelpWin->Invalidate();
a9add1
             }
a9add1
@@ -536,13 +531,12 @@ void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHe
a9add1
         pHelpWin = VclPtr<HelpTextWindow>::Create( pParent, rHelpText, nHelpWinStyle, nStyle );
a9add1
         pSVData->maHelpData.mpHelpWin = pHelpWin;
a9add1
         pHelpWin->SetStatusText( rStatusText );
a9add1
-        if ( pHelpArea )
a9add1
-            pHelpWin->SetHelpArea( *pHelpArea );
a9add1
+        pHelpWin->SetHelpArea( rHelpArea );
a9add1
 
a9add1
         //  positioning
a9add1
         Size aSz = pHelpWin->CalcOutSize();
a9add1
         pHelpWin->SetOutputSizePixel( aSz );
a9add1
-        ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
a9add1
+        ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, rHelpArea );
a9add1
         // if not called from Window::RequestHelp, then without delay...
a9add1
         if ( !pSVData->maHelpData.mbRequestingHelp )
a9add1
             nDelayMode = HELPDELAY_NONE;
a9add1
@@ -571,7 +565,7 @@ void ImplDestroyHelpWindow( bool bUpdateHideTime )
a9add1
 }
a9add1
 
a9add1
 void ImplSetHelpWindowPos( vcl::Window* pHelpWin, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
a9add1
-                           const Point& rPos, const Rectangle* pHelpArea )
a9add1
+                           const Point& rPos, const Rectangle& rHelpArea )
a9add1
 {
a9add1
     Point       aPos = rPos;
a9add1
     Size        aSz = pHelpWin->GetSizePixel();
a9add1
@@ -606,26 +600,23 @@ void ImplSetHelpWindowPos( vcl::Window* pHelpWin, sal_uInt16 nHelpWinStyle, Quic
a9add1
 
a9add1
     if ( nStyle & QuickHelpFlags::NoAutoPos )
a9add1
     {
a9add1
-        if ( pHelpArea )
a9add1
-        {
a9add1
-            // convert help area to screen coords
a9add1
-            Rectangle devHelpArea(
a9add1
-                pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->TopLeft() ),
a9add1
-                pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->BottomRight() ) );
a9add1
-
a9add1
-            // Welche Position vom Rechteck?
a9add1
-            aPos = devHelpArea.Center();
a9add1
-
a9add1
-            if ( nStyle & QuickHelpFlags::Left )
a9add1
-                aPos.X() = devHelpArea.Left();
a9add1
-            else if ( nStyle & QuickHelpFlags::Right )
a9add1
-                aPos.X() = devHelpArea.Right();
a9add1
-
a9add1
-            if ( nStyle & QuickHelpFlags::Top )
a9add1
-                aPos.Y() = devHelpArea.Top();
a9add1
-            else if ( nStyle & QuickHelpFlags::Bottom )
a9add1
-                aPos.Y() = devHelpArea.Bottom();
a9add1
-        }
a9add1
+        // convert help area to screen coords
a9add1
+        Rectangle devHelpArea(
a9add1
+            pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( rHelpArea.TopLeft() ),
a9add1
+            pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( rHelpArea.BottomRight() ) );
a9add1
+
a9add1
+        // Welche Position vom Rechteck?
a9add1
+        aPos = devHelpArea.Center();
a9add1
+
a9add1
+        if ( nStyle & QuickHelpFlags::Left )
a9add1
+            aPos.X() = devHelpArea.Left();
a9add1
+        else if ( nStyle & QuickHelpFlags::Right )
a9add1
+            aPos.X() = devHelpArea.Right();
a9add1
+
a9add1
+        if ( nStyle & QuickHelpFlags::Top )
a9add1
+            aPos.Y() = devHelpArea.Top();
a9add1
+        else if ( nStyle & QuickHelpFlags::Bottom )
a9add1
+            aPos.Y() = devHelpArea.Bottom();
a9add1
 
a9add1
         // which direction?
a9add1
         if ( nStyle & QuickHelpFlags::Left )
a9add1
diff --git a/vcl/source/window/menuwindow.cxx b/vcl/source/window/menuwindow.cxx
a9add1
index e915c33..4e89f44 100644
a9add1
--- a/vcl/source/window/menuwindow.cxx
a9add1
+++ b/vcl/source/window/menuwindow.cxx
a9add1
@@ -63,7 +63,7 @@ bool MenuWindow::ImplHandleHelpEvent(vcl::Window* pMenuWindow, Menu* pMenu, sal_
a9add1
 
a9add1
         Rectangle aRect( aPos, Size() );
a9add1
         if (!pMenu->GetHelpText(nId).isEmpty())
a9add1
-            Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
a9add1
+            Help::ShowBalloon( pMenuWindow, aPos, aRect, pMenu->GetHelpText( nId ) );
a9add1
         else
a9add1
         {
a9add1
             // give user a chance to read the full filename
a9add1
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
a9add1
index e8d2b96..20377ac 100644
a9add1
--- a/vcl/source/window/window.cxx
a9add1
+++ b/vcl/source/window/window.cxx
a9add1
@@ -1976,7 +1976,14 @@ void Window::RequestHelp( const HelpEvent& rHEvt )
a9add1
         if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
a9add1
             ImplGetParent()->RequestHelp( rHEvt );
a9add1
         else
a9add1
-            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), rStr );
a9add1
+        {
a9add1
+            Point aPos = GetPosPixel();
a9add1
+            if ( ImplGetParent() && !ImplIsOverlapWindow() )
a9add1
+                aPos = ImplGetParent()->OutputToScreenPixel( aPos );
a9add1
+            Rectangle   aRect( aPos, GetSizePixel() );
a9add1
+
a9add1
+            Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
a9add1
+        }
a9add1
     }
a9add1
     else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
a9add1
     {
a9add1
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
a9add1
index ca9d371..592c872 100644
a9add1
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
a9add1
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
a9add1
@@ -978,6 +978,8 @@ void GtkSalFrame::InitCommon()
a9add1
 
a9add1
     // connect signals
a9add1
     g_signal_connect( G_OBJECT(m_pWindow), "style-set", G_CALLBACK(signalStyleSet), this );
a9add1
+    gtk_widget_set_has_tooltip(pEventWidget, true);
a9add1
+    m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "query-tooltip", G_CALLBACK(signalTooltipQuery), this ));
a9add1
     m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-press-event", G_CALLBACK(signalButton), this ));
a9add1
     m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "motion-notify-event", G_CALLBACK(signalMotion), this ));
a9add1
     m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-release-event", G_CALLBACK(signalButton), this ));
a9add1
@@ -2623,6 +2625,32 @@ void GtkSalFrame::SetModal(bool bModal)
a9add1
     gtk_window_set_modal(GTK_WINDOW(m_pWindow), bModal);
a9add1
 }
a9add1
 
a9add1
+gboolean GtkSalFrame::signalTooltipQuery(GtkWidget*, gint /*x*/, gint /*y*/,
a9add1
+                                     gboolean /*keyboard_mode*/, GtkTooltip *tooltip,
a9add1
+                                     gpointer frame)
a9add1
+{
a9add1
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
a9add1
+    if (pThis->m_aTooltip.isEmpty())
a9add1
+        return false;
a9add1
+    gtk_tooltip_set_text(tooltip,
a9add1
+        OUStringToOString(pThis->m_aTooltip, RTL_TEXTENCODING_UTF8).getStr());
a9add1
+    GdkRectangle aHelpArea;
a9add1
+    aHelpArea.x = pThis->m_aHelpArea.Left();
a9add1
+    aHelpArea.y = pThis->m_aHelpArea.Top();
a9add1
+    aHelpArea.width = pThis->m_aHelpArea.GetWidth();
a9add1
+    aHelpArea.height = pThis->m_aHelpArea.GetHeight();
a9add1
+    gtk_tooltip_set_tip_area(tooltip, &aHelpArea);
a9add1
+    return true;
a9add1
+}
a9add1
+
a9add1
+bool GtkSalFrame::ShowTooltip(const OUString& rHelpText, const Rectangle& rHelpArea)
a9add1
+{
a9add1
+    m_aTooltip = rHelpText;
a9add1
+    m_aHelpArea = rHelpArea;
a9add1
+    gtk_widget_trigger_tooltip_query(getMouseEventWidget());
a9add1
+    return true;
a9add1
+}
a9add1
+
a9add1
 gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer frame )
a9add1
 {
a9add1
     GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
a9add1
-- 
a9add1
2.5.0
a9add1