Bug 1603419 [Linux] Cache GetCSDDecorationSize() results, r=jhorak
authorMartin Stransky <stransky@redhat.com>
Fri, 13 Dec 2019 07:44:48 +0000
changeset 506840 b0d4fec975e29a402fe50b05528ca89fa9f60b49
parent 506839 f1b4749d24a135ef79f185953812d176b1596427
child 506841 e0f4d9fd669d3bbc11c35cf49ad4089d53cdca2e
push id36913
push useropoprus@mozilla.com
push dateFri, 13 Dec 2019 16:53:24 +0000
treeherdermozilla-central@1ed684598bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjhorak
bugs1603419
milestone73.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1603419 [Linux] Cache GetCSDDecorationSize() results, r=jhorak Differential Revision: https://phabricator.services.mozilla.com/D56915
widget/gtk/gtk3drawing.cpp
widget/gtk/gtkdrawing.h
widget/gtk/nsWindow.cpp
--- a/widget/gtk/gtk3drawing.cpp
+++ b/widget/gtk/gtk3drawing.cpp
@@ -25,16 +25,18 @@ static gboolean notebook_has_tab_gap;
 
 static ScrollbarGTKMetrics sScrollbarMetrics[2];
 static ScrollbarGTKMetrics sActiveScrollbarMetrics[2];
 static ToggleGTKMetrics sCheckboxMetrics;
 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
 #define ARROW_RIGHT G_PI_2
 #define ARROW_LEFT (G_PI + G_PI_2)
 
 #if !GTK_CHECK_VERSION(3, 14, 0)
 #  define GTK_STATE_FLAG_CHECKED (1 << 11)
@@ -212,16 +214,18 @@ void moz_gtk_refresh() {
   sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false;
   sActiveScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false;
   sActiveScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false;
   sCheckboxMetrics.initialized = false;
   sRadioMetrics.initialized = false;
   sMenuCheckboxMetrics.initialized = false;
   sMenuRadioMetrics.initialized = false;
   sToolbarMetrics.initialized = false;
+  sToplevelWindowDecorationSize.initialized = false;
+  sPopupWindowDecorationSize.initialized = false;
 
   /* This will destroy all of our widgets */
   ResetWidgetCache();
 }
 
 static gint moz_gtk_get_focus_outline_size(GtkStyleContext* style,
                                            gint* focus_h_width,
                                            gint* focus_v_width) {
@@ -2951,39 +2955,42 @@ const ScrollbarGTKMetrics* GetActiveScro
   }
   return metrics;
 }
 
 /*
  * 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);
 
   /* 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);
 
   /* Get shadow extents but combine with style margin; use the bigger value.
    */
   GdkRectangle clip;
   sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip);
@@ -2991,25 +2998,34 @@ bool GetCSDDecorationSize(GtkWindow* aGt
   GtkBorder extents;
   extents.top = -clip.y;
   extents.right = clip.width + clip.x;
   extents.bottom = clip.height + clip.y;
   extents.left = -clip.x;
 
   // 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. */
 gint moz_gtk_widget_paint(WidgetNodeType widget, cairo_t* cr,
                           GdkRectangle* rect, GtkWidgetState* state, gint flags,
                           GtkTextDirection direction) {
   /* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=694086
    */
--- a/widget/gtk/gtkdrawing.h
+++ b/widget/gtk/gtkdrawing.h
@@ -101,16 +101,21 @@ typedef struct {
 } ToolbarButtonGTKMetrics;
 
 #define TOOLBAR_BUTTONS 3
 typedef struct {
   bool initialized;
   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,
   MOZ_GTK_STEPPER_VERTICAL = 1 << 2
 } GtkScrollbarButtonFlags;
 
 typedef enum { MOZ_GTK_TRACK_OPAQUE = 1 << 0 } GtkScrollbarTrackFlags;
 
@@ -606,20 +611,17 @@ const ToolbarButtonGTKMetrics* GetToolba
  *
  * returns:    Number of returned entries at aButtonLayout.
  */
 int GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout,
                                 int aMaxButtonNums,
                                 bool* aReversedButtonsPlacement);
 
 /**
- * Get size of CSD window extents of given GtkWindow.
+ * Get size of CSD window extents.
+ *
+ * aIsPopup: [IN] Get decoration size for popup or toplevel window.
  *
- * aGtkWindow      [IN]  Decorated window.
- * aDecorationSize [OUT] Returns calculated (or estimated) decoration
- *                       size of given aGtkWindow.
- *
- * 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
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -4824,17 +4824,18 @@ void nsWindow::UpdateOpaqueRegion(const 
     // Gecko does not use transparent toplevel windows (see Bug 1469716),
     // however we need to make it transparent to draw round corners of
     // Gtk titlebar.
     region = cairo_region_create();
 
     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();
     int width = mBounds.width / scale;
     int height = mBounds.height / scale;
 
     cairo_rectangle_int_t rect = {decorationSize.left, decorationSize.top,
                                   width, height};
@@ -6829,18 +6830,18 @@ void nsWindow::UpdateClientOffsetForCSDW
   if (!mIsX11Display) {
     return;
   }
 
   // _NET_FRAME_EXTENTS is not set on client decorated windows,
   // 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);
   }
 
   // Send a WindowMoved notification. This ensures that BrowserParent
   // picks up the new client offset and sends it to the child process
   // if appropriate.
@@ -7657,18 +7658,18 @@ GtkTextDirection nsWindow::GetTextDirect
 
 void nsWindow::LockAspectRatio(bool aShouldLock) {
   if (aShouldLock) {
     gint scale = GdkScaleFactor();
     float width = (float)mBounds.Width() / scale;
     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;
     }
 
     mAspectRatio = width / height;
     LOG(("nsWindow::LockAspectRatio() [%p] width %f height %f aspect %f\n",
          (void*)this, width, height, mAspectRatio));
   } else {