bug 1343802 draw trough centered instead of filling the scrollbar r?jhorak draft
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 23 Mar 2017 18:17:49 +1300
changeset 503438 bf12ceac90c0dcb7c5bc74130ed4c388982954bc
parent 503437 4c442c0d3bd88301a60f6690227270737c05a56f
child 550426 dbc3e809a92c2fd894976b362f031cad92fa371f
push id50576
push userktomlinson@mozilla.com
push dateThu, 23 Mar 2017 06:19:17 +0000
reviewersjhorak
bugs1343802
milestone55.0a1
bug 1343802 draw trough centered instead of filling the scrollbar r?jhorak to follow the behavior of version 3.20 GtkRange's contents_gadget. MozReview-Commit-ID: BQE6mQqsan8
widget/gtk/gtk3drawing.cpp
widget/gtk/gtkdrawing.h
--- a/widget/gtk/gtk3drawing.cpp
+++ b/widget/gtk/gtk3drawing.cpp
@@ -34,16 +34,19 @@ static ScrollbarGTKMetrics sScrollbarMet
 
 static gint
 moz_gtk_get_tab_thickness(GtkStyleContext *style);
 
 static gint
 moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
                         GtkWidgetState* state, GtkTextDirection direction);
 
+static GtkBorder
+GetMarginBorderPadding(GtkStyleContext* aStyle);
+
 // GetStateFlagsFromGtkWidgetState() can be safely used for the specific
 // GtkWidgets that set both prelight and active flags.  For other widgets,
 // either the GtkStateFlags or Gecko's GtkWidgetState need to be carefully
 // adjusted to match GTK behavior.  Although GTK sets insensitive and focus
 // flags in the generic GtkWidget base class, GTK adds prelight and active
 // flags only to widgets that are expected to demonstrate prelight or active
 // states.  This contrasts with HTML where any element may have :active and
 // :hover states, and so Gecko's GtkStateFlags do not necessarily map to GTK
@@ -646,22 +649,47 @@ moz_gtk_draw_styled_frame(GtkStyleContex
     if (drawFocus) {
         gtk_render_focus(style, cr,
                          rect.x, rect.y, rect.width, rect.height);
     }
 }
 
 static gint
 moz_gtk_scrollbar_trough_paint(WidgetNodeType widget,
-                               cairo_t *cr, const GdkRectangle* rect,
+                               cairo_t *cr, const GdkRectangle* aRect,
                                GtkWidgetState* state,
                                GtkTextDirection direction)
 {
-    GtkStyleContext* style = ClaimStyleContext(widget, direction);
-    moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
+    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);
+        style = ClaimStyleContext(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) {
+            rect.x += (rect.width - trackSize.width)/2;
+            rect.width = trackSize.width;
+        } else {
+            rect.y += (rect.height - trackSize.height)/2;
+            rect.height = trackSize.height;
+        }
+    } else {
+        style = ClaimStyleContext(widget, direction);
+    }
+
+    moz_gtk_draw_styled_frame(style, cr, &rect, state->focused);
     ReleaseStyleContext(style);
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_scrollbar_paint(WidgetNodeType widget,
                         cairo_t *cr, const GdkRectangle* rect,
--- a/widget/gtk/gtkdrawing.h
+++ b/widget/gtk/gtkdrawing.h
@@ -41,21 +41,31 @@ typedef struct {
 
 /**
  * A size in the same GTK pixel units as GtkBorder and GdkRectangle.
  */
 struct MozGtkSize {
   gint width;
   gint height;
 
+  MozGtkSize& operator+=(const GtkBorder& aBorder)
+  {
+    width += aBorder.left + aBorder.right;
+    height += aBorder.top + aBorder.bottom;
+    return *this;
+  }
   MozGtkSize operator+(const GtkBorder& aBorder) const
   {
-    gint resultWidth = width + aBorder.left + aBorder.right;
-    gint resultHeight = height + aBorder.top + aBorder.bottom;
-    return {resultWidth, resultHeight};
+    MozGtkSize result = *this;
+    return result += aBorder;
+  }
+  void Include(MozGtkSize aOther)
+  {
+    width = std::max(width, aOther.width);
+    height = std::max(height, aOther.height);
   }
   void Rotate()
   {
     gint tmp = width;
     width = height;
     height = tmp;
   }
 };