diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index 12fcf591bdde..b3de8d0094ca 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -30,6 +30,8 @@ static ToggleGTKMetrics sRadioMetrics; static ToggleGTKMetrics sMenuRadioMetrics; static ToggleGTKMetrics sMenuCheckboxMetrics; static ToolbarGTKMetrics sToolbarMetrics; +static CSDWindowDecorationSize sToplevelWindowDecorationSize; +static CSDWindowDecorationSize sPopupWindowDecorationSize; #define ARROW_UP 0 #define ARROW_DOWN G_PI @@ -217,6 +219,8 @@ void moz_gtk_refresh() { sMenuCheckboxMetrics.initialized = false; sMenuRadioMetrics.initialized = false; sToolbarMetrics.initialized = false; + sToplevelWindowDecorationSize.initialized = false; + sPopupWindowDecorationSize.initialized = false; /* This will destroy all of our widgets */ ResetWidgetCache(); @@ -2956,19 +2960,21 @@ const ScrollbarGTKMetrics* GetActiveScrollbarMetrics( * get_shadow_width() from gtkwindow.c is not public so we need * to implement it. */ -bool GetCSDDecorationSize(GtkWindow* aGtkWindow, GtkBorder* aDecorationSize) { +void InitWindowDecorationSize(CSDWindowDecorationSize* sWindowDecorationSize, + bool aPopupWindow) { // Available on GTK 3.20+. static auto sGtkRenderBackgroundGetClip = (void (*)( GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*))dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); if (!sGtkRenderBackgroundGetClip) { - *aDecorationSize = {0, 0, 0, 0}; - return false; + sWindowDecorationSize->decorationSize = {0, 0, 0, 0}; + return; } - GtkStyleContext* context = - gtk_widget_get_style_context(GTK_WIDGET(aGtkWindow)); + // Scale factor is applied later when decoration size is used for actual + // gtk windows. + GtkStyleContext* context = GetStyleContext(MOZ_GTK_WINDOW, 1); bool solidDecorations = gtk_style_context_has_class(context, "solid-csd"); context = GetStyleContext(solidDecorations ? MOZ_GTK_WINDOW_DECORATION_SOLID : MOZ_GTK_WINDOW_DECORATION); @@ -2976,9 +2982,10 @@ bool GetCSDDecorationSize(GtkWindow* aGtkWindow, GtkBorder* aDecorationSize) { /* Always sum border + padding */ GtkBorder padding; GtkStateFlags state = gtk_style_context_get_state(context); - gtk_style_context_get_border(context, state, aDecorationSize); + gtk_style_context_get_border(context, state, + &sWindowDecorationSize->decorationSize); gtk_style_context_get_padding(context, state, &padding); - *aDecorationSize += padding; + sWindowDecorationSize->decorationSize += padding; GtkBorder margin; gtk_style_context_get_margin(context, state, &margin); @@ -2996,15 +3003,24 @@ bool GetCSDDecorationSize(GtkWindow* aGtkWindow, GtkBorder* aDecorationSize) { // Margin is used for resize grip size - it's not present on // popup windows. - if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { + if (!aPopupWindow) { extents.top = MAX(extents.top, margin.top); extents.right = MAX(extents.right, margin.right); extents.bottom = MAX(extents.bottom, margin.bottom); extents.left = MAX(extents.left, margin.left); } - *aDecorationSize += extents; - return true; + sWindowDecorationSize->decorationSize += extents; +} + +GtkBorder GetCSDDecorationSize(bool aIsPopup) { + auto metrics = + aIsPopup ? &sPopupWindowDecorationSize : &sToplevelWindowDecorationSize; + if (!metrics->initialized) { + InitWindowDecorationSize(metrics, aIsPopup); + metrics->initialized = true; + } + return metrics->decorationSize; } /* cairo_t *cr argument has to be a system-cairo. */ diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index 36291a6e125d..1c6098056c30 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -106,6 +106,11 @@ typedef struct { ToolbarButtonGTKMetrics button[TOOLBAR_BUTTONS]; } ToolbarGTKMetrics; +typedef struct { + bool initialized; + GtkBorder decorationSize; +} CSDWindowDecorationSize; + typedef enum { MOZ_GTK_STEPPER_DOWN = 1 << 0, MOZ_GTK_STEPPER_BOTTOM = 1 << 1, @@ -611,15 +616,12 @@ int GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout, bool* aReversedButtonsPlacement); /** - * Get size of CSD window extents of given GtkWindow. + * Get size of CSD window extents. * - * aGtkWindow [IN] Decorated window. - * aDecorationSize [OUT] Returns calculated (or estimated) decoration - * size of given aGtkWindow. + * aIsPopup: [IN] Get decoration size for popup or toplevel window. * - * returns: True if we have extract decoration size (for GTK 3.20+) - * False if we have only an estimation (for GTK+ before 3.20+) + * returns: Calculated (or estimated) decoration size of given aGtkWindow. */ -bool GetCSDDecorationSize(GtkWindow* aGtkWindow, GtkBorder* aDecorationSize); +GtkBorder GetCSDDecorationSize(bool aIsPopup); #endif diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 6ec154aa9d93..006c6965c280 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -4829,7 +4829,8 @@ void nsWindow::UpdateOpaqueRegion(const LayoutDeviceIntRegion& aOpaqueRegion) { GtkBorder decorationSize = {0, 0, 0, 0}; if (mCSDSupportLevel == CSD_SUPPORT_CLIENT && mSizeState == nsSizeMode_Normal) { - GetCSDDecorationSize(GTK_WINDOW(mShell), &decorationSize); + decorationSize = GetCSDDecorationSize( + gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP); } int scale = GdkScaleFactor(); @@ -6834,8 +6835,8 @@ void nsWindow::UpdateClientOffsetForCSDWindow() { // so we need to read offset between mContainer and toplevel mShell // window. if (mSizeState == nsSizeMode_Normal) { - GtkBorder decorationSize; - GetCSDDecorationSize(GTK_WINDOW(mShell), &decorationSize); + GtkBorder decorationSize = GetCSDDecorationSize( + gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP); mClientOffset = nsIntPoint(decorationSize.left, decorationSize.top); } else { mClientOffset = nsIntPoint(0, 0); @@ -7662,8 +7663,8 @@ void nsWindow::LockAspectRatio(bool aShouldLock) { float height = (float)mBounds.Height() / scale; if (mCSDSupportLevel == CSD_SUPPORT_CLIENT) { - GtkBorder decorationSize; - GetCSDDecorationSize(GTK_WINDOW(mShell), &decorationSize); + GtkBorder decorationSize = GetCSDDecorationSize( + gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP); width += decorationSize.left + decorationSize.right; height += decorationSize.top + decorationSize.bottom; }