diff options
author | Maxim Monastirsky <momonasmon@gmail.com> | 2018-06-11 02:08:54 +0300 |
---|---|---|
committer | Maxim Monastirsky <momonasmon@gmail.com> | 2018-06-11 21:39:38 +0200 |
commit | 0da89ede1fee3a9079b7b41ee8b34504ddeb5ee5 (patch) | |
tree | 2acd724efe8de0c1ad056d294e57de1b2b310c06 | |
parent | a75cc6348ce578f619c7429f5157fae53eb08e01 (diff) |
tdf#117175 wayland: Make popup windows not show off-screen
Depends on the gtk-3-24 dev branch, for the public
gdk_window_move_to_rect symbol.
Change-Id: Ic7a34ceb3d133ecac2addac54cf5f635eea332ed
Reviewed-on: https://gerrit.libreoffice.org/55612
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
-rw-r--r-- | vcl/inc/salframe.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkframe.hxx | 6 | ||||
-rw-r--r-- | vcl/source/window/floatwin.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkframe.cxx | 83 |
4 files changed, 90 insertions, 1 deletions
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx index c04f0a8f767e..4d8d9b5db9ff 100644 --- a/vcl/inc/salframe.hxx +++ b/vcl/inc/salframe.hxx @@ -159,6 +159,7 @@ public: SAL_WARN_UNUSED_RESULT virtual bool GetWindowState( SalFrameState* pState ) = 0; virtual void ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay ) = 0; + virtual void PositionByToolkit( const tools::Rectangle&, FloatWinPopupFlags ) {}; // Enable/Disable ScreenSaver, SystemAgents, ... virtual void StartPresentation( bool bStart ) = 0; diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx index 0940736738fa..b69b14bb002a 100644 --- a/vcl/inc/unx/gtk/gtkframe.hxx +++ b/vcl/inc/unx/gtk/gtkframe.hxx @@ -210,7 +210,10 @@ class GtkSalFrame : public SalFrame #if GTK_CHECK_VERSION(3,0,0) OUString m_aTooltip; - tools::Rectangle m_aHelpArea; + tools::Rectangle m_aHelpArea; + tools::Rectangle m_aFloatRect; + FloatWinPopupFlags m_nFloatFlags; + bool m_bFloatPositioned; long m_nWidthRequest; long m_nHeightRequest; cairo_region_t* m_pRegion; @@ -532,6 +535,7 @@ public: virtual void EndSetClipRegion() override; #if GTK_CHECK_VERSION(3,0,0) + virtual void PositionByToolkit(const tools::Rectangle& rRect, FloatWinPopupFlags nFlags) override; virtual void SetModal(bool bModal) override; virtual bool ShowTooltip(const OUString& rHelpText, const tools::Rectangle& rHelpArea) override; virtual void* ShowPopover(const OUString& rHelpText, const tools::Rectangle& rHelpArea, QuickHelpFlags nFlags) override; diff --git a/vcl/source/window/floatwin.cxx b/vcl/source/window/floatwin.cxx index 0ba23a39d6d8..ea1001f3351e 100644 --- a/vcl/source/window/floatwin.cxx +++ b/vcl/source/window/floatwin.cxx @@ -741,6 +741,7 @@ void FloatingWindow::StartPopupMode( const tools::Rectangle& rRect, FloatWinPopu DoInitialLayout(); mpImplData->maPos = ImplCalcPos(this, rRect, nFlags, nArrangeIndex, &mpImplData->maLOKTwipsPos); SetPosPixel( mpImplData->maPos ); + ImplGetFrame()->PositionByToolkit(rRect, nFlags); // set data and display window // convert maFloatRect to absolute device coordinates diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx index f71e8f5ab344..da4457640ff4 100644 --- a/vcl/unx/gtk3/gtk3gtkframe.cxx +++ b/vcl/unx/gtk3/gtk3gtkframe.cxx @@ -1130,6 +1130,9 @@ void GtkSalFrame::InitCommon() m_bGraphics = false; m_pGraphics = nullptr; + m_nFloatFlags = FloatWinPopupFlags::NONE; + m_bFloatPositioned = false; + m_nWidthRequest = 0; m_nHeightRequest = 0; @@ -2447,6 +2450,16 @@ void GtkSalFrame::EndSetClipRegion() gdk_window_shape_combine_region( widget_get_window(m_pWindow), m_pRegion, 0, 0 ); } +void GtkSalFrame::PositionByToolkit(const tools::Rectangle& rRect, FloatWinPopupFlags nFlags) +{ + if (ImplGetSVData()->maNWFData.mbCanDetermineWindowPosition) + return; + + m_aFloatRect = rRect; + m_nFloatFlags = nFlags; + m_bFloatPositioned = true; +} + void GtkSalFrame::SetModal(bool bModal) { if (!m_pWindow) @@ -2993,6 +3006,24 @@ void GtkSalFrame::sizeAllocated(GtkWidget* pWidget, GdkRectangle *pAllocation, g pThis->TriggerPaintEvent(); } +#if GTK_CHECK_VERSION(3,23,0) +namespace { + +void swapDirection(GdkGravity& gravity) +{ + if (gravity == GDK_GRAVITY_NORTH_WEST) + gravity = GDK_GRAVITY_NORTH_EAST; + else if (gravity == GDK_GRAVITY_NORTH_EAST) + gravity = GDK_GRAVITY_NORTH_WEST; + else if (gravity == GDK_GRAVITY_SOUTH_WEST) + gravity = GDK_GRAVITY_SOUTH_EAST; + else if (gravity == GDK_GRAVITY_SOUTH_EAST) + gravity = GDK_GRAVITY_SOUTH_WEST; +} + +} +#endif + void GtkSalFrame::signalRealize(GtkWidget*, gpointer frame) { GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame); @@ -3000,6 +3031,49 @@ void GtkSalFrame::signalRealize(GtkWidget*, gpointer frame) if (pThis->m_bSalObjectSetPosSize) return; pThis->TriggerPaintEvent(); + +#if GTK_CHECK_VERSION(3,23,0) + if (gtk_check_version(3, 23, 0) == nullptr && pThis->m_bFloatPositioned) + { + GdkGravity rect_anchor = GDK_GRAVITY_SOUTH_WEST, menu_anchor = GDK_GRAVITY_NORTH_WEST; + + if (pThis->m_nFloatFlags & FloatWinPopupFlags::Left) + { + rect_anchor = GDK_GRAVITY_NORTH_WEST; + menu_anchor = GDK_GRAVITY_NORTH_EAST; + } + else if (pThis->m_nFloatFlags & FloatWinPopupFlags::Up) + { + rect_anchor = GDK_GRAVITY_NORTH_WEST; + menu_anchor = GDK_GRAVITY_SOUTH_WEST; + } + else if (pThis->m_nFloatFlags & FloatWinPopupFlags::Right) + { + rect_anchor = GDK_GRAVITY_NORTH_EAST; + } + + GdkRectangle rect {static_cast<int>(pThis->m_aFloatRect.Left()), + static_cast<int>(pThis->m_aFloatRect.Top()), + static_cast<int>(pThis->m_aFloatRect.GetWidth()), + static_cast<int>(pThis->m_aFloatRect.GetHeight())}; + + if (AllSettings::GetLayoutRTL()) + { + rect.x = pThis->m_pParent->maGeometry.nWidth-rect.width-1-rect.x; + swapDirection(rect_anchor); + swapDirection(menu_anchor); + } + + if (gdk_window_get_window_type(widget_get_window(pThis->m_pParent->m_pWindow)) == GDK_WINDOW_TOPLEVEL) + { + rect.x += pThis->m_pParent->maGeometry.nX; + rect.y += pThis->m_pParent->maGeometry.nY; + } + + GdkWindow* gdkWindow = widget_get_window(pThis->m_pWindow); + gdk_window_move_to_rect(gdkWindow, &rect, rect_anchor, menu_anchor, GDK_ANCHOR_FLIP, 0, 0); + } +#endif } gboolean GtkSalFrame::signalConfigure(GtkWidget*, GdkEventConfigure* pEvent, gpointer frame) @@ -3109,6 +3183,15 @@ gboolean GtkSalFrame::signalUnmap( GtkWidget*, GdkEvent*, gpointer frame ) pThis->CallCallbackExc( SalEvent::Resize, nullptr ); + if (pThis->m_bFloatPositioned) + { + // Unrealize is needed for cases where we reuse the same popup + // (e.g. the font name control), making the realize signal fire + // again on next show. + gtk_widget_unrealize(pThis->m_pWindow); + pThis->m_bFloatPositioned = false; + } + return false; } |