Index: ash/common/system/tray/tray_details_view.cc |
diff --git a/ash/common/system/tray/tray_details_view.cc b/ash/common/system/tray/tray_details_view.cc |
index 7086c0c36a0a796868e5f9172b4acecea8a4cd17..05c0a204f5bddf88a75054e392c26a53a06b1229 100644 |
--- a/ash/common/system/tray/tray_details_view.cc |
+++ b/ash/common/system/tray/tray_details_view.cc |
@@ -100,6 +100,26 @@ class ScrollContentsView : public views::View, |
PositionHeaderRows(); |
} |
+ void ReorderChildLayers(ui::Layer* parent_layer) override { |
+ views::View::ReorderChildLayers(parent_layer); |
+ ui::Layer* topmost_layer = TopmostLayer(this, parent_layer); |
+ if (!topmost_layer) |
+ return; |
+ |
+ // Keep the sticky headers with layers above the rest of the children's |
+ // layers. Make sure to avoid changing the stacking order of the layers that |
+ // are children of |parent_layer| but do not belong to the same parent view. |
+ // Note: this assumes that all views that have id=VIEW_ID_STICKY_HEADER have |
+ // a layer. |
+ for (int i = child_count() - 1; i >= 0; --i) { |
+ View* child = child_at(i); |
+ if (child->id() == VIEW_ID_STICKY_HEADER && |
+ child->layer() != topmost_layer) { |
+ parent_layer->StackAbove(child->layer(), topmost_layer); |
+ } |
+ } |
+ } |
+ |
void ViewHierarchyChanged( |
const ViewHierarchyChangedDetails& details) override { |
if (!details.is_add && details.parent == this) { |
@@ -169,24 +189,31 @@ class ScrollContentsView : public views::View, |
Header* previous_header = nullptr; |
for (auto& header : base::Reversed(headers_)) { |
views::View* header_view = header.view; |
- header.draw_separator_below = false; |
+ bool draw_separator_below = false; |
if (header.natural_offset >= scroll_offset) { |
previous_header = &header; |
header_view->SetY(header.natural_offset); |
- continue; |
- } |
- if (previous_header && |
- previous_header->view->y() <= scroll_offset + header_view->height()) { |
- // Lower header displacing the header above. |
- header.draw_separator_below = true; |
- header_view->SetY(previous_header->view->y() - header_view->height()); |
} else { |
- // A header becomes sticky. |
- header_view->SetY(scroll_offset); |
- header_view->Layout(); |
- header_view->SchedulePaint(); |
+ if (previous_header && |
+ previous_header->view->y() <= |
+ scroll_offset + header_view->height()) { |
+ // Lower header displacing the header above. |
+ draw_separator_below = true; |
+ header_view->SetY(previous_header->view->y() - header_view->height()); |
+ } else { |
+ // A header becomes sticky. |
+ header_view->SetY(scroll_offset); |
+ header_view->Layout(); |
+ header_view->SchedulePaint(); |
+ } |
+ } |
+ if (header.draw_separator_below != draw_separator_below) { |
+ header.draw_separator_below = draw_separator_below; |
+ TrayPopupUtils::ShowStickyHeaderSeparator(header_view, |
+ draw_separator_below); |
} |
- break; |
+ if (header.natural_offset < scroll_offset) |
+ break; |
} |
} |
@@ -197,22 +224,11 @@ class ScrollContentsView : public views::View, |
bool PaintDelineation(const Header& header, const ui::PaintContext& context) { |
const View* view = header.view; |
- // If the header is where it normally belongs, draw nothing. |
- if (view->y() == header.natural_offset) |
+ // If the header is where it normally belongs or If the header is pushed by |
+ // a header directly below it, draw nothing. |
+ if (view->y() == header.natural_offset || header.draw_separator_below) |
return false; |
- // If the header is pushed by a header directly below it, draw a separator. |
- if (header.draw_separator_below) { |
- // TODO(estade): look better at 1.5x scale. |
- ui::PaintRecorder recorder(context, size()); |
- gfx::Canvas* canvas = recorder.canvas(); |
- gfx::Rect separator = view->bounds(); |
- separator.set_y(separator.bottom() - kSeparatorWidth); |
- separator.set_height(kSeparatorWidth); |
- canvas->FillRect(separator, kSeparatorColor); |
- return false; |
- } |
- |
// Otherwise, draw a shadow below. |
DrawShadow(context, |
gfx::Rect(0, 0, view->width(), view->bounds().bottom())); |
@@ -234,6 +250,25 @@ class ScrollContentsView : public views::View, |
canvas->DrawRect(shadowed_area, paint); |
} |
+ // Recursively iterates through children to return the child layer that is |
+ // stacked at the top. Only considers layers that are direct |parent_layer|'s |
+ // children. |
+ ui::Layer* TopmostLayer(views::View* view, ui::Layer* parent_layer) { |
+ DCHECK(parent_layer); |
+ // Iterate backwards through the children to find the topmost layer. |
+ for (int i = view->child_count() - 1; i >= 0; --i) { |
+ views::View* child = view->child_at(i); |
+ ui::Layer* layer = TopmostLayer(child, parent_layer); |
+ if (layer) |
+ return layer; |
+ } |
+ if (view->layer() && view->layer() != parent_layer && |
+ view->layer()->parent() == parent_layer) { |
+ return view->layer(); |
+ } |
+ return nullptr; |
+ } |
+ |
views::BoxLayout* box_layout_; |
// Header child views that stick to the top of visible viewport when scrolled. |