Skip to content

Commit

Permalink
Added curtain mode view for power button widget.
Browse files Browse the repository at this point in the history
This change adds a new view for the widget displayed when the power
button is pressed and the device is in curtain mode.

Screenshot: http://screen/fLWunZ5cNQFiQJm.
Bug: b/268174075
Change-Id: I1ba0afda6717c6aa02f942adaac478df985f1b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4239885
Reviewed-by: Xiaoqian Dai <xdai@chromium.org>
Commit-Queue: Ashutosh Singhal <macinashutosh@google.com>
Reviewed-by: Jeroen Dhollander <jeroendh@google.com>
Cr-Commit-Position: refs/heads/main@{#1118802}
  • Loading branch information
Ashutosh Singhal authored and Chromium LUCI CQ committed Mar 17, 2023
1 parent 681ab80 commit 8805075
Show file tree
Hide file tree
Showing 13 changed files with 461 additions and 90 deletions.
4 changes: 4 additions & 0 deletions ash/BUILD.gn
Expand Up @@ -1739,6 +1739,8 @@ component("ash") {
"system/power/power_button_controller.h",
"system/power/power_button_display_controller.cc",
"system/power/power_button_display_controller.h",
"system/power/power_button_menu_curtain_view.cc",
"system/power/power_button_menu_curtain_view.h",
"system/power/power_button_menu_item_view.cc",
"system/power/power_button_menu_item_view.h",
"system/power/power_button_menu_metrics_type.cc",
Expand All @@ -1747,6 +1749,8 @@ component("ash") {
"system/power/power_button_menu_screen_view.h",
"system/power/power_button_menu_view.cc",
"system/power/power_button_menu_view.h",
"system/power/power_button_menu_view_util.cc",
"system/power/power_button_menu_view_util.h",
"system/power/power_button_screenshot_controller.cc",
"system/power/power_button_screenshot_controller.h",
"system/power/power_event_observer.cc",
Expand Down
14 changes: 12 additions & 2 deletions ash/ash_strings.grd
Expand Up @@ -6373,6 +6373,16 @@ New install
<message name="IDS_ASH_PAGINATION_RIGHT_ARROW_TOOLTIP" desc="The tooltip text used for pagination right arrow button." >
Next page
</message>
</messages>
</release>

<!-- Power menu widget for security curtain -->
<message name="IDS_ASH_CURTAIN_POWER_WIDGET_TITLE" desc="Title text displayed in the dialog when the power button is pressed and the remote admin session on ChromeOs device will end.">
Shut down the device?
</message>
<message name="IDS_ASH_CURTAIN_POWER_WIDGET_DESCRIPTION" desc="Detailed description displayed to inform the user that the device will be shut down and remote admin session will be end if they press the power button again. The linebreak should NOT be removed from the string.">
Once shut down, the administrator will be logged out and won't be able to control your device.

To shut down the device, press and hold the power button on the device again.
</message>
</messages>
</release>
</grit>
@@ -0,0 +1 @@
7f0989c1fd1790b3e21963c5d51b4fdf3bef1c66
@@ -0,0 +1 @@
7f0989c1fd1790b3e21963c5d51b4fdf3bef1c66
3 changes: 2 additions & 1 deletion ash/system/power/power_button_controller_unittest.cc
Expand Up @@ -14,6 +14,7 @@
#include "ash/system/power/power_button_controller_test_api.h"
#include "ash/system/power/power_button_menu_item_view.h"
#include "ash/system/power/power_button_menu_view.h"
#include "ash/system/power/power_button_menu_view_util.h"
#include "ash/system/power/power_button_test_base.h"
#include "ash/test_media_client.h"
#include "ash/touch/touch_devices_controller.h"
Expand Down Expand Up @@ -1170,7 +1171,7 @@ TEST_P(PowerButtonControllerWithPositionTest,
EXPECT_TRUE(IsMenuCentered());
TapToDismissPowerButtonMenu();

int animation_transform = PowerButtonMenuView::kMenuViewTransformDistanceDp;
int animation_transform = kPowerButtonMenuTransformDistanceDp;
EnableTabletMode(true);
EXPECT_TRUE(IsTabletMode());
OpenPowerButtonMenu();
Expand Down
190 changes: 190 additions & 0 deletions ash/system/power/power_button_menu_curtain_view.cc
@@ -0,0 +1,190 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/power/power_button_menu_curtain_view.h"

#include <memory>

#include "ash/public/cpp/style/color_provider.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "ash/style/ash_color_provider.h"
#include "ash/style/system_shadow.h"
#include "ash/system/power/power_button_menu_view_util.h"
#include "base/check_deref.h"
#include "chromeos/ui/vector_icons/vector_icons.h"
#include "ui/accessibility/ax_enums.mojom-shared.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/highlight_border.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/layout/flex_layout_view.h"
#include "ui/views/metadata/view_factory_internal.h"
#include "ui/views/style/typography.h"
#include "ui/views/view_class_properties.h"

namespace ash {

namespace {

using views::Builder;
using views::FlexLayoutView;
using views::ImageView;
using views::LayoutOrientation;

constexpr gfx::Size kEnterpriseIconSize(20, 20);

// Bottom margin for the enterprise icon.
constexpr int kIconBottomMargin = 30;

// Preferred width of the dialog.
constexpr int kWidth = 400;

// Inner padding for the widget.
constexpr int kHorizontalPadding = 25;
constexpr int kVerticalPadding = 20;

// Bottom margin for the widget title.
constexpr int kTitleBottomMargin = 35;

// Line height for the widget content text.
constexpr int kContentLineHeight = 12;

views::FlexSpecification FullFlex() {
return views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
views::MaximumFlexSizeRule::kUnbounded)
.WithWeight(1);
}

gfx::ImageSkia EnterpriseIcon(const ColorProvider& color_provider) {
return gfx::CreateVectorIcon(
chromeos::kEnterpriseIcon,
color_provider.GetContentLayerColor(
ash::AshColorProvider::ContentLayerType::kIconColorPrimary));
}

std::u16string TitleText() {
return l10n_util::GetStringUTF16(IDS_ASH_CURTAIN_POWER_WIDGET_TITLE);
}

std::u16string MessageText() {
return l10n_util::GetStringUTF16(IDS_ASH_CURTAIN_POWER_WIDGET_DESCRIPTION);
}

} // namespace

PowerButtonMenuCurtainView::PowerButtonMenuCurtainView() {
SetPaintToLayer();
SetBorder(std::make_unique<views::HighlightBorder>(
kPowerButtonMenuCornerRadius, kPowerButtonMenuBorderType,
/*use_light_colors=*/false));
SetBackground(
views::CreateThemedSolidBackground(kPowerButtonMenuBackgroundColorId));

layer()->SetFillsBoundsOpaquely(false);
layer()->SetRoundedCornerRadius(
gfx::RoundedCornersF(kPowerButtonMenuCornerRadius));
layer()->SetBackgroundBlur(kPowerButtonMenuBlurType);
GetViewAccessibility().OverrideRole(ax::mojom::Role::kDialog);
Initialize();

// Create a system shadow for current view.
shadow_ = ash::SystemShadow::CreateShadowOnNinePatchLayerForView(
this, ash::SystemShadow::Type::kElevation12);
shadow_->SetRoundedCornerRadius(kPowerButtonMenuCornerRadius);
}

PowerButtonMenuCurtainView::~PowerButtonMenuCurtainView() = default;

void PowerButtonMenuCurtainView::ScheduleShowHideAnimation(bool show) {
// Set initial state.
SetVisible(true);

// Calculate transform of menu view and shadow bounds.
gfx::Transform transform;
if (show) {
transform.Translate(0, kPowerButtonMenuTransformDistanceDp);
}

SetLayerAnimation(layer(), this, show, transform);
SetLayerAnimation(shadow_->GetLayer(), nullptr, show, transform);
}

void PowerButtonMenuCurtainView::Initialize() {
// TODO(b/272826467) Update to views::View::GetColorProvider().
const ColorProvider& color_provider = CHECK_DEREF(ColorProvider::Get());

Builder<FlexLayoutView>(this)
.SetOrientation(views::LayoutOrientation::kHorizontal)
.AddChildren(
Builder<FlexLayoutView>()
.SetOrientation(LayoutOrientation::kVertical)
.SetProperty(views::kFlexBehaviorKey, FullFlex())
.AddChildren(
// Enterprise icon
Builder<ImageView>()
.SetImage(EnterpriseIcon(color_provider))
.SetImageSize(kEnterpriseIconSize)
.SetSize(kEnterpriseIconSize)
.SetHorizontalAlignment(ImageView::Alignment::kLeading)
.SetProperty(views::kFlexBehaviorKey, FullFlex())
.SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(
kVerticalPadding, kHorizontalPadding,
kIconBottomMargin, kHorizontalPadding)),
// Title
Builder<views::Label>()
.SetText(TitleText())
.SetTextStyle(views::style::STYLE_EMPHASIZED)
.SetTextContext(views::style::CONTEXT_DIALOG_TITLE)
.SetHorizontalAlignment(
gfx::HorizontalAlignment::ALIGN_LEFT)
.SetMultiLine(true)
.SetEnabledColor(color_provider.GetContentLayerColor(
ColorProvider::ContentLayerType::kTextColorPrimary))
.SetProperty(views::kFlexBehaviorKey, FullFlex())
.SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, kHorizontalPadding,
kTitleBottomMargin,
kHorizontalPadding))
.SetMaximumWidth(kWidth),
// Description
Builder<views::Label>()
.SetText(MessageText())
.SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT)
.SetHorizontalAlignment(
gfx::HorizontalAlignment::ALIGN_LEFT)
.SetMultiLine(true)
.SetEnabledColor(color_provider.GetContentLayerColor(
ColorProvider::ContentLayerType::kTextColorPrimary))
.SetProperty(views::kFlexBehaviorKey, FullFlex())
.SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, kHorizontalPadding,
kVerticalPadding,
kHorizontalPadding))
.SetLineHeight(kContentLineHeight)
.SetMaximumWidth(kWidth)))
.BuildChildren();
}

void PowerButtonMenuCurtainView::OnImplicitAnimationsCompleted() {
if (layer()->opacity() == 0.f) {
SetVisible(false);
}
}

BEGIN_METADATA(PowerButtonMenuCurtainView, views::FlexLayoutView)
END_METADATA

} // namespace ash
45 changes: 45 additions & 0 deletions ash/system/power/power_button_menu_curtain_view.h
@@ -0,0 +1,45 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_SYSTEM_POWER_POWER_BUTTON_MENU_CURTAIN_VIEW_H_
#define ASH_SYSTEM_POWER_POWER_BUTTON_MENU_CURTAIN_VIEW_H_

#include "ash/ash_export.h"
#include "ash/style/system_shadow.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/flex_layout_view.h"

namespace ash {

// PowerButtonMenuCurtainView is displayed inside the power menu popup when the
// power button is pressed while the security curtain is present.
class ASH_EXPORT PowerButtonMenuCurtainView
: public views::FlexLayoutView,
public ui::ImplicitAnimationObserver {
public:
PowerButtonMenuCurtainView();
PowerButtonMenuCurtainView(const PowerButtonMenuCurtainView&) = delete;
PowerButtonMenuCurtainView& operator=(const PowerButtonMenuCurtainView&) =
delete;
~PowerButtonMenuCurtainView() override;

void ScheduleShowHideAnimation(bool show);

METADATA_HEADER(PowerButtonMenuCurtainView);

private:
void Initialize();

// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override;

std::unique_ptr<ash::SystemShadow> shadow_;
};

} // namespace ash

#endif // ASH_SYSTEM_POWER_POWER_BUTTON_MENU_CURTAIN_VIEW_H_

0 comments on commit 8805075

Please sign in to comment.