summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Monastirsky <momonasmon@gmail.com>2018-06-11 02:08:54 +0300
committerMaxim Monastirsky <momonasmon@gmail.com>2018-06-11 21:39:38 +0200
commit0da89ede1fee3a9079b7b41ee8b34504ddeb5ee5 (patch)
tree2acd724efe8de0c1ad056d294e57de1b2b310c06
parenta75cc6348ce578f619c7429f5157fae53eb08e01 (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.hxx1
-rw-r--r--vcl/inc/unx/gtk/gtkframe.hxx6
-rw-r--r--vcl/source/window/floatwin.cxx1
-rw-r--r--vcl/unx/gtk3/gtk3gtkframe.cxx83
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;
}