| // 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/login/ui/pin_request_view.h" |
| |
| #include "ash/login/ui/arrow_button_view.h" |
| #include "ash/login/ui/login_pin_view.h" |
| #include "ash/login/ui/pin_request_widget.h" |
| #include "ash/public/cpp/shelf_config.h" |
| #include "ash/resources/vector_icons/vector_icons.h" |
| #include "ash/shell.h" |
| #include "ash/strings/grit/ash_strings.h" |
| #include "ash/style/ash_color_provider.h" |
| #include "ash/wallpaper/wallpaper_controller_impl.h" |
| #include "ui/accessibility/ax_enums.mojom.h" |
| #include "ui/accessibility/ax_node_data.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/color_analysis.h" |
| #include "ui/gfx/color_utils.h" |
| #include "ui/gfx/paint_vector_icon.h" |
| #include "ui/views/background.h" |
| #include "ui/views/controls/button/label_button.h" |
| #include "ui/views/controls/focus_ring.h" |
| #include "ui/views/controls/label.h" |
| #include "ui/views/layout/box_layout.h" |
| #include "ui/views/layout/fill_layout.h" |
| #include "ui/views/vector_icons.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| constexpr int kPinRequestViewWidthDp = 340; |
| constexpr int kPinKeyboardHeightDp = 224; |
| constexpr int kPinRequestViewRoundedCornerRadiusDp = 8; |
| constexpr int kPinRequestViewVerticalInsetDp = 8; |
| // Inset for all elements except the back button. |
| constexpr int kPinRequestViewMainHorizontalInsetDp = 36; |
| // Minimum inset (= back button inset). |
| constexpr int kPinRequestViewHorizontalInsetDp = 8; |
| |
| constexpr int kCrossSizeDp = 20; |
| constexpr int kBackButtonSizeDp = 36; |
| constexpr int kLockIconSizeDp = 24; |
| constexpr int kBackButtonLockIconVerticalOverlapDp = 8; |
| constexpr int kHeaderHeightDp = |
| kBackButtonSizeDp + kLockIconSizeDp - kBackButtonLockIconVerticalOverlapDp; |
| |
| constexpr int kIconToTitleDistanceDp = 24; |
| constexpr int kTitleToDescriptionDistanceDp = 8; |
| constexpr int kDescriptionToAccessCodeDistanceDp = 32; |
| constexpr int kAccessCodeToPinKeyboardDistanceDp = 16; |
| constexpr int kPinKeyboardToFooterDistanceDp = 16; |
| constexpr int kSubmitButtonBottomMarginDp = 28; |
| |
| constexpr int kTitleFontSizeDeltaDp = 4; |
| constexpr int kTitleLineWidthDp = 268; |
| constexpr int kTitleLineHeightDp = 24; |
| constexpr int kTitleMaxLines = 4; |
| constexpr int kDescriptionFontSizeDeltaDp = 0; |
| constexpr int kDescriptionLineWidthDp = 268; |
| constexpr int kDescriptionTextLineHeightDp = 18; |
| constexpr int kDescriptionMaxLines = 4; |
| |
| constexpr int kArrowButtonSizeDp = 48; |
| |
| constexpr int kPinRequestViewMinimumHeightDp = |
| kPinRequestViewMainHorizontalInsetDp + kLockIconSizeDp + |
| kIconToTitleDistanceDp + kTitleToDescriptionDistanceDp + |
| kDescriptionToAccessCodeDistanceDp + |
| AccessCodeInput::kAccessCodeInputFieldHeightDp + |
| kAccessCodeToPinKeyboardDistanceDp + kPinKeyboardToFooterDistanceDp + |
| kArrowButtonSizeDp + kPinRequestViewMainHorizontalInsetDp; // = 266 |
| |
| constexpr int kAlpha70Percent = 178; |
| constexpr int kAlpha74Percent = 189; |
| |
| constexpr SkColor kTextColor = SK_ColorWHITE; |
| constexpr SkColor kErrorColor = gfx::kGoogleRed300; |
| constexpr SkColor kArrowButtonColor = SkColorSetARGB(0x2B, 0xFF, 0xFF, 0xFF); |
| |
| bool IsTabletMode() { |
| return Shell::Get()->tablet_mode_controller()->InTabletMode(); |
| } |
| |
| } // namespace |
| |
| PinRequest::PinRequest() = default; |
| PinRequest::PinRequest(PinRequest&&) = default; |
| PinRequest& PinRequest::operator=(PinRequest&&) = default; |
| PinRequest::~PinRequest() = default; |
| |
| // Label button that displays focus ring. |
| class PinRequestView::FocusableLabelButton : public views::LabelButton { |
| public: |
| FocusableLabelButton(views::ButtonListener* listener, |
| const base::string16& text) |
| : views::LabelButton(listener, text) { |
| SetInstallFocusRingOnFocus(true); |
| focus_ring()->SetColor(ShelfConfig::Get()->shelf_focus_border_color()); |
| } |
| |
| FocusableLabelButton(const FocusableLabelButton&) = delete; |
| FocusableLabelButton& operator=(const FocusableLabelButton&) = delete; |
| ~FocusableLabelButton() override = default; |
| }; |
| |
| PinRequestView::TestApi::TestApi(PinRequestView* view) : view_(view) { |
| DCHECK(view_); |
| } |
| |
| PinRequestView::TestApi::~TestApi() = default; |
| |
| LoginButton* PinRequestView::TestApi::back_button() { |
| return view_->back_button_; |
| } |
| |
| views::Label* PinRequestView::TestApi::title_label() { |
| return view_->title_label_; |
| } |
| |
| views::Label* PinRequestView::TestApi::description_label() { |
| return view_->description_label_; |
| } |
| |
| views::View* PinRequestView::TestApi::access_code_view() { |
| return view_->access_code_view_; |
| } |
| |
| views::LabelButton* PinRequestView::TestApi::help_button() { |
| return view_->help_button_; |
| } |
| |
| ArrowButtonView* PinRequestView::TestApi::submit_button() { |
| return view_->submit_button_; |
| } |
| |
| LoginPinView* PinRequestView::TestApi::pin_keyboard_view() { |
| return view_->pin_keyboard_view_; |
| } |
| |
| views::Textfield* PinRequestView::TestApi::GetInputTextField(int index) { |
| return FixedLengthCodeInput::TestApi( |
| static_cast<FixedLengthCodeInput*>(view_->access_code_view_)) |
| .GetInputTextField(index); |
| } |
| |
| PinRequestViewState PinRequestView::TestApi::state() const { |
| return view_->state_; |
| } |
| |
| // static |
| SkColor PinRequestView::GetChildUserDialogColor(bool using_blur) { |
| SkColor color = AshColorProvider::Get()->GetBaseLayerColor( |
| AshColorProvider::BaseLayerType::kOpaque, |
| AshColorProvider::AshColorMode::kDark); |
| |
| SkColor extracted_color = |
| Shell::Get()->wallpaper_controller()->GetProminentColor( |
| color_utils::ColorProfile(color_utils::LumaRange::DARK, |
| color_utils::SaturationRange::MUTED)); |
| |
| if (extracted_color != kInvalidWallpaperColor && |
| extracted_color != SK_ColorTRANSPARENT) { |
| color = color_utils::GetResultingPaintColor( |
| SkColorSetA(SK_ColorBLACK, kAlpha70Percent), extracted_color); |
| } |
| |
| return using_blur ? SkColorSetA(color, kAlpha74Percent) : color; |
| } |
| |
| // TODO(crbug.com/1061008): Make dialog look good on small screens with high |
| // zoom factor. |
| PinRequestView::PinRequestView(PinRequest request, Delegate* delegate) |
| : delegate_(delegate), |
| on_pin_request_done_(std::move(request.on_pin_request_done)), |
| pin_keyboard_always_enabled_(request.pin_keyboard_always_enabled), |
| default_title_(request.title), |
| default_description_(request.description), |
| default_accessible_title_(request.accessible_title.empty() |
| ? request.title |
| : request.accessible_title) { |
| // Main view contains all other views aligned vertically and centered. |
| auto layout = std::make_unique<views::BoxLayout>( |
| views::BoxLayout::Orientation::kVertical, |
| gfx::Insets(kPinRequestViewVerticalInsetDp, |
| kPinRequestViewHorizontalInsetDp), |
| 0); |
| layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kStart); |
| layout->set_cross_axis_alignment( |
| views::BoxLayout::CrossAxisAlignment::kCenter); |
| SetLayoutManager(std::move(layout)); |
| |
| SetPaintToLayer(); |
| layer()->SetFillsBoundsOpaquely(false); |
| layer()->SetRoundedCornerRadius( |
| gfx::RoundedCornersF(kPinRequestViewRoundedCornerRadiusDp)); |
| layer()->SetBackgroundBlur(ShelfConfig::Get()->shelf_blur_radius()); |
| |
| const int child_view_width = |
| kPinRequestViewWidthDp - 2 * kPinRequestViewMainHorizontalInsetDp; |
| |
| // Header view which contains the back button that is aligned top right and |
| // the lock icon which is in the bottom center. |
| auto header_layout = std::make_unique<views::FillLayout>(); |
| auto* header = new NonAccessibleView(); |
| header->SetLayoutManager(std::move(header_layout)); |
| AddChildView(header); |
| auto* header_spacer = new NonAccessibleView(); |
| header_spacer->SetPreferredSize(gfx::Size(0, kHeaderHeightDp)); |
| header->AddChildView(header_spacer); |
| |
| // Main view icon. |
| auto* icon_view = new NonAccessibleView(); |
| icon_view->SetPreferredSize(gfx::Size(0, kHeaderHeightDp)); |
| auto icon_layout = std::make_unique<views::BoxLayout>( |
| views::BoxLayout::Orientation::kVertical, gfx::Insets(), 0); |
| icon_layout->set_main_axis_alignment( |
| views::BoxLayout::MainAxisAlignment::kEnd); |
| icon_layout->set_cross_axis_alignment( |
| views::BoxLayout::CrossAxisAlignment::kCenter); |
| icon_view->SetLayoutManager(std::move(icon_layout)); |
| header->AddChildView(icon_view); |
| |
| views::ImageView* icon = new views::ImageView(); |
| icon->SetPreferredSize(gfx::Size(kLockIconSizeDp, kLockIconSizeDp)); |
| icon->SetImage(gfx::CreateVectorIcon(kPinRequestLockIcon, SK_ColorWHITE)); |
| icon_view->AddChildView(icon); |
| |
| // Back button. Note that it should be the last view added to |header| in |
| // order to be clickable. |
| auto* back_button_view = new NonAccessibleView(); |
| back_button_view->SetPreferredSize( |
| gfx::Size(child_view_width + 2 * (kPinRequestViewMainHorizontalInsetDp - |
| kPinRequestViewHorizontalInsetDp), |
| kHeaderHeightDp)); |
| auto back_button_layout = std::make_unique<views::BoxLayout>( |
| views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0); |
| back_button_layout->set_main_axis_alignment( |
| views::BoxLayout::MainAxisAlignment::kEnd); |
| back_button_layout->set_cross_axis_alignment( |
| views::BoxLayout::CrossAxisAlignment::kStart); |
| back_button_view->SetLayoutManager(std::move(back_button_layout)); |
| header->AddChildView(back_button_view); |
| |
| back_button_ = new LoginButton(this); |
| back_button_->SetPreferredSize( |
| gfx::Size(kBackButtonSizeDp, kBackButtonSizeDp)); |
| back_button_->SetBackground( |
| views::CreateSolidBackground(SK_ColorTRANSPARENT)); |
| back_button_->SetImage( |
| views::Button::STATE_NORMAL, |
| gfx::CreateVectorIcon(views::kIcCloseIcon, kCrossSizeDp, SK_ColorWHITE)); |
| back_button_->SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER); |
| back_button_->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE); |
| back_button_->SetAccessibleName( |
| l10n_util::GetStringUTF16(IDS_ASH_LOGIN_BACK_BUTTON_ACCESSIBLE_NAME)); |
| back_button_->SetFocusBehavior(FocusBehavior::ALWAYS); |
| back_button_view->AddChildView(back_button_); |
| |
| auto add_spacer = [&](int height) { |
| auto* spacer = new NonAccessibleView(); |
| spacer->SetPreferredSize(gfx::Size(0, height)); |
| AddChildView(spacer); |
| }; |
| |
| add_spacer(kIconToTitleDistanceDp); |
| |
| auto decorate_label = [](views::Label* label) { |
| label->SetSubpixelRenderingEnabled(false); |
| label->SetAutoColorReadabilityEnabled(false); |
| label->SetEnabledColor(kTextColor); |
| label->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); |
| }; |
| |
| // Main view title. |
| title_label_ = new views::Label(default_title_, views::style::CONTEXT_LABEL, |
| views::style::STYLE_PRIMARY); |
| title_label_->SetMultiLine(true); |
| title_label_->SetMaxLines(kTitleMaxLines); |
| title_label_->SizeToFit(kTitleLineWidthDp); |
| title_label_->SetLineHeight(kTitleLineHeightDp); |
| title_label_->SetFontList(gfx::FontList().Derive( |
| kTitleFontSizeDeltaDp, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); |
| decorate_label(title_label_); |
| AddChildView(title_label_); |
| |
| add_spacer(kTitleToDescriptionDistanceDp); |
| |
| // Main view description. |
| description_label_ = |
| new views::Label(default_description_, views::style::CONTEXT_LABEL, |
| views::style::STYLE_PRIMARY); |
| description_label_->SetMultiLine(true); |
| description_label_->SetMaxLines(kDescriptionMaxLines); |
| description_label_->SizeToFit(kDescriptionLineWidthDp); |
| description_label_->SetLineHeight(kDescriptionTextLineHeightDp); |
| description_label_->SetFontList( |
| gfx::FontList().Derive(kDescriptionFontSizeDeltaDp, gfx::Font::NORMAL, |
| gfx::Font::Weight::NORMAL)); |
| decorate_label(description_label_); |
| AddChildView(description_label_); |
| |
| add_spacer(kDescriptionToAccessCodeDistanceDp); |
| |
| // Access code input view. |
| if (request.pin_length.has_value()) { |
| CHECK_GT(request.pin_length.value(), 0); |
| access_code_view_ = AddChildView(std::make_unique<FixedLengthCodeInput>( |
| request.pin_length.value(), |
| base::BindRepeating(&PinRequestView::OnInputChange, |
| base::Unretained(this)), |
| base::BindRepeating(&PinRequestView::SubmitCode, |
| base::Unretained(this)), |
| base::BindRepeating(&PinRequestView::OnBack, base::Unretained(this)), |
| request.obscure_pin)); |
| access_code_view_->SetFocusBehavior(FocusBehavior::ALWAYS); |
| } else { |
| auto flex_code_input = std::make_unique<FlexCodeInput>( |
| base::BindRepeating(&PinRequestView::OnInputChange, |
| base::Unretained(this), false), |
| base::BindRepeating(&PinRequestView::SubmitCode, |
| base::Unretained(this)), |
| base::BindRepeating(&PinRequestView::OnBack, base::Unretained(this)), |
| request.obscure_pin); |
| flex_code_input->SetAccessibleName(default_accessible_title_); |
| access_code_view_ = AddChildView(std::move(flex_code_input)); |
| } |
| |
| add_spacer(kAccessCodeToPinKeyboardDistanceDp); |
| |
| // Pin keyboard. Note that the keyboard's own submit button is disabled via |
| // passing a null |on_submit| callback. |
| pin_keyboard_view_ = |
| new LoginPinView(LoginPinView::Style::kAlphanumeric, |
| base::BindRepeating(&AccessCodeInput::InsertDigit, |
| base::Unretained(access_code_view_)), |
| base::BindRepeating(&AccessCodeInput::Backspace, |
| base::Unretained(access_code_view_)), |
| /*on_submit=*/LoginPinView::OnPinSubmit()); |
| // Backspace key is always enabled and |access_code_| field handles it. |
| pin_keyboard_view_->OnPasswordTextChanged(false); |
| AddChildView(pin_keyboard_view_); |
| |
| add_spacer(kPinKeyboardToFooterDistanceDp); |
| |
| // Footer view contains help text button aligned to its start, submit |
| // button aligned to its end and spacer view in between. |
| auto* footer = new NonAccessibleView(); |
| footer->SetPreferredSize(gfx::Size(child_view_width, kArrowButtonSizeDp)); |
| auto* bottom_layout = |
| footer->SetLayoutManager(std::make_unique<views::BoxLayout>( |
| views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0)); |
| AddChildView(footer); |
| |
| help_button_ = new FocusableLabelButton( |
| this, l10n_util::GetStringUTF16(IDS_ASH_LOGIN_PIN_REQUEST_HELP)); |
| help_button_->SetPaintToLayer(); |
| help_button_->layer()->SetFillsBoundsOpaquely(false); |
| help_button_->SetTextSubpixelRenderingEnabled(false); |
| help_button_->SetEnabledTextColors(kTextColor); |
| help_button_->SetFocusBehavior(FocusBehavior::ALWAYS); |
| help_button_->SetVisible(request.help_button_enabled); |
| footer->AddChildView(help_button_); |
| |
| auto* horizontal_spacer = new NonAccessibleView(); |
| footer->AddChildView(horizontal_spacer); |
| bottom_layout->SetFlexForView(horizontal_spacer, 1); |
| |
| submit_button_ = new ArrowButtonView(this, kArrowButtonSizeDp); |
| submit_button_->SetBackgroundColor(kArrowButtonColor); |
| submit_button_->SetPreferredSize( |
| gfx::Size(kArrowButtonSizeDp, kArrowButtonSizeDp)); |
| submit_button_->SetEnabled(false); |
| submit_button_->SetAccessibleName( |
| l10n_util::GetStringUTF16(IDS_ASH_LOGIN_SUBMIT_BUTTON_ACCESSIBLE_NAME)); |
| submit_button_->SetFocusBehavior(FocusBehavior::ALWAYS); |
| footer->AddChildView(submit_button_); |
| add_spacer(kSubmitButtonBottomMarginDp); |
| |
| pin_keyboard_view_->SetVisible(PinKeyboardVisible()); |
| |
| tablet_mode_observer_.Add(Shell::Get()->tablet_mode_controller()); |
| |
| SetPreferredSize(GetPinRequestViewSize()); |
| } |
| |
| PinRequestView::~PinRequestView() = default; |
| |
| void PinRequestView::OnPaint(gfx::Canvas* canvas) { |
| views::View::OnPaint(canvas); |
| |
| cc::PaintFlags flags; |
| flags.setStyle(cc::PaintFlags::kFill_Style); |
| flags.setColor(GetChildUserDialogColor(true)); |
| canvas->DrawRoundRect(GetContentsBounds(), |
| kPinRequestViewRoundedCornerRadiusDp, flags); |
| } |
| |
| void PinRequestView::RequestFocus() { |
| access_code_view_->RequestFocus(); |
| } |
| |
| gfx::Size PinRequestView::CalculatePreferredSize() const { |
| return GetPinRequestViewSize(); |
| } |
| |
| ui::ModalType PinRequestView::GetModalType() const { |
| // MODAL_TYPE_SYSTEM is used to get a semi-transparent background behind the |
| // pin request view, when it is used directly on a widget. The overlay |
| // consumes all the inputs from the user, so that they can only interact with |
| // the pin request view while it is visible. |
| return ui::MODAL_TYPE_SYSTEM; |
| } |
| |
| views::View* PinRequestView::GetInitiallyFocusedView() { |
| return access_code_view_; |
| } |
| |
| base::string16 PinRequestView::GetAccessibleWindowTitle() const { |
| return default_accessible_title_; |
| } |
| |
| void PinRequestView::ButtonPressed(views::Button* sender, |
| const ui::Event& event) { |
| if (sender == back_button_) { |
| OnBack(); |
| } else if (sender == help_button_) { |
| delegate_->OnHelp(GetWidget()->GetNativeWindow()); |
| } else if (sender == submit_button_) { |
| SubmitCode(); |
| } |
| } |
| |
| void PinRequestView::OnTabletModeStarted() { |
| if (!pin_keyboard_always_enabled_) { |
| VLOG(1) << "Showing PIN keyboard in PinRequestView"; |
| pin_keyboard_view_->SetVisible(true); |
| // This will trigger ChildPreferredSizeChanged in parent view and Layout() |
| // in view. As the result whole hierarchy will go through re-layout. |
| UpdatePreferredSize(); |
| } |
| } |
| |
| void PinRequestView::OnTabletModeEnded() { |
| if (!pin_keyboard_always_enabled_) { |
| VLOG(1) << "Hiding PIN keyboard in PinRequestView"; |
| DCHECK(pin_keyboard_view_); |
| pin_keyboard_view_->SetVisible(false); |
| // This will trigger ChildPreferredSizeChanged in parent view and Layout() |
| // in view. As the result whole hierarchy will go through re-layout. |
| UpdatePreferredSize(); |
| } |
| } |
| |
| void PinRequestView::OnTabletControllerDestroyed() { |
| tablet_mode_observer_.RemoveAll(); |
| } |
| |
| void PinRequestView::SubmitCode() { |
| base::Optional<std::string> code = access_code_view_->GetCode(); |
| DCHECK(code.has_value()); |
| |
| SubmissionResult result = delegate_->OnPinSubmitted(*code); |
| switch (result) { |
| case SubmissionResult::kPinAccepted: { |
| std::move(on_pin_request_done_).Run(true /* success */); |
| return; |
| } |
| case SubmissionResult::kPinError: { |
| // Caller is expected to call UpdateState() to allow for customization of |
| // error messages. |
| return; |
| } |
| case SubmissionResult::kSubmitPending: { |
| // Waiting on validation result - do nothing for now. |
| return; |
| } |
| } |
| } |
| |
| void PinRequestView::OnBack() { |
| delegate_->OnBack(); |
| if (PinRequestWidget::Get()) { |
| PinRequestWidget::Get()->Close(false /* success */); |
| } |
| } |
| |
| void PinRequestView::UpdateState(PinRequestViewState state, |
| const base::string16& title, |
| const base::string16& description) { |
| state_ = state; |
| title_label_->SetText(title); |
| description_label_->SetText(description); |
| UpdatePreferredSize(); |
| switch (state_) { |
| case PinRequestViewState::kNormal: { |
| access_code_view_->SetInputColor(kTextColor); |
| title_label_->SetEnabledColor(kTextColor); |
| return; |
| } |
| case PinRequestViewState::kError: { |
| access_code_view_->SetInputColor(kErrorColor); |
| title_label_->SetEnabledColor(kErrorColor); |
| // Read out the error. |
| title_label_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); |
| return; |
| } |
| } |
| } |
| |
| void PinRequestView::ClearInput() { |
| access_code_view_->ClearInput(); |
| } |
| |
| void PinRequestView::SetInputEnabled(bool input_enabled) { |
| access_code_view_->SetInputEnabled(input_enabled); |
| } |
| |
| void PinRequestView::UpdatePreferredSize() { |
| SetPreferredSize(CalculatePreferredSize()); |
| if (GetWidget()) |
| GetWidget()->CenterWindow(GetPreferredSize()); |
| } |
| |
| void PinRequestView::FocusSubmitButton() { |
| submit_button_->RequestFocus(); |
| } |
| |
| void PinRequestView::OnInputChange(bool last_field_active, bool complete) { |
| if (state_ == PinRequestViewState::kError) { |
| UpdateState(PinRequestViewState::kNormal, default_title_, |
| default_description_); |
| } |
| |
| submit_button_->SetEnabled(complete); |
| |
| if (complete && last_field_active) { |
| if (auto_submit_enabled_) { |
| auto_submit_enabled_ = false; |
| SubmitCode(); |
| return; |
| } |
| |
| // Moving focus is delayed by using PostTask to allow for proper |
| // a11y announcements. |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(&PinRequestView::FocusSubmitButton, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| } |
| |
| void PinRequestView::GetAccessibleNodeData(ui::AXNodeData* node_data) { |
| views::View::GetAccessibleNodeData(node_data); |
| node_data->role = ax::mojom::Role::kDialog; |
| node_data->SetName(default_accessible_title_); |
| } |
| |
| // If |pin_keyboard_always_enabled_| is not set, pin keyboard is only shown in |
| // tablet mode. |
| bool PinRequestView::PinKeyboardVisible() const { |
| return pin_keyboard_always_enabled_ || IsTabletMode(); |
| } |
| |
| gfx::Size PinRequestView::GetPinRequestViewSize() const { |
| int height = kPinRequestViewMinimumHeightDp + |
| std::min(int{title_label_->GetRequiredLines()}, kTitleMaxLines) * |
| kTitleLineHeightDp + |
| std::min(int{description_label_->GetRequiredLines()}, |
| kDescriptionMaxLines) * |
| kDescriptionTextLineHeightDp; |
| if (PinKeyboardVisible()) |
| height += kPinKeyboardHeightDp; |
| return gfx::Size(kPinRequestViewWidthDp, height); |
| } |
| |
| } // namespace ash |