Commit 322b7e4f authored by Abhijeet Singh's avatar Abhijeet Singh Committed by Commit Bot

Add keyboard accessibility for Quick Answers Consent-View

Allow the Quick-Answers UserConsentView to obtain keyboard-focus to pass
on to the settings, acknowledgement and dogfood buttons, using
arrow-keys.

Bug: b:152057976
Test: Tested on Chrome OS VM.
Change-Id: I01a4f6bd3da09e811398fe224b82e0c01f5add0c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2247156
Commit-Queue: Abhijeet Singh <siabhijeet@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#781972}
parent e30ea146
...@@ -614,6 +614,8 @@ component("ash") { ...@@ -614,6 +614,8 @@ component("ash") {
"quick_answers/quick_answers_controller_impl.h", "quick_answers/quick_answers_controller_impl.h",
"quick_answers/quick_answers_ui_controller.cc", "quick_answers/quick_answers_ui_controller.cc",
"quick_answers/quick_answers_ui_controller.h", "quick_answers/quick_answers_ui_controller.h",
"quick_answers/ui/quick_answers_focus_search.cc",
"quick_answers/ui/quick_answers_focus_search.h",
"quick_answers/ui/quick_answers_pre_target_handler.cc", "quick_answers/ui/quick_answers_pre_target_handler.cc",
"quick_answers/ui/quick_answers_pre_target_handler.h", "quick_answers/ui/quick_answers_pre_target_handler.h",
"quick_answers/ui/quick_answers_view.cc", "quick_answers/ui/quick_answers_view.cc",
......
// 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/quick_answers/ui/quick_answers_focus_search.h"
namespace ash {
QuickAnswersFocusSearch::QuickAnswersFocusSearch(
views::View* view,
const GetFocusableViewsCallback& callback)
: FocusSearch(/*root=*/view, /*cycle=*/true, /*accessibility_mode=*/true),
view_(view),
get_focusable_views_callback_(callback) {}
QuickAnswersFocusSearch::~QuickAnswersFocusSearch() = default;
views::View* QuickAnswersFocusSearch::FindNextFocusableView(
views::View* starting_view,
SearchDirection search_direction,
TraversalDirection traversal_direction,
StartingViewPolicy check_starting_view,
AnchoredDialogPolicy can_go_into_anchored_dialog,
views::FocusTraversable** focus_traversable,
views::View** focus_traversable_view) {
DCHECK_EQ(root(), view_);
// The callback provided by |view_| polls the currently focusable views.
auto focusable_views = get_focusable_views_callback_.Run();
if (focusable_views.empty())
return nullptr;
int delta =
search_direction == FocusSearch::SearchDirection::kForwards ? 1 : -1;
int focusable_views_size = int{focusable_views.size()};
for (int i = 0; i < focusable_views_size; ++i) {
// If current view from the set is found to be focused, return the view
// next (or previous) to it as next focusable view.
if (focusable_views[i] == starting_view) {
int next_index =
(i + delta + focusable_views_size) % focusable_views_size;
return focusable_views[next_index];
}
}
// Case when none of the views are already focused.
return (search_direction == FocusSearch::SearchDirection::kForwards)
? focusable_views.front()
: focusable_views.back();
}
views::FocusSearch* QuickAnswersFocusSearch::GetFocusSearch() {
return this;
}
views::FocusTraversable* QuickAnswersFocusSearch::GetFocusTraversableParent() {
return nullptr;
}
views::View* QuickAnswersFocusSearch::GetFocusTraversableParentView() {
return nullptr;
}
} // 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_QUICK_ANSWERS_UI_QUICK_ANSWERS_FOCUS_SEARCH_H_
#define ASH_QUICK_ANSWERS_UI_QUICK_ANSWERS_FOCUS_SEARCH_H_
#include "base/callback.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/focus/focus_search.h"
namespace ash {
// This class manages the focus traversal order for elements inside
// Quick-Answers related views.
// TODO(siabhijeet): QuickAnswersView is a menu-companion, so ideally should
// avoid disturbing existing focus. Explore other ways for keyboard
// accessibility.
class QuickAnswersFocusSearch : public views::FocusSearch,
public views::FocusTraversable {
public:
using GetFocusableViewsCallback =
base::RepeatingCallback<std::vector<views::View*>(void)>;
explicit QuickAnswersFocusSearch(views::View* view,
const GetFocusableViewsCallback& callback);
~QuickAnswersFocusSearch() override;
// views::FocusSearch:
views::View* FindNextFocusableView(
views::View* starting_view,
SearchDirection search_direction,
TraversalDirection traversal_direction,
StartingViewPolicy check_starting_view,
AnchoredDialogPolicy can_go_into_anchored_dialog,
views::FocusTraversable** focus_traversable,
views::View** focus_traversable_view) override;
// views::FocusTraversable:
views::FocusSearch* GetFocusSearch() override;
views::FocusTraversable* GetFocusTraversableParent() override;
views::View* GetFocusTraversableParentView() override;
private:
views::View* const view_;
const GetFocusableViewsCallback get_focusable_views_callback_;
};
} // namespace ash
#endif // ASH_QUICK_ANSWERS_UI_QUICK_ANSWERS_FOCUS_SEARCH_H_
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h" #include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/focus/focus_search.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h" #include "ui/views/layout/fill_layout.h"
#include "ui/views/painter.h" #include "ui/views/painter.h"
...@@ -120,66 +119,6 @@ View* AddHorizontalUiElements( ...@@ -120,66 +119,6 @@ View* AddHorizontalUiElements(
} // namespace } // namespace
// QuickAnswersFocusSearch ----------------------------------------------------
// This class manages the focus traversal order for elements inside
// QuickAnswersView.
// TODO(siabhijeet): QuickAnswersView is a menu-companion, so ideally should
// avoid disturbing existing focus. Explore other ways for keyboard
// accessibility.
class QuickAnswersFocusSearch : public views::FocusSearch {
public:
explicit QuickAnswersFocusSearch(QuickAnswersView* view)
: FocusSearch(/*root=*/view, /*cycle=*/true, /*accessibility_mode=*/true),
view_(view) {}
~QuickAnswersFocusSearch() override = default;
// views::FocusSearch:
views::View* FindNextFocusableView(
views::View* starting_view,
SearchDirection search_direction,
TraversalDirection traversal_direction,
StartingViewPolicy check_starting_view,
AnchoredDialogPolicy can_go_into_anchored_dialog,
views::FocusTraversable** focus_traversable,
views::View** focus_traversable_view) override {
DCHECK_EQ(root(), view_);
std::vector<views::View*> focusable_views;
// |view_| is not included in focus loop for retry-view.
if (!view_->retry_label_)
focusable_views.push_back(view_);
if (view_->retry_label_ && view_->retry_label_->GetVisible())
focusable_views.push_back(view_->retry_label_);
if (view_->dogfood_button_ && view_->dogfood_button_->GetVisible())
focusable_views.push_back(view_->dogfood_button_);
if (focusable_views.empty())
return nullptr;
int delta =
search_direction == FocusSearch::SearchDirection::kForwards ? 1 : -1;
int focusable_views_size = int{focusable_views.size()};
for (int i = 0; i < focusable_views_size; ++i) {
// If current view from the set is found to be focused, return the view
// next (or previous) to it as next focusable view.
if (focusable_views[i] == starting_view) {
int next_index =
(i + delta + focusable_views_size) % focusable_views_size;
return focusable_views[next_index];
}
}
// Case when none of the views are already focused.
return (search_direction == FocusSearch::SearchDirection::kForwards)
? focusable_views.front()
: focusable_views.back();
}
private:
QuickAnswersView* const view_;
};
// QuickAnswersView ----------------------------------------------------------- // QuickAnswersView -----------------------------------------------------------
QuickAnswersView::QuickAnswersView(const gfx::Rect& anchor_view_bounds, QuickAnswersView::QuickAnswersView(const gfx::Rect& anchor_view_bounds,
...@@ -191,7 +130,10 @@ QuickAnswersView::QuickAnswersView(const gfx::Rect& anchor_view_bounds, ...@@ -191,7 +130,10 @@ QuickAnswersView::QuickAnswersView(const gfx::Rect& anchor_view_bounds,
title_(title), title_(title),
quick_answers_view_handler_( quick_answers_view_handler_(
std::make_unique<QuickAnswersPreTargetHandler>(this)), std::make_unique<QuickAnswersPreTargetHandler>(this)),
focus_search_(std::make_unique<QuickAnswersFocusSearch>(this)) { focus_search_(std::make_unique<QuickAnswersFocusSearch>(
this,
base::BindRepeating(&QuickAnswersView::GetFocusableViews,
base::Unretained(this)))) {
InitLayout(); InitLayout();
InitWidget(); InitWidget();
...@@ -239,7 +181,20 @@ void QuickAnswersView::OnBlur() { ...@@ -239,7 +181,20 @@ void QuickAnswersView::OnBlur() {
} }
views::FocusTraversable* QuickAnswersView::GetPaneFocusTraversable() { views::FocusTraversable* QuickAnswersView::GetPaneFocusTraversable() {
return this; return focus_search_.get();
}
std::vector<views::View*> QuickAnswersView::GetFocusableViews() {
std::vector<views::View*> focusable_views;
// The view itself does not gain focus for retry-view and transfers it to the
// retry-label, and so is not included when this is the case.
if (!retry_label_)
focusable_views.push_back(this);
if (retry_label_ && retry_label_->GetVisible())
focusable_views.push_back(retry_label_);
if (dogfood_button_ && dogfood_button_->GetVisible())
focusable_views.push_back(dogfood_button_);
return focusable_views;
} }
void QuickAnswersView::StateChanged(views::Button::ButtonState old_state) { void QuickAnswersView::StateChanged(views::Button::ButtonState old_state) {
...@@ -279,18 +234,6 @@ void QuickAnswersView::SetButtonNotifyActionToOnPress(views::Button* button) { ...@@ -279,18 +234,6 @@ void QuickAnswersView::SetButtonNotifyActionToOnPress(views::Button* button) {
views::ButtonController::NotifyAction::kOnPress); views::ButtonController::NotifyAction::kOnPress);
} }
views::FocusSearch* QuickAnswersView::GetFocusSearch() {
return focus_search_.get();
}
views::FocusTraversable* QuickAnswersView::GetFocusTraversableParent() {
return nullptr;
}
views::View* QuickAnswersView::GetFocusTraversableParentView() {
return nullptr;
}
void QuickAnswersView::SendQuickAnswersQuery() { void QuickAnswersView::SendQuickAnswersQuery() {
controller_->OnQuickAnswersViewPressed(); controller_->OnQuickAnswersViewPressed();
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <vector> #include <vector>
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/quick_answers/ui/quick_answers_focus_search.h"
#include "ui/events/event_handler.h" #include "ui/events/event_handler.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/focus/focus_manager.h" #include "ui/views/focus/focus_manager.h"
...@@ -19,7 +20,6 @@ struct QuickAnswer; ...@@ -19,7 +20,6 @@ struct QuickAnswer;
} // namespace chromeos } // namespace chromeos
namespace views { namespace views {
class FocusSearch;
class ImageButton; class ImageButton;
class Label; class Label;
class LabelButton; class LabelButton;
...@@ -32,8 +32,7 @@ class QuickAnswersPreTargetHandler; ...@@ -32,8 +32,7 @@ class QuickAnswersPreTargetHandler;
// A bubble style view to show QuickAnswer. // A bubble style view to show QuickAnswer.
class ASH_EXPORT QuickAnswersView : public views::Button, class ASH_EXPORT QuickAnswersView : public views::Button,
public views::ButtonListener, public views::ButtonListener {
public views::FocusTraversable {
public: public:
QuickAnswersView(const gfx::Rect& anchor_view_bounds, QuickAnswersView(const gfx::Rect& anchor_view_bounds,
const std::string& title, const std::string& title,
...@@ -55,11 +54,6 @@ class ASH_EXPORT QuickAnswersView : public views::Button, ...@@ -55,11 +54,6 @@ class ASH_EXPORT QuickAnswersView : public views::Button,
// views::ButtonListener: // views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// views::FocusTraversable:
views::FocusSearch* GetFocusSearch() override;
views::FocusTraversable* GetFocusTraversableParent() override;
views::View* GetFocusTraversableParentView() override;
// Called when a click happens to trigger Assistant Query. // Called when a click happens to trigger Assistant Query.
void SendQuickAnswersQuery(); void SendQuickAnswersQuery();
...@@ -72,8 +66,6 @@ class ASH_EXPORT QuickAnswersView : public views::Button, ...@@ -72,8 +66,6 @@ class ASH_EXPORT QuickAnswersView : public views::Button,
void ShowRetryView(); void ShowRetryView();
private: private:
friend class QuickAnswersFocusSearch;
void InitLayout(); void InitLayout();
void InitWidget(); void InitWidget();
void AddDogfoodButton(); void AddDogfoodButton();
...@@ -88,6 +80,10 @@ class ASH_EXPORT QuickAnswersView : public views::Button, ...@@ -88,6 +80,10 @@ class ASH_EXPORT QuickAnswersView : public views::Button,
// mouse-release), since events of former type dismiss the accompanying menu. // mouse-release), since events of former type dismiss the accompanying menu.
void SetButtonNotifyActionToOnPress(views::Button* button); void SetButtonNotifyActionToOnPress(views::Button* button);
// QuickAnswersFocusSearch::GetFocusableViewsCallback to poll currently
// focusable views.
std::vector<views::View*> GetFocusableViews();
gfx::Rect anchor_view_bounds_; gfx::Rect anchor_view_bounds_;
QuickAnswersUiController* const controller_; QuickAnswersUiController* const controller_;
bool has_second_row_answer_ = false; bool has_second_row_answer_ = false;
...@@ -100,7 +96,7 @@ class ASH_EXPORT QuickAnswersView : public views::Button, ...@@ -100,7 +96,7 @@ class ASH_EXPORT QuickAnswersView : public views::Button,
views::ImageButton* dogfood_button_ = nullptr; views::ImageButton* dogfood_button_ = nullptr;
std::unique_ptr<QuickAnswersPreTargetHandler> quick_answers_view_handler_; std::unique_ptr<QuickAnswersPreTargetHandler> quick_answers_view_handler_;
std::unique_ptr<views::FocusSearch> focus_search_; std::unique_ptr<QuickAnswersFocusSearch> focus_search_;
base::WeakPtrFactory<QuickAnswersView> weak_factory_{this}; base::WeakPtrFactory<QuickAnswersView> weak_factory_{this};
}; };
} // namespace ash } // namespace ash
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "ash/quick_answers/ui/user_consent_view.h" #include "ash/quick_answers/ui/user_consent_view.h"
#include "ash/accessibility/accessibility_controller_impl.h"
#include "ash/public/cpp/vector_icons/vector_icons.h" #include "ash/public/cpp/vector_icons/vector_icons.h"
#include "ash/quick_answers/quick_answers_ui_controller.h" #include "ash/quick_answers/quick_answers_ui_controller.h"
#include "ash/quick_answers/ui/quick_answers_pre_target_handler.h" #include "ash/quick_answers/ui/quick_answers_pre_target_handler.h"
...@@ -18,14 +19,16 @@ ...@@ -18,14 +19,16 @@
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/border.h" #include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/label_button.h" #include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/image_view.h" #include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h" #include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/tooltip_manager.h" #include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash { namespace ash {
namespace quick_answers { namespace quick_answers {
...@@ -53,18 +56,14 @@ constexpr int kDescFontSizeDelta = 1; ...@@ -53,18 +56,14 @@ constexpr int kDescFontSizeDelta = 1;
// Buttons common. // Buttons common.
constexpr int kButtonSpacingDip = 8; constexpr int kButtonSpacingDip = 8;
constexpr int kButtonBorderRadiusDip = 4;
constexpr int kButtonBorderThicknessDip = 1;
constexpr gfx::Insets kButtonBarInsets = {8, 0, 0, 0}; constexpr gfx::Insets kButtonBarInsets = {8, 0, 0, 0};
constexpr gfx::Insets kButtonInsets = {6, 16, 6, 16}; constexpr gfx::Insets kButtonInsets = {6, 16, 6, 16};
constexpr int kButtonFontSizeDelta = 1; constexpr int kButtonFontSizeDelta = 1;
// Manage-Settings button. // Manage-Settings button.
constexpr SkColor kSettingsButtonBorderColor = gfx::kGoogleGrey300;
constexpr SkColor kSettingsButtonTextColor = gfx::kGoogleBlue600; constexpr SkColor kSettingsButtonTextColor = gfx::kGoogleBlue600;
// Grant-Consent button. // Grant-Consent button.
constexpr SkColor kConsentButtonBgColor = gfx::kGoogleBlue600;
constexpr SkColor kConsentButtonTextColor = gfx::kGoogleGrey200; constexpr SkColor kConsentButtonTextColor = gfx::kGoogleGrey200;
// Dogfood button. // Dogfood button.
...@@ -92,12 +91,14 @@ std::unique_ptr<views::Label> CreateLabel(const base::string16& text, ...@@ -92,12 +91,14 @@ std::unique_ptr<views::Label> CreateLabel(const base::string16& text,
// views::LabelButton with custom line-height, color and font-list for the // views::LabelButton with custom line-height, color and font-list for the
// underlying label. // underlying label.
class CustomizedLabelButton : public views::LabelButton { class CustomizedLabelButton : public views::MdTextButton {
public: public:
CustomizedLabelButton(views::ButtonListener* listener, CustomizedLabelButton(views::ButtonListener* listener,
const base::string16& text, const base::string16& text,
const SkColor color) const SkColor color)
: LabelButton(listener, text) { : MdTextButton(listener, views::style::CONTEXT_BUTTON_MD) {
SetText(text);
SetCustomPadding(kButtonInsets);
SetEnabledTextColors(color); SetEnabledTextColors(color);
label()->SetLineHeight(kLineHeightDip); label()->SetLineHeight(kLineHeightDip);
label()->SetFontList(views::Label::GetDefaultFontList() label()->SetFontList(views::Label::GetDefaultFontList()
...@@ -123,10 +124,18 @@ UserConsentView::UserConsentView(const gfx::Rect& anchor_view_bounds, ...@@ -123,10 +124,18 @@ UserConsentView::UserConsentView(const gfx::Rect& anchor_view_bounds,
QuickAnswersUiController* ui_controller) QuickAnswersUiController* ui_controller)
: anchor_view_bounds_(anchor_view_bounds), : anchor_view_bounds_(anchor_view_bounds),
event_handler_(std::make_unique<QuickAnswersPreTargetHandler>(this)), event_handler_(std::make_unique<QuickAnswersPreTargetHandler>(this)),
ui_controller_(ui_controller) { ui_controller_(ui_controller),
focus_search_(std::make_unique<QuickAnswersFocusSearch>(
this,
base::BindRepeating(&UserConsentView::GetFocusableViews,
base::Unretained(this)))) {
InitLayout(); InitLayout();
InitWidget(); InitWidget();
// Focus should cycle to each of the buttons the view contains and back to it.
SetFocusBehavior(FocusBehavior::ALWAYS);
views::FocusRing::Install(this);
// Allow tooltips to be shown despite menu-controller owning capture. // Allow tooltips to be shown despite menu-controller owning capture.
GetWidget()->SetNativeWindowProperty( GetWidget()->SetNativeWindowProperty(
views::TooltipManager::kGroupingPropertyKey, views::TooltipManager::kGroupingPropertyKey,
...@@ -156,6 +165,32 @@ gfx::Size UserConsentView::CalculatePreferredSize() const { ...@@ -156,6 +165,32 @@ gfx::Size UserConsentView::CalculatePreferredSize() const {
return gfx::Size(width, GetHeightForWidth(width)); return gfx::Size(width, GetHeightForWidth(width));
} }
void UserConsentView::OnFocus() {
// Unless screen-reader mode is enabled, transfer the focus to an actionable
// button, otherwise retain to read out its contents.
if (!ash::Shell::Get()->accessibility_controller()->spoken_feedback_enabled())
settings_button_->RequestFocus();
}
views::FocusTraversable* UserConsentView::GetPaneFocusTraversable() {
return focus_search_.get();
}
std::vector<views::View*> UserConsentView::GetFocusableViews() {
std::vector<views::View*> focusable_views;
// The view itself is not included in focus loop, unless screen-reader is on.
if (ash::Shell::Get()
->accessibility_controller()
->spoken_feedback_enabled()) {
focusable_views.push_back(this);
}
focusable_views.push_back(settings_button_);
focusable_views.push_back(consent_button_);
if (dogfood_button_)
focusable_views.push_back(dogfood_button_);
return focusable_views;
}
void UserConsentView::ButtonPressed(views::Button* sender, void UserConsentView::ButtonPressed(views::Button* sender,
const ui::Event& event) { const ui::Event& event) {
if (sender == consent_button_) { if (sender == consent_button_) {
...@@ -256,11 +291,6 @@ void UserConsentView::InitButtonBar() { ...@@ -256,11 +291,6 @@ void UserConsentView::InitButtonBar() {
l10n_util::GetStringUTF16( l10n_util::GetStringUTF16(
IDS_ASH_QUICK_ANSWERS_USER_CONSENT_VIEW_MANAGE_SETTINGS_BUTTON), IDS_ASH_QUICK_ANSWERS_USER_CONSENT_VIEW_MANAGE_SETTINGS_BUTTON),
kSettingsButtonTextColor); kSettingsButtonTextColor);
settings_button->SetBorder(views::CreatePaddedBorder(
views::CreateRoundedRectBorder(kButtonBorderThicknessDip,
kButtonBorderRadiusDip,
kSettingsButtonBorderColor),
kButtonInsets));
settings_button_ = button_bar->AddChildView(std::move(settings_button)); settings_button_ = button_bar->AddChildView(std::move(settings_button));
// Grant-Consent button. // Grant-Consent button.
...@@ -269,21 +299,27 @@ void UserConsentView::InitButtonBar() { ...@@ -269,21 +299,27 @@ void UserConsentView::InitButtonBar() {
l10n_util::GetStringUTF16( l10n_util::GetStringUTF16(
IDS_ASH_QUICK_ANSWERS_USER_CONSENT_VIEW_GRANT_CONSENT_BUTTON), IDS_ASH_QUICK_ANSWERS_USER_CONSENT_VIEW_GRANT_CONSENT_BUTTON),
kConsentButtonTextColor); kConsentButtonTextColor);
consent_button->SetBackground(views::CreateRoundedRectBackground( consent_button->SetProminent(true);
kConsentButtonBgColor, kButtonBorderRadiusDip));
consent_button->SetBorder(views::CreateEmptyBorder(kButtonInsets));
consent_button_ = button_bar->AddChildView(std::move(consent_button)); consent_button_ = button_bar->AddChildView(std::move(consent_button));
} }
void UserConsentView::InitWidget() { void UserConsentView::InitWidget() {
views::Widget::InitParams params; views::Widget::InitParams params;
params.activatable = views::Widget::InitParams::Activatable::ACTIVATABLE_NO; params.activatable = views::Widget::InitParams::Activatable::ACTIVATABLE_NO;
params.context = Shell::Get()->GetRootWindowForNewWindows();
params.shadow_elevation = 2; params.shadow_elevation = 2;
params.shadow_type = views::Widget::InitParams::ShadowType::kDrop; params.shadow_type = views::Widget::InitParams::ShadowType::kDrop;
params.type = views::Widget::InitParams::TYPE_POPUP; params.type = views::Widget::InitParams::TYPE_POPUP;
params.z_order = ui::ZOrderLevel::kFloatingUIElement; params.z_order = ui::ZOrderLevel::kFloatingUIElement;
// Parent the widget depending on the context.
auto* active_menu_controller = views::MenuController::GetActiveInstance();
if (active_menu_controller && active_menu_controller->owner()) {
params.parent = active_menu_controller->owner()->GetNativeView();
params.child = true;
} else {
params.context = Shell::Get()->GetRootWindowForNewWindows();
}
views::Widget* widget = new views::Widget(); views::Widget* widget = new views::Widget();
widget->Init(std::move(params)); widget->Init(std::move(params));
widget->SetContentsView(this); widget->SetContentsView(this);
...@@ -304,6 +340,7 @@ void UserConsentView::AddDogfoodButton() { ...@@ -304,6 +340,7 @@ void UserConsentView::AddDogfoodButton() {
kDogfoodButtonColor)); kDogfoodButtonColor));
dogfood_button->SetTooltipText(l10n_util::GetStringUTF16( dogfood_button->SetTooltipText(l10n_util::GetStringUTF16(
IDS_ASH_QUICK_ANSWERS_DOGFOOD_BUTTON_TOOLTIP_TEXT)); IDS_ASH_QUICK_ANSWERS_DOGFOOD_BUTTON_TOOLTIP_TEXT));
dogfood_button->SetFocusForPlatform();
dogfood_button_ = dogfood_view->AddChildView(std::move(dogfood_button)); dogfood_button_ = dogfood_view->AddChildView(std::move(dogfood_button));
} }
...@@ -317,7 +354,9 @@ void UserConsentView::UpdateWidgetBounds() { ...@@ -317,7 +354,9 @@ void UserConsentView::UpdateWidgetBounds() {
.y()) { .y()) {
y = anchor_view_bounds_.bottom() + kMarginDip; y = anchor_view_bounds_.bottom() + kMarginDip;
} }
GetWidget()->SetBounds({{x, y}, size}); gfx::Rect bounds({x, y}, size);
wm::ConvertRectFromScreen(GetWidget()->GetNativeWindow()->parent(), &bounds);
GetWidget()->SetBounds(bounds);
} }
} // namespace quick_answers } // namespace quick_answers
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "ash/quick_answers/ui/quick_answers_focus_search.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/view.h" #include "ui/views/view.h"
...@@ -38,6 +39,8 @@ class UserConsentView : public views::View, public views::ButtonListener { ...@@ -38,6 +39,8 @@ class UserConsentView : public views::View, public views::ButtonListener {
// views::View: // views::View:
const char* GetClassName() const override; const char* GetClassName() const override;
gfx::Size CalculatePreferredSize() const override; gfx::Size CalculatePreferredSize() const override;
void OnFocus() override;
views::FocusTraversable* GetPaneFocusTraversable() override;
// views::ButtonListener: // views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
...@@ -52,11 +55,16 @@ class UserConsentView : public views::View, public views::ButtonListener { ...@@ -52,11 +55,16 @@ class UserConsentView : public views::View, public views::ButtonListener {
void AddDogfoodButton(); void AddDogfoodButton();
void UpdateWidgetBounds(); void UpdateWidgetBounds();
// QuickAnswersFocusSearch::GetFocusableViewsCallback to poll currently
// focusable views.
std::vector<views::View*> GetFocusableViews();
// Cached bounds of the anchor this view is tied to. // Cached bounds of the anchor this view is tied to.
gfx::Rect anchor_view_bounds_; gfx::Rect anchor_view_bounds_;
std::unique_ptr<QuickAnswersPreTargetHandler> event_handler_; std::unique_ptr<QuickAnswersPreTargetHandler> event_handler_;
QuickAnswersUiController* const ui_controller_; QuickAnswersUiController* const ui_controller_;
std::unique_ptr<QuickAnswersFocusSearch> focus_search_;
// Owned by view hierarchy. // Owned by view hierarchy.
views::View* main_view_ = nullptr; views::View* main_view_ = nullptr;
......
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