Commit fed77b0e authored by minch's avatar minch Committed by Commit Bot

back_gesture: Add contextual nudge.

This is an initial cl for the contextual nudge of the back gesture.

See screenshot: https://screenshot.googleplex.com/CAagJhL5f7z

Following up work:
1. Add animation for the nudge based on the spec.
2. Add the condition to show the nudge.

Bug: 1009005b
Change-Id: I28471c9f5281b0d1af8e16f3598d802a803d91f6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2040059Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Min Chen <minch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#739165}
parent aa29b015
...@@ -1176,6 +1176,8 @@ component("ash") { ...@@ -1176,6 +1176,8 @@ component("ash") {
"wm/fullscreen_window_finder.h", "wm/fullscreen_window_finder.h",
"wm/gestures/back_gesture/back_gesture_affordance.cc", "wm/gestures/back_gesture/back_gesture_affordance.cc",
"wm/gestures/back_gesture/back_gesture_affordance.h", "wm/gestures/back_gesture/back_gesture_affordance.h",
"wm/gestures/back_gesture/back_gesture_contextual_nudge.cc",
"wm/gestures/back_gesture/back_gesture_contextual_nudge.h",
"wm/gestures/back_gesture/back_gesture_event_handler.cc", "wm/gestures/back_gesture/back_gesture_event_handler.cc",
"wm/gestures/back_gesture/back_gesture_event_handler.h", "wm/gestures/back_gesture/back_gesture_event_handler.h",
"wm/gestures/back_gesture/back_gesture_metrics.cc", "wm/gestures/back_gesture/back_gesture_metrics.cc",
......
...@@ -2268,6 +2268,11 @@ This file contains the strings for ash. ...@@ -2268,6 +2268,11 @@ This file contains the strings for ash.
<message name="IDS_ASH_VIRTUAL_DESKS_ALERT_WINDOW_MOVED_FROM_ACTIVE_DESK" desc="A window in active desk got be moved to another virtual desk."> <message name="IDS_ASH_VIRTUAL_DESKS_ALERT_WINDOW_MOVED_FROM_ACTIVE_DESK" desc="A window in active desk got be moved to another virtual desk.">
Window <ph name="WINDOW_TITLE">$1<ex>Files</ex></ph> moved from Desk <ph name="ACTIVE_DESK">$2</ph> to Desk <ph name="TARGET_DESK">$3</ph> Window <ph name="WINDOW_TITLE">$1<ex>Files</ex></ph> moved from Desk <ph name="ACTIVE_DESK">$2</ph> to Desk <ph name="TARGET_DESK">$3</ph>
</message> </message>
<!-- Back gesture -->
<message name="IDS_ASH_BACK_GESTURE_CONTEXTUAL_NUDGE" desc="Information shown in the suggestion label for the contextual nudge of the back gesture in tablet mode">
Swipe from the left to go back
</message>
</messages> </messages>
</release> </release>
</grit> </grit>
// Copyright 2020 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/gestures/back_gesture/back_gesture_contextual_nudge.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/views/controls/label.h"
#include "ui/views/view.h"
namespace ash {
namespace {
// Width of the contextual nudge.
constexpr int kBackgroundWidth = 160;
// Color of the contextual nudge.
constexpr SkColor kBackgroundColor = SkColorSetA(SK_ColorBLACK, 153); // 60%
// Radius of the circle in the middle of the contextual nudge.
constexpr int kCircleRadius = 20;
// Color of the circle in the middle of the contextual nudge.
constexpr SkColor kCircleColor = SK_ColorWHITE;
// Width of the circle that inside the screen at the beginning.
constexpr int kCircleInsideScreenWidth = 12;
// Padding between the circle and the label.
constexpr int kPaddingBetweenCircleAndLabel = 8;
// Color of the label.
constexpr SkColor kLabelColor = gfx::kGoogleGrey200;
// Width and height of the label.
constexpr int kLabelWidth = 80;
constexpr int kLabelHeight = 80;
std::unique_ptr<views::Widget> CreateWidget() {
auto widget = std::make_unique<views::Widget>();
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
params.z_order = ui::ZOrderLevel::kFloatingWindow;
params.accept_events = false;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.name = "BackGestureContextualNudge";
params.layer_type = ui::LAYER_NOT_DRAWN;
params.parent = Shell::GetPrimaryRootWindow()->GetChildById(
kShellWindowId_AlwaysOnTopContainer);
widget->Init(std::move(params));
// TODO(crbug.com/1009005): Get the bounds of the display that should show the
// nudge, which may based on the conditions to show the nudge.
gfx::Rect widget_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
widget_bounds.set_width(kBackgroundWidth);
widget->SetBounds(widget_bounds);
return widget;
}
class GradientLayerDelegate : public ui::LayerDelegate {
public:
GradientLayerDelegate() : layer_(ui::LAYER_TEXTURED) {
layer_.set_delegate(this);
layer_.SetFillsBoundsOpaquely(false);
}
~GradientLayerDelegate() override { layer_.set_delegate(nullptr); }
ui::Layer* layer() { return &layer_; }
private:
// ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override {
const gfx::Size size = layer()->size();
ui::PaintRecorder recorder(context, size);
cc::PaintFlags flags;
flags.setBlendMode(SkBlendMode::kSrc);
flags.setAntiAlias(false);
flags.setShader(
gfx::CreateGradientShader(gfx::Point(), gfx::Point(size.width(), 0),
SK_ColorBLACK, SK_ColorTRANSPARENT));
recorder.canvas()->DrawRect(gfx::Rect(gfx::Point(), size), flags);
}
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override {}
ui::Layer layer_;
GradientLayerDelegate(const GradientLayerDelegate&) = delete;
GradientLayerDelegate& operator=(const GradientLayerDelegate&) = delete;
};
class ContextualNudgeView : public views::View {
public:
ContextualNudgeView() : label_(new views::Label) {
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
gradient_layer_delegate_ = std::make_unique<GradientLayerDelegate>();
layer()->SetMaskLayer(gradient_layer_delegate_->layer());
label_->SetBackgroundColor(SK_ColorTRANSPARENT);
label_->SetEnabledColor(kLabelColor);
label_->SetText(
l10n_util::GetStringUTF16(IDS_ASH_BACK_GESTURE_CONTEXTUAL_NUDGE));
label_->SetMultiLine(true);
label_->SetFontList(
gfx::FontList().DeriveWithWeight(gfx::Font::Weight::MEDIUM));
AddChildView(label_);
}
~ContextualNudgeView() override = default;
private:
// views::View:
void Layout() override {
const gfx::Rect bounds = GetLocalBounds();
gradient_layer_delegate_->layer()->SetBounds(bounds);
gfx::Rect label_rect(bounds);
label_rect.ClampToCenteredSize(gfx::Size(kLabelWidth, kLabelHeight));
label_rect.set_x(bounds.left_center().x() + kCircleInsideScreenWidth +
kPaddingBetweenCircleAndLabel);
label_->SetBoundsRect(label_rect);
}
// views::View:
void OnPaint(gfx::Canvas* canvas) override {
views::View::OnPaint(canvas);
canvas->DrawColor(kBackgroundColor);
// Draw the circle.
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(kCircleColor);
gfx::Point left_center = layer()->bounds().left_center();
canvas->DrawCircle(
gfx::Point(kCircleInsideScreenWidth - kCircleRadius, left_center.y()),
kCircleRadius, flags);
}
std::unique_ptr<GradientLayerDelegate> gradient_layer_delegate_;
views::Label* label_ = nullptr;
ContextualNudgeView(const ContextualNudgeView&) = delete;
ContextualNudgeView& operator=(const ContextualNudgeView&) = delete;
};
} // namespace
BackGestureContextualNudge::BackGestureContextualNudge() {
if (!widget_)
widget_ = CreateWidget();
widget_->SetContentsView(new ContextualNudgeView());
widget_->Show();
}
BackGestureContextualNudge::~BackGestureContextualNudge() = default;
} // namespace ash
// Copyright 2020 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.
#ifndef ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_CONTEXTUAL_NUDGE_H_
#define ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_CONTEXTUAL_NUDGE_H_
#include <memory>
#include "ui/views/widget/widget.h"
namespace ash {
class BackGestureContextualNudge {
public:
BackGestureContextualNudge();
~BackGestureContextualNudge();
private:
std::unique_ptr<views::Widget> widget_;
BackGestureContextualNudge(const BackGestureContextualNudge&) = delete;
BackGestureContextualNudge& operator=(const BackGestureContextualNudge&) =
delete;
};
} // namespace ash
#endif // ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_CONTEXTUAL_NUDGE_H_
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