Bug 1376756 - gtk: while drawing nsTreeBodyFrame, fetch current row attributes for proper style rendering. r=karlt
authorSamuel Thibault <samuel.thibault>
Wed, 27 Jun 2018 05:11:00 +0300
changeset 424190 b36d448ce91847bd8b6cca8b7d467d558d674988
parent 424189 510b02c8eb4c30437fd06058a6d46b827f0f1d78
child 424191 0413702a1dc9c21ac95017b21b88f5c309986d68
push id34201
push usershindli@mozilla.com
push dateThu, 28 Jun 2018 21:54:04 +0000
treeherdermozilla-central@8f49b2a0e003 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1376756
milestone63.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 1376756 - gtk: while drawing nsTreeBodyFrame, fetch current row attributes for proper style rendering. r=karlt
layout/xul/tree/nsTreeBodyFrame.h
widget/gtk/gtk2drawing.c
widget/gtk/gtk3drawing.cpp
widget/gtk/gtkdrawing.h
widget/gtk/nsNativeThemeGTK.cpp
--- a/layout/xul/tree/nsTreeBodyFrame.h
+++ b/layout/xul/tree/nsTreeBodyFrame.h
@@ -192,16 +192,23 @@ public:
   nsITreeBoxObject* GetTreeBoxObject() const { return mTreeBoxObject; }
 
   // Get the base element, <tree> or <select>
   mozilla::dom::Element* GetBaseElement();
 
   bool GetVerticalOverflow() const { return mVerticalOverflow; }
   bool GetHorizontalOverflow() const {return mHorizontalOverflow; }
 
+  // This returns the property array where atoms are stored for style during
+  // draw, whether the row currently being drawn is selected, hovered, etc.
+  const mozilla::AtomArray& GetPropertyArrayForCurrentDrawingItem()
+  {
+    return mScratchArray;
+  }
+
 protected:
   friend class nsOverflowChecker;
 
   // This method paints a specific column background of the tree.
   ImgDrawResult PaintColumn(nsTreeColumn*        aColumn,
                          const nsRect&        aColumnRect,
                          nsPresContext*       aPresContext,
                          gfxContext&          aRenderingContext,
--- a/widget/gtk/gtk2drawing.c
+++ b/widget/gtk/gtk2drawing.c
@@ -1815,17 +1815,20 @@ moz_gtk_treeview_expander_paint(GdkDrawa
 
     ensure_tree_view_widget();
     gtk_widget_set_direction(gTreeViewWidget, direction);
 
     style = gTreeViewWidget->style;
 
     /* Because the frame we get is of the entire treeview, we can't get the precise
      * event state of one expander, thus rendering hover and active feedback useless. */
-    state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
+    state_type = state->disabled ? GTK_STATE_INSENSITIVE :
+                 state->inHover  ? GTK_STATE_PRELIGHT :
+                 state->selected ? GTK_STATE_SELECTED :
+                                   GTK_STATE_NORMAL;
 
     TSOffsetStyleGCs(style, rect->x, rect->y);
     gtk_paint_expander(style, drawable, state_type, cliprect, gTreeViewWidget, "treeview",
                        rect->x + rect->width / 2, rect->y + rect->height / 2, expander_state);
 
     return MOZ_GTK_SUCCESS;
 }
 
--- a/widget/gtk/gtk3drawing.cpp
+++ b/widget/gtk/gtk3drawing.cpp
@@ -1385,16 +1385,23 @@ moz_gtk_treeview_expander_paint(cairo_t 
                                 GtkExpanderStyle expander_state,
                                 GtkTextDirection direction)
 {
     /* Because the frame we get is of the entire treeview, we can't get the precise
      * event state of one expander, thus rendering hover and active feedback useless. */
     GtkStateFlags state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE :
                                                   GTK_STATE_FLAG_NORMAL;
 
+    if (state->inHover)
+        state_flags =
+            static_cast<GtkStateFlags>(state_flags|GTK_STATE_FLAG_PRELIGHT);
+    if (state->selected)
+        state_flags =
+            static_cast<GtkStateFlags>(state_flags|GTK_STATE_FLAG_SELECTED);
+
     /* GTK_STATE_FLAG_ACTIVE controls expanded/colapsed state rendering
      * in gtk_render_expander()
      */
     if (expander_state == GTK_EXPANDER_EXPANDED)
         state_flags = static_cast<GtkStateFlags>(state_flags|checkbox_check_state);
     else
         state_flags = static_cast<GtkStateFlags>(state_flags&~(checkbox_check_state));
 
--- a/widget/gtk/gtkdrawing.h
+++ b/widget/gtk/gtkdrawing.h
@@ -18,16 +18,17 @@
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 #include <algorithm>
 
 /*** type definitions ***/
 typedef struct {
   guint8 active;
   guint8 focused;
+  guint8 selected;
   guint8 inHover;
   guint8 disabled;
   guint8 isDefault;
   guint8 canDefault;
   /* The depressed state is for buttons which remain active for a longer period:
    * activated toggle buttons or buttons showing a popup menu. */
   guint8 depressed;
   gint32 curpos; /* curpos and maxpos are used for scrollbars */
--- a/widget/gtk/nsNativeThemeGTK.cpp
+++ b/widget/gtk/nsNativeThemeGTK.cpp
@@ -14,16 +14,17 @@
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
 #include "nsIContent.h"
 #include "nsViewManager.h"
 #include "nsNameSpaceManager.h"
 #include "nsGfxCIID.h"
 #include "nsTransform2D.h"
 #include "nsMenuFrame.h"
+#include "tree/nsTreeBodyFrame.h"
 #include "prlink.h"
 #include "nsGkAtoms.h"
 #include "nsAttrValueInlines.h"
 
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/Services.h"
 
@@ -276,16 +277,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
       stateFrame = aFrame = aFrame->GetParent();
     }
 
     EventStates eventState = GetContentState(stateFrame, aWidgetType);
 
     aState->disabled = IsDisabled(aFrame, eventState) || IsReadOnly(aFrame);
     aState->active  = eventState.HasState(NS_EVENT_STATE_ACTIVE);
     aState->focused = eventState.HasState(NS_EVENT_STATE_FOCUS);
+    aState->selected = FALSE;
     aState->inHover = eventState.HasState(NS_EVENT_STATE_HOVER);
     aState->isDefault = IsDefaultButton(aFrame);
     aState->canDefault = FALSE; // XXX fix me
     aState->depressed = FALSE;
 
     if (aWidgetType == NS_THEME_FOCUS_OUTLINE) {
       aState->disabled = FALSE;
       aState->active  = FALSE;
@@ -297,16 +299,25 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
       aState->depressed = TRUE; // see moz_gtk_entry_paint()
     } else if (aWidgetType == NS_THEME_BUTTON ||
                aWidgetType == NS_THEME_TOOLBARBUTTON ||
                aWidgetType == NS_THEME_DUALBUTTON ||
                aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN ||
                aWidgetType == NS_THEME_MENULIST ||
                aWidgetType == NS_THEME_MENULIST_BUTTON) {
       aState->active &= aState->inHover;
+    } else if (aWidgetType == NS_THEME_TREETWISTY ||
+               aWidgetType == NS_THEME_TREETWISTYOPEN) {
+      nsTreeBodyFrame *treeBodyFrame = do_QueryFrame(aFrame);
+      if (treeBodyFrame) {
+        const mozilla::AtomArray& atoms =
+          treeBodyFrame->GetPropertyArrayForCurrentDrawingItem();
+        aState->selected = atoms.Contains(nsGkAtoms::selected);
+        aState->inHover = atoms.Contains(nsGkAtoms::hover);
+      }
     }
 
     if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
       // For these widget types, some element (either a child or parent)
       // actually has element focus, so we check the focused attribute
       // to see whether to draw in the focused state.
       if (aWidgetType == NS_THEME_NUMBER_INPUT ||
           aWidgetType == NS_THEME_TEXTFIELD ||