Commit 957114a2 authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

overview: Add shadows to close button, title and window icon.

This requires some changes to WindowMiniView to make it more
customizeable as UX specifically only wants shadows on overview and not
alt-tab. Changes made were to apply effects on an icon supplied through
a window property, in this case a shadow.

Also, adding shadow to a label will shift the text. Since we want to
keep the text right aligned with the icon, make OverviewItemView
header layout code custom (previously was using the default from
WindowMiniView FlexLayout).

Test: manual
Fixed: 1028845
Change-Id: Ief8e9bbccc42fa198ff31729b735edc519d78270
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2128835Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755964}
parent 8d688b75
......@@ -22,6 +22,7 @@
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
......@@ -29,6 +30,7 @@
#include "ui/views/animation/ink_drop_mask.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/widget/widget.h"
......@@ -66,6 +68,21 @@ constexpr SkColor kCloseButtonInkDropRippleColor =
constexpr SkColor kCloseButtonInkDropRippleHighlightColor =
SkColorSetA(kCloseButtonColor, 0x14);
// Shadow values for shadow on overview header views.
constexpr int kTitleShadowBlur = 28;
constexpr SkColor kTitleShadowColor = SkColorSetA(SK_ColorBLACK, 82);
constexpr int kIconShadowBlur = 10;
constexpr SkColor kIconShadowColor = SkColorSetA(SK_ColorBLACK, 31);
gfx::ShadowValues GetTitleShadowValues() {
return {
gfx::ShadowValue(gfx::Vector2d(), kTitleShadowBlur, kTitleShadowColor)};
}
gfx::ShadowValues GetIconShadowValues() {
return {gfx::ShadowValue(gfx::Vector2d(), kIconShadowBlur, kIconShadowColor)};
}
// Animates |layer| from 0 -> 1 opacity if |visible| and 1 -> 0 opacity
// otherwise. The tween type differs for |visible| and if |visible| is true
// there is a slight delay before the animation begins. Does not animate if
......@@ -95,9 +112,14 @@ class OverviewCloseButton : public views::ImageButton {
explicit OverviewCloseButton(views::ButtonListener* listener)
: views::ImageButton(listener) {
SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
SetImage(
views::Button::STATE_NORMAL,
gfx::CreateVectorIcon(kOverviewWindowCloseIcon, kCloseButtonColor));
// Add a shadow to the close vector icon.
gfx::ImageSkia image_shadow =
gfx::ImageSkiaOperations::CreateImageWithDropShadow(
gfx::CreateVectorIcon(kOverviewWindowCloseIcon, kCloseButtonColor),
GetIconShadowValues());
SetImage(views::Button::STATE_NORMAL, image_shadow);
SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
SetMinimumImageSize(gfx::Size(kHeaderHeightDp, kHeaderHeightDp));
......@@ -107,11 +129,9 @@ class OverviewCloseButton : public views::ImageButton {
views::InstallFixedSizeCircleHighlightPathGenerator(
this, kCloseButtonInkDropRadiusDp);
}
~OverviewCloseButton() override = default;
OverviewCloseButton(const OverviewCloseButton&) = delete;
OverviewCloseButton& operator=(const OverviewCloseButton&) = delete;
~OverviewCloseButton() override = default;
// Resets the listener so that the listener can go out of scope.
void ResetListener() { listener_ = nullptr; }
......@@ -155,6 +175,11 @@ OverviewItemView::OverviewItemView(OverviewItem* overview_item,
std::make_unique<OverviewCloseButton>(overview_item_));
close_button_->SetPaintToLayer();
close_button_->layer()->SetFillsBoundsOpaquely(false);
// The button's image may be larger than |kHeaderHeightDp| due to added
// shadows.
close_button_->SetPreferredSize(gfx::Size(kHeaderHeightDp, kHeaderHeightDp));
title_label()->SetShadows(GetTitleShadowValues());
// Call this last as it calls |Layout()| which relies on the some of the other
// elements existing.
......@@ -167,6 +192,13 @@ OverviewItemView::OverviewItemView(OverviewItem* overview_item,
}
border_ptr()->set_extra_margin(kWindowMargin);
UpdateIconView();
// Do not use a layout manager for the header as its elements have shadows
// which need to overlap each other. Remove the FlexLayout set in
// WindowMiniView.
header_view()->SetLayoutManager(nullptr);
}
OverviewItemView::~OverviewItemView() = default;
......@@ -239,8 +271,7 @@ gfx::Rect OverviewItemView::GetHeaderBounds() const {
// additional padding would be equal to half the difference in width between
// the preferred width and the image size. The resulting padding would be that
// number plus the padding in the resource, in dips.
const int image_width =
close_button_->GetImage(views::ImageButton::STATE_NORMAL).width();
const int image_width = kIconSize.width();
const int close_button_width = close_button_->GetPreferredSize().width();
const int right_padding =
(close_button_width - image_width) / 2 + kCloseButtonIconMarginDp;
......@@ -291,6 +322,41 @@ gfx::Size OverviewItemView::GetPreviewViewSize() const {
return gfx::ToRoundedSize(target_size);
}
gfx::ImageSkia OverviewItemView::ModifyIcon(gfx::ImageSkia* image) const {
gfx::ImageSkia image_resized = gfx::ImageSkiaOperations::CreateResizedImage(
*image, skia::ImageOperations::RESIZE_BEST, kIconSize);
return gfx::ImageSkiaOperations::CreateImageWithDropShadow(
image_resized, GetIconShadowValues());
}
void OverviewItemView::Layout() {
WindowMiniView::Layout();
// Layout the header items. The icon, if available should be aligned left, the
// close button should be aligned right and the title should take up all the
// space in between but the text should be aligned left.
gfx::Rect header_bounds = header_view()->GetLocalBounds();
const int width = header_bounds.width();
const int height = header_bounds.height();
int x = 0;
if (icon_view()) {
const int icon_width = kIconSize.width();
icon_view()->SetBounds(x, 0, icon_width, height);
x += icon_width;
}
const gfx::Size close_button_size = close_button()->GetPreferredSize();
close_button()->SetBoundsRect(gfx::Rect(
gfx::Point(width - close_button_size.width(), 0), close_button_size));
// The title label text has shadow blur of |kTitleShadowBlur|. This will cause
// the preferred size of the title label to increase by |kTitleShadowBlur| / 2
// on all sides. To create the visual of the title label being
// |kHeaderPaddingDp| away from the icon (excluding the shadows), layout it
// somewhat on top of the icon.
x -= (kTitleShadowBlur / 2 - kHeaderPaddingDp);
title_label()->SetBounds(x, 0, width - close_button_size.width() - x, height);
}
views::View* OverviewItemView::GetView() {
return this;
}
......
......@@ -65,6 +65,8 @@ class ASH_EXPORT OverviewItemView
int GetMargin() const override;
gfx::Rect GetHeaderBounds() const override;
gfx::Size GetPreviewViewSize() const override;
gfx::ImageSkia ModifyIcon(gfx::ImageSkia* image) const override;
void Layout() override;
// OverviewHighlightController::OverviewHighlightableView:
views::View* GetView() override;
......
......@@ -159,6 +159,7 @@ class WindowCycleItemView : public WindowMiniView {
SetShowPreview(/*show=*/true);
UpdatePreviewRoundedCorners(/*show=*/true);
SetFocusBehavior(FocusBehavior::ALWAYS);
UpdateIconView();
}
~WindowCycleItemView() override = default;
......
......@@ -28,13 +28,6 @@ namespace {
// Foreground label color.
constexpr SkColor kLabelColor = SK_ColorWHITE;
// Horizontal padding for the label, on both sides.
constexpr int kHorizontalLabelPaddingDp = 12;
// The size in dp of the window icon shown on the overview window next to the
// title.
constexpr gfx::Size kIconSize{24, 24};
// The font delta of the window title.
constexpr int kLabelFontDelta = 2;
......@@ -46,6 +39,9 @@ constexpr SkColor kBackdropColor = SkColorSetA(SK_ColorWHITE, 0x24);
WindowMiniView::~WindowMiniView() = default;
constexpr gfx::Size WindowMiniView::kIconSize;
constexpr int WindowMiniView::kHeaderPaddingDp;
void WindowMiniView::SetBackdropVisibility(bool visible) {
if (!backdrop_view_ && !visible)
return;
......@@ -121,6 +117,11 @@ gfx::Size WindowMiniView::GetPreviewViewSize() const {
return preview_view_->GetPreferredSize();
}
gfx::ImageSkia WindowMiniView::ModifyIcon(gfx::ImageSkia* image) const {
return gfx::ImageSkiaOperations::CreateResizedImage(
*image, skia::ImageOperations::RESIZE_BEST, kIconSize);
}
WindowMiniView::WindowMiniView(aura::Window* source_window)
: source_window_(source_window) {
SetPaintToLayer();
......@@ -134,9 +135,7 @@ WindowMiniView::WindowMiniView(aura::Window* source_window)
views::BoxLayout* layout =
header_view_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
kHorizontalLabelPaddingDp));
UpdateIconView();
kHeaderPaddingDp));
title_label_ = header_view_->AddChildView(std::make_unique<views::Label>(
wm::GetTransientRoot(source_window_)->GetTitle()));
......@@ -154,6 +153,24 @@ WindowMiniView::WindowMiniView(aura::Window* source_window)
SetBorder(std::move(border));
}
void WindowMiniView::UpdateIconView() {
aura::Window* transient_root = wm::GetTransientRoot(source_window_);
// Prefer kAppIconKey over kWindowIconKey as the app icon is typically larger.
gfx::ImageSkia* icon = transient_root->GetProperty(aura::client::kAppIconKey);
if (!icon || icon->size().IsEmpty())
icon = transient_root->GetProperty(aura::client::kWindowIconKey);
if (!icon)
return;
if (!icon_view_) {
icon_view_ =
header_view_->AddChildViewAt(std::make_unique<views::ImageView>(), 0);
}
icon_view_->SetImage(ModifyIcon(icon));
icon_view_->SetSize(kIconSize);
}
gfx::Rect WindowMiniView::GetContentAreaBounds() const {
gfx::Rect bounds(GetContentsBounds());
bounds.Inset(0, kHeaderHeightDp, 0, 0);
......@@ -203,23 +220,4 @@ void WindowMiniView::OnWindowTitleChanged(aura::Window* window) {
title_label_->SetText(wm::GetTransientRoot(window)->GetTitle());
}
void WindowMiniView::UpdateIconView() {
aura::Window* transient_root = wm::GetTransientRoot(source_window_);
// Prefer kAppIconKey over kWindowIconKey as the app icon is typically larger.
gfx::ImageSkia* icon = transient_root->GetProperty(aura::client::kAppIconKey);
if (!icon || icon->size().IsEmpty())
icon = transient_root->GetProperty(aura::client::kWindowIconKey);
if (!icon)
return;
if (!icon_view_) {
icon_view_ =
header_view_->AddChildView(std::make_unique<views::ImageView>());
icon_view_->SetSize(kIconSize);
}
icon_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage(
*icon, skia::ImageOperations::RESIZE_BEST, kIconSize));
}
} // namespace ash
......@@ -6,7 +6,6 @@
#define ASH_WM_WINDOW_MINI_VIEW_H_
#include "ash/ash_export.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
......@@ -28,11 +27,18 @@ class WmHighlightItemBorder;
class ASH_EXPORT WindowMiniView : public views::View,
public aura::WindowObserver {
public:
static constexpr int kHeaderHeightDp = 40;
WindowMiniView(const WindowMiniView&) = delete;
WindowMiniView& operator=(const WindowMiniView&) = delete;
~WindowMiniView() override;
// Sets the visiblity of |backdrop_view_|. Creates it if it is null.
static constexpr int kHeaderHeightDp = 40;
// The size in dp of the window icon shown on the alt-tab/overview window next
// to the title.
static constexpr gfx::Size kIconSize = gfx::Size(24, 24);
// Padding between header items.
static constexpr int kHeaderPaddingDp = 12;
// Sets the visibility of |backdrop_view_|. Creates it if it is null.
void SetBackdropVisibility(bool visible);
// Creates or deletes |preview_view_| as needed.
......@@ -46,12 +52,17 @@ class ASH_EXPORT WindowMiniView : public views::View,
views::View* header_view() { return header_view_; }
views::Label* title_label() const { return title_label_; }
views::ImageView* icon_view() { return icon_view_; }
views::View* backdrop_view() { return backdrop_view_; }
WindowPreviewView* preview_view() const { return preview_view_; }
protected:
explicit WindowMiniView(aura::Window* source_window);
// Updates the icon view by creating it if necessary, and grabbing the correct
// image from |source_window_|.
void UpdateIconView();
WmHighlightItemBorder* border_ptr() { return border_ptr_; }
// Returns the bounds where the backdrop and preview should go.
......@@ -62,6 +73,9 @@ class ASH_EXPORT WindowMiniView : public views::View,
virtual int GetMargin() const;
virtual gfx::Rect GetHeaderBounds() const;
virtual gfx::Size GetPreviewViewSize() const;
// Allows subclasses to resize/add shadow to the image that will appear as the
// icon. Defaults to do resize the image to |kIconSize|.
virtual gfx::ImageSkia ModifyIcon(gfx::ImageSkia* image) const;
// views::View:
void Layout() override;
......@@ -75,10 +89,6 @@ class ASH_EXPORT WindowMiniView : public views::View,
void OnWindowTitleChanged(aura::Window* window) override;
private:
// Updates the icon view by creating it if necessary, and grabbing the correct
// image from |source_window_|.
void UpdateIconView();
// The window this class is meant to be a header for. This class also may
// optionally show a mirrored view of this window.
aura::Window* source_window_;
......@@ -100,8 +110,6 @@ class ASH_EXPORT WindowMiniView : public views::View,
WindowPreviewView* preview_view_ = nullptr;
ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this};
DISALLOW_COPY_AND_ASSIGN(WindowMiniView);
};
} // namespace ash
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment