blob: fec7bdda219bccbe2399605b05fa4657ddd676a5 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/wm/window_mini_view.h"
#include "ash/wm/overview/rounded_rect_view.h"
#include "ash/wm/window_preview_view.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/wm/core/window_util.h"
namespace ash {
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;
// Values of the backdrop.
constexpr int kBackdropRoundingDp = 4;
constexpr SkColor kBackdropColor = SkColorSetA(SK_ColorWHITE, 0x24);
} // namespace
WindowMiniView::~WindowMiniView() = default;
void WindowMiniView::SetBackdropVisibility(bool visible) {
if (!backdrop_view_ && !visible)
return;
if (!backdrop_view_) {
backdrop_view_ = new RoundedRectView(kBackdropRoundingDp, kBackdropColor);
backdrop_view_->set_can_process_events_within_subtree(false);
AddChildViewOf(this, backdrop_view_);
Layout();
}
backdrop_view_->SetVisible(visible);
}
void WindowMiniView::SetShowPreview(bool show) {
if (show == !!preview_view_)
return;
if (!show) {
RemoveChildView(preview_view_);
delete preview_view_;
preview_view_ = nullptr;
return;
}
if (!source_window_)
return;
preview_view_ = new WindowPreviewView(source_window_,
/*trilinear_filtering_on_init=*/false);
AddChildViewOf(this, preview_view_);
Layout();
}
int WindowMiniView::GetMargin() const {
return 0;
}
gfx::Rect WindowMiniView::GetHeaderBounds() const {
return gfx::Rect(GetLocalBounds().width(), kHeaderHeightDp);
}
gfx::Size WindowMiniView::GetPreviewViewSize() const {
DCHECK(preview_view_);
return preview_view_->GetPreferredSize();
}
WindowMiniView::WindowMiniView(aura::Window* source_window,
bool views_should_paint_to_layers)
: source_window_(source_window),
views_should_paint_to_layers_(views_should_paint_to_layers) {
window_observer_.Add(source_window);
header_view_ = new views::View();
views::BoxLayout* layout =
header_view_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
kHorizontalLabelPaddingDp));
AddChildViewOf(this, header_view_);
// Display the icon and title of the transient root.
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 && !icon->size().IsEmpty()) {
image_view_ = new views::ImageView();
image_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage(
*icon, skia::ImageOperations::RESIZE_BEST, kIconSize));
image_view_->SetSize(kIconSize);
AddChildViewOf(header_view_, image_view_);
}
title_label_ = new views::Label(transient_root->GetTitle());
title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
title_label_->SetAutoColorReadabilityEnabled(false);
title_label_->SetEnabledColor(kLabelColor);
title_label_->SetSubpixelRenderingEnabled(false);
title_label_->SetFontList(gfx::FontList().Derive(
kLabelFontDelta, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM));
AddChildViewOf(header_view_, title_label_);
layout->SetFlexForView(title_label_, 1);
}
void WindowMiniView::AddChildViewOf(views::View* parent, views::View* child) {
parent->AddChildView(child);
if (views_should_paint_to_layers_) {
child->SetPaintToLayer();
child->layer()->SetFillsBoundsOpaquely(false);
}
}
void WindowMiniView::Layout() {
const int margin = GetMargin();
gfx::Rect bounds(GetLocalBounds());
bounds.Inset(margin, margin);
if (backdrop_view_) {
gfx::Rect backdrop_bounds = bounds;
backdrop_bounds.Inset(0, kHeaderHeightDp, 0, 0);
backdrop_view_->SetBoundsRect(backdrop_bounds);
}
if (preview_view_) {
gfx::Rect preview_bounds = bounds;
preview_bounds.Inset(0, kHeaderHeightDp, 0, 0);
preview_bounds.ClampToCenteredSize(GetPreviewViewSize());
preview_view_->SetBoundsRect(preview_bounds);
}
header_view_->SetBoundsRect(GetHeaderBounds());
}
void WindowMiniView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ax::mojom::Role::kWindow;
node_data->SetName(title_label_->GetText());
}
void WindowMiniView::OnWindowDestroying(aura::Window* window) {
if (window != source_window_)
return;
window_observer_.RemoveAll();
source_window_ = nullptr;
SetShowPreview(false);
}
void WindowMiniView::OnWindowTitleChanged(aura::Window* window) {
title_label_->SetText(wm::GetTransientRoot(window)->GetTitle());
}
} // namespace ash