Bug 1355143 - Provide ScrollbarGTKMetrics for active (mouse over) scrollbars, r=jhorak
authorMartin Stransky <stransky@redhat.com>
Wed, 18 Apr 2018 11:05:46 +0200
changeset 468010 111bb4416a8541abbe481459c6c3f6189dc2eb56
parent 468009 8683842b60582c60de0226d1398c335a7e1a7b3f
child 468011 4405d1c4673b0b1eb415b528c5e252585094b150
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjhorak
bugs1355143
milestone61.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 1355143 - Provide ScrollbarGTKMetrics for active (mouse over) scrollbars, r=jhorak MozReview-Commit-ID: 95d1jeQ8mXd
widget/gtk/gtk3drawing.cpp
widget/gtk/gtkdrawing.h
--- a/widget/gtk/gtk3drawing.cpp
+++ b/widget/gtk/gtk3drawing.cpp
@@ -19,16 +19,17 @@
 
 #include <math.h>
 #include <dlfcn.h>
 
 static gboolean checkbox_check_state;
 static gboolean notebook_has_tab_gap;
 
 static ScrollbarGTKMetrics sScrollbarMetrics[2];
+static ScrollbarGTKMetrics sScrollbarMetricsActive[2];
 static ToggleGTKMetrics sCheckboxMetrics;
 static ToggleGTKMetrics sRadioMetrics;
 static ToolbarGTKMetrics sToolbarMetrics;
 
 #define ARROW_UP      0
 #define ARROW_DOWN    G_PI
 #define ARROW_RIGHT   G_PI_2
 #define ARROW_LEFT    (G_PI+G_PI_2)
@@ -177,16 +178,18 @@ moz_gtk_refresh()
                                     "has-tab-gap", &notebook_has_tab_gap, NULL);
     }
     else {
         notebook_has_tab_gap = true;
     }
 
     sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false;
     sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false;
+    sScrollbarMetricsActive[GTK_ORIENTATION_HORIZONTAL].initialized = false;
+    sScrollbarMetricsActive[GTK_ORIENTATION_VERTICAL].initialized = false;
     sCheckboxMetrics.initialized = false;
     sRadioMetrics.initialized = false;
     sToolbarMetrics.initialized = false;
 
     /* This will destroy all of our widgets */
     ResetWidgetCache();
 }
 
@@ -735,20 +738,19 @@ GetMinContentBox(GtkStyleContext* style)
     return {width, height};
 }
 
 /**
  * Get minimum widget size as sum of margin, padding, border and
  * min-width/min-height.
  */
 static void
-moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width,
+moz_gtk_get_widget_min_size(GtkStyleContext* style, int* width,
                             int* height)
 {
-  GtkStyleContext* style = GetStyleContext(aGtkWidgetType);
   GtkStateFlags state_flags = gtk_style_context_get_state(style);
   gtk_style_context_get(style, state_flags,
                         "min-height", height,
                         "min-width", width,
                         nullptr);
 
   GtkBorder border, padding, margin;
   gtk_style_context_get_border(style, state_flags, &border);
@@ -757,20 +759,20 @@ moz_gtk_get_widget_min_size(WidgetNodeTy
 
   *width += border.left + border.right + margin.left + margin.right +
             padding.left + padding.right;
   *height += border.top + border.bottom + margin.top + margin.bottom +
              padding.top + padding.bottom;
 }
 
 static MozGtkSize
-GetMinMarginBox(WidgetNodeType aNodeType)
+GetMinMarginBox(GtkStyleContext* style)
 {
     gint width, height;
-    moz_gtk_get_widget_min_size(aNodeType, &width, &height);
+    moz_gtk_get_widget_min_size(style, &width, &height);
     return {width, height};
 }
 
 static void
 Inset(GdkRectangle* rect, const GtkBorder& aBorder)
 {
     MOZ_ASSERT(rect);
     rect->x += aBorder.left;
@@ -942,17 +944,17 @@ moz_gtk_scrollbar_trough_paint(WidgetNod
 {
     GdkRectangle rect = *aRect;
     GtkStyleContext* style;
 
     if (gtk_get_minor_version() >= 20) {
         WidgetNodeType thumb = widget == MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL ?
             MOZ_GTK_SCROLLBAR_THUMB_VERTICAL :
             MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
-        MozGtkSize thumbSize = GetMinMarginBox(thumb);
+        MozGtkSize thumbSize = GetMinMarginBox(GetStyleContext(thumb));
         style = GetStyleContext(widget, direction);
         MozGtkSize trackSize = GetMinContentBox(style);
         trackSize.Include(thumbSize);
         trackSize += GetMarginBorderPadding(style);
         // Gecko's trough |aRect| fills available breadth, but GTK's trough is
         // centered in the contents_gadget.  The centering here round left
         // and up, like gtk_box_gadget_allocate_child().
         if (widget == MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL) {
@@ -2760,17 +2762,18 @@ moz_gtk_get_scale_metrics(GtkOrientation
       } else {
           *scale_width = thumb_height + trough_border * 2;
           *scale_height = thumb_length + trough_border * 2;
       }
   } else {
       WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ?
                                MOZ_GTK_SCALE_TROUGH_HORIZONTAL :
                                MOZ_GTK_SCALE_TROUGH_VERTICAL;
-      moz_gtk_get_widget_min_size(widget, scale_width, scale_height);
+      moz_gtk_get_widget_min_size(GetStyleContext(widget),
+                                  scale_width, scale_height);
   }
 }
 
 gint
 moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height)
 {
 
   if (gtk_check_version(3, 20, 0) != nullptr) {
@@ -2879,29 +2882,32 @@ GetToggleMetrics(bool isRadio)
                              nullptr);
         metrics->minSizeWithBorder.width =
             metrics->minSizeWithBorder.height = indicator_size;
     }
     return metrics;
 }
 
 const ScrollbarGTKMetrics*
-GetScrollbarMetrics(GtkOrientation aOrientation)
+GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive)
 {
-    auto metrics = &sScrollbarMetrics[aOrientation];
+    auto metrics = aActive ? &sScrollbarMetricsActive[aOrientation] :
+                             &sScrollbarMetrics[aOrientation];
     if (metrics->initialized)
         return metrics;
 
     metrics->initialized = true;
 
     WidgetNodeType scrollbar = aOrientation == GTK_ORIENTATION_HORIZONTAL ?
         MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL;
 
     gboolean backward, forward, secondary_backward, secondary_forward;
-    GtkStyleContext* style = GetStyleContext(scrollbar);
+    GtkStyleContext* style = GetStyleContext(scrollbar, GTK_TEXT_DIR_NONE,
+                             aActive ? GTK_STATE_FLAG_PRELIGHT :
+                                       GTK_STATE_FLAG_NORMAL);
     gtk_style_context_get_style(style,
                                 "has-backward-stepper", &backward,
                                 "has-forward-stepper", &forward,
                                 "has-secondary-backward-stepper",
                                 &secondary_backward,
                                 "has-secondary-forward-stepper",
                                 &secondary_forward, nullptr);
     bool hasButtons =
@@ -2958,26 +2964,58 @@ GetScrollbarMetrics(GtkOrientation aOrie
         contents = MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL;
         track = MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL;
         thumb = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
     } else {
         contents = MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL;
         track = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL;
         thumb = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
     }
+
+    /* GetStyleContext() sets GtkStateFlags to the latest widget name
+     * in css selector string. When we call:
+     *
+     *     GetStyleContext(thumb, GTK_STATE_FLAG_PRELIGHT)
+     *
+     * we get:
+     *
+     *    "scrollbar contents trough slider:hover"
+     *
+     * Some themes (Ubuntu Ambiance) styles trough/thumb by scrollbar,
+     * the Gtk+ css rule looks like:
+     *
+     *    "scrollbar:hover contents trough slider"
+     *
+     *  So we need to apply GtkStateFlags to each widgets in style path.
+     */
+
     // thumb
-    metrics->size.thumb = GetMinMarginBox(thumb);
+    style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE,
+                                         aActive ? GTK_STATE_FLAG_PRELIGHT :
+                                                   GTK_STATE_FLAG_NORMAL);
+    metrics->size.thumb = GetMinMarginBox(style);
+    g_object_unref(style);
+
     // track
-    style = GetStyleContext(track);
+    style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE,
+                                         aActive ? GTK_STATE_FLAG_PRELIGHT :
+                                                   GTK_STATE_FLAG_NORMAL);
     metrics->border.track = GetMarginBorderPadding(style);
     MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track;
     MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track;
+    g_object_unref(style);
+
     // button
     if (hasButtons) {
-        metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON);
+        style = CreateStyleContextWithStates(MOZ_GTK_SCROLLBAR_BUTTON,
+                                             GTK_TEXT_DIR_NONE,
+                                             aActive ? GTK_STATE_FLAG_PRELIGHT :
+                                                       GTK_STATE_FLAG_NORMAL);
+        metrics->size.button = GetMinMarginBox(style);
+        g_object_unref(style);
     } else {
         metrics->size.button = {0, 0};
     }
     if (aOrientation == GTK_ORIENTATION_HORIZONTAL) {
         metrics->size.button.Rotate();
         // If the track is wider than necessary for the thumb, including when
         // the buttons will cause Gecko to expand the track to fill
         // available breadth, then add to the track border to prevent Gecko
@@ -3001,18 +3039,21 @@ GetScrollbarMetrics(GtkOrientation aOrie
             // If extra is odd, then the thumb is 0.5 pixels to the left
             // of center as in gtk_range_compute_slider_position().
             metrics->border.track.left += extra / 2;
             metrics->border.track.right += extra - extra / 2;
             trackSizeForThumb.width += extra;
         }
     }
 
-    style = GetStyleContext(contents);
+    style = CreateStyleContextWithStates(contents, GTK_TEXT_DIR_NONE,
+                                            aActive ? GTK_STATE_FLAG_PRELIGHT :
+                                                      GTK_STATE_FLAG_NORMAL);
     GtkBorder contentsBorder = GetMarginBorderPadding(style);
+    g_object_unref(style);
 
     metrics->size.scrollbar =
         trackSizeForThumb + contentsBorder + metrics->border.scrollbar;
 
     return metrics;
 }
 
 /* cairo_t *cr argument has to be a system-cairo. */
--- a/widget/gtk/gtkdrawing.h
+++ b/widget/gtk/gtkdrawing.h
@@ -48,16 +48,21 @@ struct MozGtkSize {
     height += aBorder.top + aBorder.bottom;
     return *this;
   }
   MozGtkSize operator+(const GtkBorder& aBorder) const
   {
     MozGtkSize result = *this;
     return result += aBorder;
   }
+  bool operator<(const MozGtkSize &aOther) const
+  {
+    return (width < aOther.width && height <= aOther.height) ||
+           (width <= aOther.width && height < aOther.height);
+  }
   void Include(MozGtkSize aOther)
   {
     width = std::max(width, aOther.width);
     height = std::max(height, aOther.height);
   }
   void Rotate()
   {
     gint tmp = width;
@@ -486,19 +491,22 @@ moz_gtk_get_scale_metrics(GtkOrientation
  *
  * returns:    MOZ_GTK_SUCCESS if there was no error, an error code otherwise
  */
 gint
 moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height);
 
 /**
  * Get the metrics in GTK pixels for a scrollbar.
+ * aOrientation:     [IN] the scrollbar orientation
+ * aActive:          [IN] Metricts for scrollbar with mouse pointer over it.
+ *
  */
 const ScrollbarGTKMetrics*
-GetScrollbarMetrics(GtkOrientation aOrientation);
+GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive = false);
 
 /**
  * Get the desired size of a dropdown arrow button
  * width:   [OUT] the desired width
  * height:  [OUT] the desired height
  *
  * returns:    MOZ_GTK_SUCCESS if there was no error, an error code otherwise
  */