From d1ddf5e48e19d5e59e63e2c202e8d8298c9ac75a Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 6 Jun 2017 22:27:18 -0700 Subject: [PATCH] Bug 1367576 - Cache results of getting GTK widget borders. r=karlt See comments in the header file. This also clears out mSafeWidgetStates in ThemeChanged since that seems like a good thing to do, and marks nsNativeThemeGTK as final. MozReview-Commit-ID: 5Zne4eGbGlh --- widget/gtk/gtk3drawing.cpp | 5 ++++- widget/gtk/gtkdrawing.h | 4 +++- widget/gtk/nsNativeThemeGTK.cpp | 21 +++++++++++++++++---- widget/gtk/nsNativeThemeGTK.h | 11 ++++++++--- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/widget/gtk/gtk3drawing.cpp b/widget/gtk/gtk3drawing.cpp index ff76512e03d5..73bd1987fd39 100644 --- a/widget/gtk/gtk3drawing.cpp +++ b/widget/gtk/gtk3drawing.cpp @@ -2074,7 +2074,10 @@ GetMarginBorderPadding(GtkStyleContext* aStyle) gint moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, - gint* right, gint* bottom, GtkTextDirection direction) + gint* right, gint* bottom, + // NOTE: callers depend on direction being used + // only for MOZ_GTK_DROPDOWN widgets. + GtkTextDirection direction) { GtkWidget* w; GtkStyleContext* style; diff --git a/widget/gtk/gtkdrawing.h b/widget/gtk/gtkdrawing.h index 1efcd98c23ad..42dbf8287499 100644 --- a/widget/gtk/gtkdrawing.h +++ b/widget/gtk/gtkdrawing.h @@ -356,7 +356,9 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, * Get the border size of a widget * left/right: [OUT] the widget's left/right border * top/bottom: [OUT] the widget's top/bottom border - * direction: the text direction for the widget + * direction: the text direction for the widget. Callers depend on this + * being used only for MOZ_GTK_DROPDOWN widgets, and cache + * results for other widget types across direction values. * * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise */ diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp index 85955b6a6580..779bf51b790f 100644 --- a/widget/gtk/nsNativeThemeGTK.cpp +++ b/widget/gtk/nsNativeThemeGTK.cpp @@ -70,8 +70,7 @@ nsNativeThemeGTK::nsNativeThemeGTK() mozilla::services::GetObserverService(); obsServ->AddObserver(this, "xpcom-shutdown", false); - memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes)); - memset(mSafeWidgetStates, 0, sizeof(mSafeWidgetStates)); + ThemeChanged(); } nsNativeThemeGTK::~nsNativeThemeGTK() { @@ -1269,8 +1268,20 @@ nsNativeThemeGTK::GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, gint unusedFlags; if (GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nullptr, &unusedFlags)) { - moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top, - &aResult->right, &aResult->bottom, aDirection); + MOZ_ASSERT(0 <= gtkWidgetType && gtkWidgetType < MOZ_GTK_WIDGET_NODE_COUNT); + uint8_t cacheIndex = gtkWidgetType / 8; + uint8_t cacheBit = 1u << (gtkWidgetType % 8); + + if (mBorderCacheValid[cacheIndex] & cacheBit) { + *aResult = mBorderCache[gtkWidgetType]; + } else { + moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top, + &aResult->right, &aResult->bottom, aDirection); + if (aWidgetType != MOZ_GTK_DROPDOWN) { // depends on aDirection + mBorderCacheValid[cacheIndex] |= cacheBit; + mBorderCache[gtkWidgetType] = *aResult; + } + } } } @@ -1780,6 +1791,8 @@ NS_IMETHODIMP nsNativeThemeGTK::ThemeChanged() { memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes)); + memset(mSafeWidgetStates, 0, sizeof(mSafeWidgetStates)); + memset(mBorderCacheValid, 0, sizeof(mBorderCacheValid)); return NS_OK; } diff --git a/widget/gtk/nsNativeThemeGTK.h b/widget/gtk/nsNativeThemeGTK.h index 4ef7dc1572a9..7cdc28ff1d9a 100644 --- a/widget/gtk/nsNativeThemeGTK.h +++ b/widget/gtk/nsNativeThemeGTK.h @@ -15,9 +15,9 @@ #include #include "gtkdrawing.h" -class nsNativeThemeGTK: private nsNativeTheme, - public nsITheme, - public nsIObserver { +class nsNativeThemeGTK final : private nsNativeTheme, + public nsITheme, + public nsIObserver { public: NS_DECL_ISUPPORTS_INHERITED @@ -89,8 +89,13 @@ private: uint8_t mSafeWidgetStates[1024]; // 256 widgets * 32 bits per widget static const char* sDisabledEngines[]; + // Because moz_gtk_get_widget_border can be slow, we cache its results + // by widget type. Each bit in mBorderCacheValid says whether the + // corresponding entry in mBorderCache is valid. void GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, GtkTextDirection aDirection, nsIntMargin* aResult); + uint8_t mBorderCacheValid[(MOZ_GTK_WIDGET_NODE_COUNT + 7) / 8]; + nsIntMargin mBorderCache[MOZ_GTK_WIDGET_NODE_COUNT]; }; #endif