Commit 084388c2 authored by yoshiki iguchi's avatar yoshiki iguchi Committed by Commit Bot

Move the control buttons from dedicate widget to view

Previously, the buttons are on the dedicate widget to show them above
the ARC notification (NativeViewHost). This CL moves them to a view.

In addition, this CL adds a hacks for ARC notification which manipulates
the hierarycy of layers to show the buttons at top most.

Bug: b/62771497
Bug: 717455
Bug: 747217
Change-Id: I876c653e01d4a4237055bd4f763aa55017ba38ef
Reviewed-on: https://chromium-review.googlesource.com/579107
Commit-Queue: Yoshiki Iguchi <yoshiki@chromium.org>
Reviewed-by: default avatarYuichiro Hanada <yhanada@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488599}
parent 2551f6a3
...@@ -50,14 +50,6 @@ class ArcNotificationContentView::EventForwarder : public ui::EventHandler { ...@@ -50,14 +50,6 @@ class ArcNotificationContentView::EventForwarder : public ui::EventHandler {
private: private:
// ui::EventHandler // ui::EventHandler
void OnEvent(ui::Event* event) override { void OnEvent(ui::Event* event) override {
// Do not forward event targeted to the floating close button so that
// keyboard press and tap are handled properly.
if (owner_->floating_control_buttons_widget_ && event->target() &&
owner_->floating_control_buttons_widget_->GetNativeWindow() ==
event->target()) {
return;
}
// TODO(yoshiki): Use a better tigger (eg. focusing EditText on // TODO(yoshiki): Use a better tigger (eg. focusing EditText on
// notification) than clicking (crbug.com/697379). // notification) than clicking (crbug.com/697379).
if (event->type() == ui::ET_MOUSE_PRESSED) if (event->type() == ui::ET_MOUSE_PRESSED)
...@@ -84,6 +76,16 @@ class ArcNotificationContentView::EventForwarder : public ui::EventHandler { ...@@ -84,6 +76,16 @@ class ArcNotificationContentView::EventForwarder : public ui::EventHandler {
return; return;
} }
// Forward the event if the event is on the control buttons.
const gfx::Point& point_in_root_window = located_event->location();
if (owner_->HitTestControlButtons(point_in_root_window)) {
if (located_event->IsMouseEvent())
widget->OnMouseEvent(located_event->AsMouseEvent());
else if (located_event->IsGestureEvent())
widget->OnGestureEvent(located_event->AsGestureEvent());
return;
}
if (located_event->type() == ui::ET_MOUSE_MOVED || if (located_event->type() == ui::ET_MOUSE_MOVED ||
located_event->IsMouseWheelEvent()) { located_event->IsMouseWheelEvent()) {
widget->OnMouseEvent(located_event->AsMouseEvent()); widget->OnMouseEvent(located_event->AsMouseEvent());
...@@ -181,22 +183,6 @@ class ArcNotificationContentView::ContentViewDelegate ...@@ -181,22 +183,6 @@ class ArcNotificationContentView::ContentViewDelegate
explicit ContentViewDelegate(ArcNotificationContentView* owner) explicit ContentViewDelegate(ArcNotificationContentView* owner)
: owner_(owner) {} : owner_(owner) {}
bool IsCloseButtonFocused() const override {
if (!owner_->control_buttons_view_)
return false;
return owner_->control_buttons_view_->IsCloseButtonFocused();
}
void RequestFocusOnCloseButton() override {
if (owner_->control_buttons_view_)
owner_->control_buttons_view_->RequestFocusOnCloseButton();
owner_->UpdateControlButtonsVisibility();
}
void UpdateControlButtonsVisibility() override {
owner_->UpdateControlButtonsVisibility();
}
void OnSlideChanged() override { void OnSlideChanged() override {
if (owner_->slide_helper_) if (owner_->slide_helper_)
owner_->slide_helper_->Update(); owner_->slide_helper_->Update();
...@@ -218,7 +204,6 @@ ArcNotificationContentView::ArcNotificationContentView( ...@@ -218,7 +204,6 @@ ArcNotificationContentView::ArcNotificationContentView(
notification_key_(item->GetNotificationKey()), notification_key_(item->GetNotificationKey()),
event_forwarder_(new EventForwarder(this)) { event_forwarder_(new EventForwarder(this)) {
SetFocusBehavior(FocusBehavior::ALWAYS); SetFocusBehavior(FocusBehavior::ALWAYS);
set_notify_enter_exit_on_child(true);
item_->IncrementWindowRefCount(); item_->IncrementWindowRefCount();
item_->AddObserver(this); item_->AddObserver(this);
...@@ -260,55 +245,38 @@ ArcNotificationContentView::CreateContentViewDelegate() { ...@@ -260,55 +245,38 @@ ArcNotificationContentView::CreateContentViewDelegate() {
this); this);
} }
void ArcNotificationContentView::MaybeCreateFloatingControlButtons() { void ArcNotificationContentView::UpdateControlButtons() {
// Floating close button is a transient child of |surface_| and also part if (!item_)
// of the hosting widget's focus chain. It could only be created when both
// are present. Further, if we are being destroyed (|item_| is null), don't
// create the control buttons.
if (!surface_ || !GetWidget() || !item_)
return; return;
DCHECK(!control_buttons_view_);
DCHECK(!floating_control_buttons_widget_);
CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName()); CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName());
auto* notification_view = static_cast<ArcNotificationView*>(parent()); auto* notification_view = static_cast<ArcNotificationView*>(parent());
// Creates the control_buttons_view_, which collects all control buttons into notification_view->SetControlButtonsBackgroundColor(
// a horizontal box.
control_buttons_view_ =
new message_center::NotificationControlButtonsView(notification_view);
control_buttons_view_->SetBackgroundColor(
GetControlButtonBackgroundColor(item_->GetShownContents())); GetControlButtonBackgroundColor(item_->GetShownContents()));
control_buttons_view_->ShowSettingsButton( }
item_->IsOpeningSettingsSupported());
control_buttons_view_->ShowCloseButton(!item_->GetPinned());
views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.parent = surface_->GetWindow();
floating_control_buttons_widget_.reset(new views::Widget); void ArcNotificationContentView::UpdateControlButtonsVisibility() {
floating_control_buttons_widget_->Init(params); CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName());
floating_control_buttons_widget_->SetContentsView(control_buttons_view_); auto* notification_view = static_cast<ArcNotificationView*>(parent());
notification_view->UpdateControlButtonsVisibility();
}
// Put the close button into the focus chain. bool ArcNotificationContentView::HitTestControlButtons(
floating_control_buttons_widget_->SetFocusTraversableParent( const gfx::Point& point_in_root_window) {
GetWidget()->GetFocusTraversable()); CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName());
floating_control_buttons_widget_->SetFocusTraversableParentView(this); auto* notification_view = static_cast<ArcNotificationView*>(parent());
Layout(); gfx::Point point_in_parent = point_in_root_window;
views::View::ConvertPointToTarget(GetWidget()->GetRootView(),
notification_view, &point_in_parent);
return notification_view->HitTestControlButtons(point_in_parent);
} }
void ArcNotificationContentView::SetSurface(ArcNotificationSurface* surface) { void ArcNotificationContentView::SetSurface(ArcNotificationSurface* surface) {
if (surface_ == surface) if (surface_ == surface)
return; return;
// Reset |floating_control_buttons_widget_| when |surface_| is changed.
floating_control_buttons_widget_.reset();
control_buttons_view_ = nullptr;
if (surface_ && surface_->GetWindow()) { if (surface_ && surface_->GetWindow()) {
surface_->GetWindow()->RemoveObserver(this); surface_->GetWindow()->RemoveObserver(this);
surface_->GetWindow()->RemovePreTargetHandler(event_forwarder_.get()); surface_->GetWindow()->RemovePreTargetHandler(event_forwarder_.get());
...@@ -348,37 +316,6 @@ void ArcNotificationContentView::UpdatePreferredSize() { ...@@ -348,37 +316,6 @@ void ArcNotificationContentView::UpdatePreferredSize() {
SetPreferredSize(preferred_size); SetPreferredSize(preferred_size);
} }
void ArcNotificationContentView::UpdateControlButtonsVisibility() {
if (!control_buttons_view_)
return;
DCHECK(floating_control_buttons_widget_);
const bool target_visiblity =
IsMouseHovered() || (control_buttons_view_->IsCloseButtonFocused()) ||
(control_buttons_view_->IsSettingsButtonFocused());
if (target_visiblity == floating_control_buttons_widget_->IsVisible())
return;
if (target_visiblity)
floating_control_buttons_widget_->Show();
else
floating_control_buttons_widget_->Hide();
}
void ArcNotificationContentView::UpdatePinnedState() {
if (!item_)
return;
// Surface is not attached yet.
if (!control_buttons_view_)
return;
control_buttons_view_->ShowCloseButton(!item_->GetPinned());
Layout();
}
void ArcNotificationContentView::UpdateSnapshot() { void ArcNotificationContentView::UpdateSnapshot() {
// Bail if we have a |surface_| because it controls the sizes and paints UI. // Bail if we have a |surface_| because it controls the sizes and paints UI.
if (surface_) if (surface_)
...@@ -409,7 +346,7 @@ void ArcNotificationContentView::AttachSurface() { ...@@ -409,7 +346,7 @@ void ArcNotificationContentView::AttachSurface() {
slide_helper_->Update(); slide_helper_->Update();
// (Re-)create the floating buttons after |surface_| is attached to a widget. // (Re-)create the floating buttons after |surface_| is attached to a widget.
MaybeCreateFloatingControlButtons(); UpdateControlButtons();
} }
void ArcNotificationContentView::UpdateAccessibleName() { void ArcNotificationContentView::UpdateAccessibleName() {
...@@ -471,24 +408,6 @@ void ArcNotificationContentView::Layout() { ...@@ -471,24 +408,6 @@ void ArcNotificationContentView::Layout() {
// be positioned without the need to consider the transform. // be positioned without the need to consider the transform.
surface_->GetContentWindow()->SetTransform(transform); surface_->GetContentWindow()->SetTransform(transform);
if (control_buttons_view_) {
DCHECK(floating_control_buttons_widget_);
gfx::Rect control_buttons_bounds(contents_bounds);
int buttons_width = control_buttons_view_->GetPreferredSize().width();
int buttons_height = control_buttons_view_->GetPreferredSize().height();
control_buttons_bounds.set_x(control_buttons_bounds.right() -
buttons_width -
message_center::kControlButtonPadding);
control_buttons_bounds.set_y(control_buttons_bounds.y() +
message_center::kControlButtonPadding);
control_buttons_bounds.set_width(buttons_width);
control_buttons_bounds.set_height(buttons_height);
floating_control_buttons_widget_->SetBounds(control_buttons_bounds);
}
UpdateControlButtonsVisibility();
ash::wm::SnapWindowToPixelBoundary(surface_->GetWindow()); ash::wm::SnapWindowToPixelBoundary(surface_->GetWindow());
} }
...@@ -505,14 +424,6 @@ void ArcNotificationContentView::OnPaint(gfx::Canvas* canvas) { ...@@ -505,14 +424,6 @@ void ArcNotificationContentView::OnPaint(gfx::Canvas* canvas) {
contents_bounds.height(), false); contents_bounds.height(), false);
} }
void ArcNotificationContentView::OnMouseEntered(const ui::MouseEvent&) {
UpdateControlButtonsVisibility();
}
void ArcNotificationContentView::OnMouseExited(const ui::MouseEvent&) {
UpdateControlButtonsVisibility();
}
void ArcNotificationContentView::OnFocus() { void ArcNotificationContentView::OnFocus() {
CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName()); CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName());
...@@ -540,13 +451,6 @@ void ArcNotificationContentView::ActivateToast() { ...@@ -540,13 +451,6 @@ void ArcNotificationContentView::ActivateToast() {
} }
} }
views::FocusTraversable* ArcNotificationContentView::GetFocusTraversable() {
if (floating_control_buttons_widget_)
return static_cast<views::internal::RootView*>(
floating_control_buttons_widget_->GetRootView());
return nullptr;
}
bool ArcNotificationContentView::HandleAccessibleAction( bool ArcNotificationContentView::HandleAccessibleAction(
const ui::AXActionData& action_data) { const ui::AXActionData& action_data) {
if (item_ && action_data.action == ui::AX_ACTION_DO_DEFAULT) { if (item_ && action_data.action == ui::AX_ACTION_DO_DEFAULT) {
...@@ -592,13 +496,8 @@ void ArcNotificationContentView::OnItemDestroying() { ...@@ -592,13 +496,8 @@ void ArcNotificationContentView::OnItemDestroying() {
void ArcNotificationContentView::OnItemUpdated() { void ArcNotificationContentView::OnItemUpdated() {
UpdateAccessibleName(); UpdateAccessibleName();
UpdatePinnedState();
UpdateSnapshot(); UpdateSnapshot();
if (control_buttons_view_) { UpdateControlButtons();
DCHECK(floating_control_buttons_widget_);
control_buttons_view_->SetBackgroundColor(
GetControlButtonBackgroundColor(item_->GetShownContents()));
}
} }
void ArcNotificationContentView::OnNotificationSurfaceAdded( void ArcNotificationContentView::OnNotificationSurfaceAdded(
......
...@@ -15,19 +15,10 @@ ...@@ -15,19 +15,10 @@
#include "ui/aura/window_observer.h" #include "ui/aura/window_observer.h"
#include "ui/views/controls/native/native_view_host.h" #include "ui/views/controls/native/native_view_host.h"
namespace message_center {
class NotificationControlButtonsView;
}
namespace ui { namespace ui {
struct AXActionData; struct AXActionData;
} }
namespace views {
class FocusTraversable;
class Widget;
}
namespace arc { namespace arc {
class ArcNotificationSurface; class ArcNotificationSurface;
...@@ -61,7 +52,7 @@ class ArcNotificationContentView ...@@ -61,7 +52,7 @@ class ArcNotificationContentView
void CreateCloseButton(); void CreateCloseButton();
void CreateSettingsButton(); void CreateSettingsButton();
void MaybeCreateFloatingControlButtons(); void UpdateControlButtons();
void SetSurface(ArcNotificationSurface* surface); void SetSurface(ArcNotificationSurface* surface);
void UpdatePreferredSize(); void UpdatePreferredSize();
void UpdateControlButtonsVisibility(); void UpdateControlButtonsVisibility();
...@@ -70,17 +61,15 @@ class ArcNotificationContentView ...@@ -70,17 +61,15 @@ class ArcNotificationContentView
void AttachSurface(); void AttachSurface();
void ActivateToast(); void ActivateToast();
void UpdateAccessibleName(); void UpdateAccessibleName();
bool HitTestControlButtons(const gfx::Point& point);
// views::NativeViewHost // views::NativeViewHost
void ViewHierarchyChanged( void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override; const ViewHierarchyChangedDetails& details) override;
void Layout() override; void Layout() override;
void OnPaint(gfx::Canvas* canvas) override; void OnPaint(gfx::Canvas* canvas) override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
void OnFocus() override; void OnFocus() override;
void OnBlur() override; void OnBlur() override;
views::FocusTraversable* GetFocusTraversable() override;
bool HandleAccessibleAction(const ui::AXActionData& action) override; bool HandleAccessibleAction(const ui::AXActionData& action) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
...@@ -116,15 +105,6 @@ class ArcNotificationContentView ...@@ -116,15 +105,6 @@ class ArcNotificationContentView
// when a slide is in progress and restore the surface when it finishes. // when a slide is in progress and restore the surface when it finishes.
std::unique_ptr<SlideHelper> slide_helper_; std::unique_ptr<SlideHelper> slide_helper_;
// A control buttons on top of NotificationSurface. Needed because the
// aura::Window of NotificationSurface is added after hosting widget's
// RootView thus standard notification control buttons are always below
// it.
std::unique_ptr<views::Widget> floating_control_buttons_widget_;
message_center::NotificationControlButtonsView* control_buttons_view_ =
nullptr;
// Protects from call loops between Layout and OnWindowBoundsChanged. // Protects from call loops between Layout and OnWindowBoundsChanged.
bool in_layout_ = false; bool in_layout_ = false;
......
...@@ -12,9 +12,6 @@ namespace arc { ...@@ -12,9 +12,6 @@ namespace arc {
// directly without delegate. // directly without delegate.
class ArcNotificationContentViewDelegate { class ArcNotificationContentViewDelegate {
public: public:
virtual bool IsCloseButtonFocused() const = 0;
virtual void RequestFocusOnCloseButton() = 0;
virtual void UpdateControlButtonsVisibility() = 0;
virtual void OnSlideChanged() = 0; virtual void OnSlideChanged() = 0;
}; };
......
...@@ -242,8 +242,7 @@ class ArcNotificationContentViewTest : public views::ViewsTestBase { ...@@ -242,8 +242,7 @@ class ArcNotificationContentViewTest : public views::ViewsTestBase {
void PressCloseButton() { void PressCloseButton() {
DummyEvent dummy_event; DummyEvent dummy_event;
auto* control_buttons_view = auto* control_buttons_view = notification_view_->control_buttons_view_;
GetArcNotificationContentView()->control_buttons_view_;
message_center::PaddedButton* close_button = message_center::PaddedButton* close_button =
control_buttons_view->close_button_for_testing(); control_buttons_view->close_button_for_testing();
ASSERT_NE(nullptr, close_button); ASSERT_NE(nullptr, close_button);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <algorithm> #include <algorithm>
#include "ui/arc/notification/arc_notification_content_view.h"
#include "ui/arc/notification/arc_notification_content_view_delegate.h" #include "ui/arc/notification/arc_notification_content_view_delegate.h"
#include "ui/arc/notification/arc_notification_item.h" #include "ui/arc/notification/arc_notification_item.h"
#include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method.h"
...@@ -14,6 +15,7 @@ ...@@ -14,6 +15,7 @@
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/message_center/message_center_style.h" #include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/message_center_controller.h" #include "ui/message_center/views/message_center_controller.h"
#include "ui/message_center/views/notification_control_buttons_view.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h" #include "ui/views/controls/image_view.h"
...@@ -44,6 +46,18 @@ ArcNotificationView::ArcNotificationView( ...@@ -44,6 +46,18 @@ ArcNotificationView::ArcNotificationView(
contents_view_->background()->get_color()); contents_view_->background()->get_color());
} }
// Creates the control_buttons_view_, which collects all control buttons into
// a horizontal box.
DCHECK(!control_buttons_view_);
control_buttons_view_ =
new message_center::NotificationControlButtonsView(this);
AddChildView(control_buttons_view_);
control_buttons_view_->ReparentToWidgetLayer();
control_buttons_view_->ShowCloseButton(!notification.pinned());
control_buttons_view_->ShowSettingsButton(
notification.delegate()->ShouldDisplaySettingsButton());
focus_painter_ = views::Painter::CreateSolidFocusPainter( focus_painter_ = views::Painter::CreateSolidFocusPainter(
message_center::kFocusBorderColor, gfx::Insets(0, 1, 3, 2)); message_center::kFocusBorderColor, gfx::Insets(0, 1, 3, 2));
} }
...@@ -51,10 +65,12 @@ ArcNotificationView::ArcNotificationView( ...@@ -51,10 +65,12 @@ ArcNotificationView::ArcNotificationView(
ArcNotificationView::~ArcNotificationView() = default; ArcNotificationView::~ArcNotificationView() = default;
void ArcNotificationView::OnContentFocused() { void ArcNotificationView::OnContentFocused() {
UpdateControlButtonsVisibility();
SchedulePaint(); SchedulePaint();
} }
void ArcNotificationView::OnContentBlured() { void ArcNotificationView::OnContentBlured() {
UpdateControlButtonsVisibility();
SchedulePaint(); SchedulePaint();
} }
...@@ -66,15 +82,27 @@ void ArcNotificationView::SetDrawBackgroundAsActive(bool active) { ...@@ -66,15 +82,27 @@ void ArcNotificationView::SetDrawBackgroundAsActive(bool active) {
message_center::MessageView::SetDrawBackgroundAsActive(active); message_center::MessageView::SetDrawBackgroundAsActive(active);
} }
void ArcNotificationView::SetControlButtonsBackgroundColor(
const SkColor& bgcolor) {
control_buttons_view_->SetBackgroundColor(bgcolor);
}
void ArcNotificationView::UpdateWithNotification(
const message_center::Notification& notification) {
message_center::MessageView::UpdateWithNotification(notification);
control_buttons_view_->ShowCloseButton(!notification.pinned());
control_buttons_view_->ShowSettingsButton(
notification.delegate()->ShouldDisplaySettingsButton());
}
bool ArcNotificationView::IsCloseButtonFocused() const { bool ArcNotificationView::IsCloseButtonFocused() const {
if (!contents_view_delegate_) return control_buttons_view_->IsCloseButtonFocused();
return false;
return contents_view_delegate_->IsCloseButtonFocused();
} }
void ArcNotificationView::RequestFocusOnCloseButton() { void ArcNotificationView::RequestFocusOnCloseButton() {
if (contents_view_delegate_) control_buttons_view_->RequestFocusOnCloseButton();
contents_view_delegate_->RequestFocusOnCloseButton(); UpdateControlButtonsVisibility();
} }
const char* ArcNotificationView::GetClassName() const { const char* ArcNotificationView::GetClassName() const {
...@@ -82,8 +110,17 @@ const char* ArcNotificationView::GetClassName() const { ...@@ -82,8 +110,17 @@ const char* ArcNotificationView::GetClassName() const {
} }
void ArcNotificationView::UpdateControlButtonsVisibility() { void ArcNotificationView::UpdateControlButtonsVisibility() {
if (contents_view_delegate_) if (!control_buttons_view_)
contents_view_delegate_->UpdateControlButtonsVisibility(); return;
const bool target_visibility =
IsMouseHovered() || (control_buttons_view_->IsCloseButtonFocused()) ||
(control_buttons_view_->IsSettingsButtonFocused());
if (target_visibility == control_buttons_view_->GetButtonsVisible())
return;
control_buttons_view_->SetButtonsVisible(target_visibility);
} }
void ArcNotificationView::GetAccessibleNodeData(ui::AXNodeData* node_data) { void ArcNotificationView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
...@@ -108,7 +145,25 @@ gfx::Size ArcNotificationView::CalculatePreferredSize() const { ...@@ -108,7 +145,25 @@ gfx::Size ArcNotificationView::CalculatePreferredSize() const {
void ArcNotificationView::Layout() { void ArcNotificationView::Layout() {
message_center::MessageView::Layout(); message_center::MessageView::Layout();
contents_view_->SetBoundsRect(GetContentsBounds()); const gfx::Rect contents_bounds = GetContentsBounds();
contents_view_->SetBoundsRect(contents_bounds);
if (control_buttons_view_) {
gfx::Rect control_buttons_bounds(contents_bounds);
int buttons_width = control_buttons_view_->GetPreferredSize().width();
int buttons_height = control_buttons_view_->GetPreferredSize().height();
control_buttons_bounds.set_x(control_buttons_bounds.right() -
buttons_width -
message_center::kControlButtonPadding);
control_buttons_bounds.set_y(control_buttons_bounds.y() +
message_center::kControlButtonPadding);
control_buttons_bounds.set_width(buttons_width);
control_buttons_bounds.set_height(buttons_height);
control_buttons_view_->SetBoundsRect(control_buttons_bounds);
}
UpdateControlButtonsVisibility();
// If the content view claims focus, defer focus handling to the content view. // If the content view claims focus, defer focus handling to the content view.
if (contents_view_->IsFocusable()) if (contents_view_->IsFocusable())
...@@ -138,6 +193,21 @@ void ArcNotificationView::OnPaint(gfx::Canvas* canvas) { ...@@ -138,6 +193,21 @@ void ArcNotificationView::OnPaint(gfx::Canvas* canvas) {
focus_painter_.get()); focus_painter_.get());
} }
bool ArcNotificationView::HitTestControlButtons(const gfx::Point& point) {
gfx::Point point_in_buttons = point;
views::View::ConvertPointToTarget(this, control_buttons_view_,
&point_in_buttons);
return control_buttons_view_->HitTestPoint(point_in_buttons);
}
void ArcNotificationView::OnMouseEntered(const ui::MouseEvent&) {
UpdateControlButtonsVisibility();
}
void ArcNotificationView::OnMouseExited(const ui::MouseEvent&) {
UpdateControlButtonsVisibility();
}
bool ArcNotificationView::OnKeyPressed(const ui::KeyEvent& event) { bool ArcNotificationView::OnKeyPressed(const ui::KeyEvent& event) {
if (contents_view_) { if (contents_view_) {
ui::InputMethod* input_method = contents_view_->GetInputMethod(); ui::InputMethod* input_method = contents_view_->GetInputMethod();
...@@ -157,6 +227,10 @@ bool ArcNotificationView::OnKeyPressed(const ui::KeyEvent& event) { ...@@ -157,6 +227,10 @@ bool ArcNotificationView::OnKeyPressed(const ui::KeyEvent& event) {
return message_center::MessageView::OnKeyPressed(event); return message_center::MessageView::OnKeyPressed(event);
} }
void ArcNotificationView::OnLayerBoundsChanged(const gfx::Rect& old_bounds) {
control_buttons_view_->AdjustLayerBounds();
}
void ArcNotificationView::ChildPreferredSizeChanged(View* child) { void ArcNotificationView::ChildPreferredSizeChanged(View* child) {
// Notify MessageCenterController when the custom content changes size, // Notify MessageCenterController when the custom content changes size,
// as it may need to relayout. // as it may need to relayout.
......
...@@ -12,6 +12,10 @@ namespace views { ...@@ -12,6 +12,10 @@ namespace views {
class Painter; class Painter;
} }
namespace message_center {
class NotificationControlButtonsView;
}
namespace arc { namespace arc {
class ArcNotificationContentViewDelegate; class ArcNotificationContentViewDelegate;
...@@ -30,6 +34,13 @@ class ArcNotificationView : public message_center::MessageView { ...@@ -30,6 +34,13 @@ class ArcNotificationView : public message_center::MessageView {
const message_center::Notification& notification); const message_center::Notification& notification);
~ArcNotificationView() override; ~ArcNotificationView() override;
bool HitTestControlButtons(const gfx::Point& point);
void SetControlButtonsBackgroundColor(const SkColor& bgcolor);
message_center::NotificationControlButtonsView* control_buttons_view() const {
return control_buttons_view_;
}
// These method are called by the content view when focus handling is defered // These method are called by the content view when focus handling is defered
// to the content. // to the content.
void OnContentFocused(); void OnContentFocused();
...@@ -41,6 +52,8 @@ class ArcNotificationView : public message_center::MessageView { ...@@ -41,6 +52,8 @@ class ArcNotificationView : public message_center::MessageView {
void RequestFocusOnCloseButton() override; void RequestFocusOnCloseButton() override;
void UpdateControlButtonsVisibility() override; void UpdateControlButtonsVisibility() override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
void UpdateWithNotification(
const message_center::Notification& notification) override;
// views::SlideOutController::Delegate: // views::SlideOutController::Delegate:
void OnSlideChanged() override; void OnSlideChanged() override;
...@@ -52,7 +65,10 @@ class ArcNotificationView : public message_center::MessageView { ...@@ -52,7 +65,10 @@ class ArcNotificationView : public message_center::MessageView {
bool HasFocus() const override; bool HasFocus() const override;
void RequestFocus() override; void RequestFocus() override;
void OnPaint(gfx::Canvas* canvas) override; void OnPaint(gfx::Canvas* canvas) override;
void OnMouseEntered(const ui::MouseEvent&) override;
void OnMouseExited(const ui::MouseEvent&) override;
bool OnKeyPressed(const ui::KeyEvent& event) override; bool OnKeyPressed(const ui::KeyEvent& event) override;
void OnLayerBoundsChanged(const gfx::Rect& old_bounds) override;
void ChildPreferredSizeChanged(View* child) override; void ChildPreferredSizeChanged(View* child) override;
bool HandleAccessibleAction(const ui::AXActionData& action) override; bool HandleAccessibleAction(const ui::AXActionData& action) override;
...@@ -64,6 +80,13 @@ class ArcNotificationView : public message_center::MessageView { ...@@ -64,6 +80,13 @@ class ArcNotificationView : public message_center::MessageView {
views::View* contents_view_ = nullptr; views::View* contents_view_ = nullptr;
std::unique_ptr<ArcNotificationContentViewDelegate> contents_view_delegate_; std::unique_ptr<ArcNotificationContentViewDelegate> contents_view_delegate_;
// A control buttons on top of NotificationSurface. Needed because the
// aura::Window of NotificationSurface is added after hosting widget's
// RootView thus standard notification control buttons are always below
// it.
message_center::NotificationControlButtonsView* control_buttons_view_ =
nullptr;
std::unique_ptr<views::Painter> focus_painter_; std::unique_ptr<views::Painter> focus_painter_;
DISALLOW_COPY_AND_ASSIGN(ArcNotificationView); DISALLOW_COPY_AND_ASSIGN(ArcNotificationView);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/arc/notification/arc_notification_content_view.h"
#include "ui/arc/notification/arc_notification_content_view_delegate.h" #include "ui/arc/notification/arc_notification_content_view_delegate.h"
#include "ui/arc/notification/arc_notification_view.h" #include "ui/arc/notification/arc_notification_view.h"
#include "ui/base/ime/dummy_text_input_client.h" #include "ui/base/ime/dummy_text_input_client.h"
...@@ -47,6 +48,9 @@ class TestNotificationContentsView : public views::View { ...@@ -47,6 +48,9 @@ class TestNotificationContentsView : public views::View {
} }
// views::View // views::View
const char* GetClassName() const override {
return ArcNotificationContentView::kViewClassName;
}
bool OnMousePressed(const ui::MouseEvent& event) override { bool OnMousePressed(const ui::MouseEvent& event) override {
++mouse_event_count_; ++mouse_event_count_;
return true; return true;
...@@ -74,9 +78,6 @@ class TestNotificationContentsView : public views::View { ...@@ -74,9 +78,6 @@ class TestNotificationContentsView : public views::View {
class TestContentViewDelegate : public ArcNotificationContentViewDelegate { class TestContentViewDelegate : public ArcNotificationContentViewDelegate {
public: public:
bool IsCloseButtonFocused() const override { return false; }
void RequestFocusOnCloseButton() override {}
void UpdateControlButtonsVisibility() override {}
void OnSlideChanged() override {} void OnSlideChanged() override {}
}; };
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include "ui/strings/grit/ui_strings.h" #include "ui/strings/grit/ui_strings.h"
#include "ui/views/background.h" #include "ui/views/background.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/widget/widget.h"
namespace { namespace {
...@@ -34,19 +36,75 @@ namespace message_center { ...@@ -34,19 +36,75 @@ namespace message_center {
const char NotificationControlButtonsView::kViewClassName[] = const char NotificationControlButtonsView::kViewClassName[] =
"NotificationControlButtonsView"; "NotificationControlButtonsView";
// InnerView is the floaing view which contains buttons. InnerView can a
// dedicate layer as a direct child of the root layer, so that it can be shown
// above the NativeViewHost of ARC notification.
class NotificationControlButtonsView::InnerView : public views::View {
public:
InnerView(NotificationControlButtonsView* parent) : parent_(parent) {
SetPaintToLayer(ui::LAYER_TEXTURED);
layer()->SetFillsBoundsOpaquely(false);
}
~InnerView() override = default;
#if defined(OS_CHROMEOS)
// views::View override:
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override {
// Update the layer hierarchy.
// See NotificationControlButtonsView::CalculateOffsetToAncestorWithLayer()
// for detail.
UpdateParentLayer();
}
#endif // defined(OS_CHROMEOS)
void SetLayerVisible(bool visible) {
DCHECK(layer());
DCHECK_EQ(parent(), parent_);
layer()->SetOpacity(visible ? 1.0 : 0.0);
}
bool GetLayerVisible() const {
DCHECK(layer());
DCHECK_EQ(parent(), parent_);
return layer()->opacity() != 0.0;
}
#if defined(OS_CHROMEOS)
void AdjustLayerBounds() {
DCHECK(layer());
DCHECK_EQ(parent(), parent_);
if (!visible() || layer()->opacity() == 0)
return;
// Adjust the position of this layer.
layer()->SetBounds(GetLocalBounds() + gfx::Vector2d(GetMirroredX(), y()) +
parent_->CalculateOffsetToAncestorWithLayer(nullptr));
SnapLayerToPixelBoundary();
}
#endif // defined(OS_CHROMEOS)
private:
NotificationControlButtonsView* const parent_;
DISALLOW_COPY_AND_ASSIGN(InnerView);
};
NotificationControlButtonsView::NotificationControlButtonsView( NotificationControlButtonsView::NotificationControlButtonsView(
MessageView* message_view) MessageView* message_view)
: message_view_(message_view), : message_view_(message_view),
bgcolor_origin_(kInitialBackgroundColor), bgcolor_origin_(kInitialBackgroundColor),
bgcolor_target_(kInitialBackgroundColor) { bgcolor_target_(kInitialBackgroundColor) {
DCHECK(message_view); DCHECK(message_view);
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal)); SetLayoutManager(new views::FillLayout());
// Use layer to change the opacity. buttons_container_ = base::MakeUnique<InnerView>(this);
SetPaintToLayer(); buttons_container_->set_owned_by_client();
layer()->SetFillsBoundsOpaquely(false); buttons_container_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal));
SetBackground(views::CreateSolidBackground(kInitialBackgroundColor)); buttons_container_->SetBackground(
views::CreateSolidBackground(kInitialBackgroundColor));
AddChildView(buttons_container_.get());
} }
NotificationControlButtonsView::~NotificationControlButtonsView() = default; NotificationControlButtonsView::~NotificationControlButtonsView() = default;
...@@ -65,10 +123,10 @@ void NotificationControlButtonsView::ShowCloseButton(bool show) { ...@@ -65,10 +123,10 @@ void NotificationControlButtonsView::ShowCloseButton(bool show) {
views::CreateSolidBackground(SK_ColorTRANSPARENT)); views::CreateSolidBackground(SK_ColorTRANSPARENT));
// Add the button at the last. // Add the button at the last.
DCHECK_LE(child_count(), 1); DCHECK_LE(buttons_container_->child_count(), 1);
AddChildView(close_button_.get()); buttons_container_->AddChildView(close_button_.get());
} else if (!show && close_button_) { } else if (!show && close_button_) {
DCHECK(Contains(close_button_.get())); DCHECK(buttons_container_->Contains(close_button_.get()));
close_button_.reset(); close_button_.reset();
} }
} }
...@@ -87,19 +145,19 @@ void NotificationControlButtonsView::ShowSettingsButton(bool show) { ...@@ -87,19 +145,19 @@ void NotificationControlButtonsView::ShowSettingsButton(bool show) {
views::CreateSolidBackground(SK_ColorTRANSPARENT)); views::CreateSolidBackground(SK_ColorTRANSPARENT));
// Add the button at the first. // Add the button at the first.
DCHECK_LE(child_count(), 1); DCHECK_LE(buttons_container_->child_count(), 1);
AddChildViewAt(settings_button_.get(), 0); buttons_container_->AddChildViewAt(settings_button_.get(), 0);
} else if (!show && settings_button_) { } else if (!show && settings_button_) {
DCHECK(Contains(settings_button_.get())); DCHECK(buttons_container_->Contains(settings_button_.get()));
settings_button_.reset(); settings_button_.reset();
} }
} }
void NotificationControlButtonsView::SetBackgroundColor( void NotificationControlButtonsView::SetBackgroundColor(
const SkColor& target_bgcolor) { const SkColor& target_bgcolor) {
DCHECK(background()); DCHECK(buttons_container_->background());
if (background()->get_color() != target_bgcolor) { if (buttons_container_->background()->get_color() != target_bgcolor) {
bgcolor_origin_ = background()->get_color(); bgcolor_origin_ = buttons_container_->background()->get_color();
bgcolor_target_ = target_bgcolor; bgcolor_target_ = target_bgcolor;
if (bgcolor_animation_) if (bgcolor_animation_)
...@@ -110,14 +168,18 @@ void NotificationControlButtonsView::SetBackgroundColor( ...@@ -110,14 +168,18 @@ void NotificationControlButtonsView::SetBackgroundColor(
} }
} }
void NotificationControlButtonsView::SetVisible(bool visible) { void NotificationControlButtonsView::SetButtonsVisible(bool visible) {
DCHECK(layer()); DCHECK(buttons_container_->layer());
// Manipulate the opacity instead of changing the visibility to keep the tab // Manipulate the opacity instead of changing the visibility to keep the tab
// order even when the view is invisible. // order even when the view is invisible.
layer()->SetOpacity(visible ? 1. : 0.); buttons_container_->SetLayerVisible(visible);
set_can_process_events_within_subtree(visible); set_can_process_events_within_subtree(visible);
} }
bool NotificationControlButtonsView::GetButtonsVisible() const {
return buttons_container_->GetLayerVisible();
}
void NotificationControlButtonsView::RequestFocusOnCloseButton() { void NotificationControlButtonsView::RequestFocusOnCloseButton() {
if (close_button_) if (close_button_)
close_button_->RequestFocus(); close_button_->RequestFocus();
...@@ -131,6 +193,28 @@ bool NotificationControlButtonsView::IsSettingsButtonFocused() const { ...@@ -131,6 +193,28 @@ bool NotificationControlButtonsView::IsSettingsButtonFocused() const {
return settings_button_ && settings_button_->HasFocus(); return settings_button_ && settings_button_->HasFocus();
} }
#if defined(OS_CHROMEOS)
void NotificationControlButtonsView::ReparentToWidgetLayer() {
// Reparent the inner container from the MessageView's layer to the widget
// layer. This calls this class's CalculateOffsetToAncestorWithLayer
// internally and reparents the layer.
buttons_container_->SetPaintToLayer(ui::LAYER_TEXTURED);
is_layer_parent_widget_ = true;
}
void NotificationControlButtonsView::AdjustLayerBounds() {
// If the flag is not set, we don need to adjust the bound explicitly.
if (!is_layer_parent_widget_)
return;
DCHECK_EQ(1, child_count());
DCHECK_EQ(buttons_container_.get(), child_at(0));
buttons_container_->AdjustLayerBounds();
}
#endif // defined(OS_CHROMEOS)
message_center::PaddedButton* message_center::PaddedButton*
NotificationControlButtonsView::close_button_for_testing() const { NotificationControlButtonsView::close_button_for_testing() const {
return close_button_.get(); return close_button_.get();
...@@ -145,6 +229,38 @@ const char* NotificationControlButtonsView::GetClassName() const { ...@@ -145,6 +229,38 @@ const char* NotificationControlButtonsView::GetClassName() const {
return kViewClassName; return kViewClassName;
} }
#if defined(OS_CHROMEOS)
void NotificationControlButtonsView::ReorderChildLayers(
ui::Layer* parent_layer) {
// If the flag is set, do nothing, since the layer of the child view is a
// child of th widget.
if (!is_layer_parent_widget_)
return views::View::ReorderChildLayers(parent_layer);
}
gfx::Vector2d
NotificationControlButtonsView::CalculateOffsetToAncestorWithLayer(
ui::Layer** layer_parent) {
// If the flag is not set, do the default behavior.
if (!is_layer_parent_widget_)
return views::View::CalculateOffsetToAncestorWithLayer(layer_parent);
if (!parent() || !GetWidget())
return gfx::Vector2d();
// Sets the widget layer as the parent layer.
if (layer_parent)
*layer_parent = GetWidget()->GetLayer();
// Returns the position relative to the widget origin.
gfx::Point pos(GetMirroredX(), y());
views::View::ConvertPointToWidget(parent(), &pos);
return gfx::Vector2d(pos.x(), pos.y());
}
#endif // defined(OS_CHROMEOS)
void NotificationControlButtonsView::ButtonPressed(views::Button* sender, void NotificationControlButtonsView::ButtonPressed(views::Button* sender,
const ui::Event& event) { const ui::Event& event) {
if (close_button_ && sender == close_button_.get()) { if (close_button_ && sender == close_button_.get()) {
...@@ -160,8 +276,8 @@ void NotificationControlButtonsView::AnimationProgressed( ...@@ -160,8 +276,8 @@ void NotificationControlButtonsView::AnimationProgressed(
const SkColor color = gfx::Tween::ColorValueBetween( const SkColor color = gfx::Tween::ColorValueBetween(
animation->GetCurrentValue(), bgcolor_origin_, bgcolor_target_); animation->GetCurrentValue(), bgcolor_origin_, bgcolor_target_);
SetBackground(views::CreateSolidBackground(color)); buttons_container_->SetBackground(views::CreateSolidBackground(color));
SchedulePaint(); buttons_container_->SchedulePaint();
} }
void NotificationControlButtonsView::AnimationEnded( void NotificationControlButtonsView::AnimationEnded(
...@@ -177,8 +293,9 @@ void NotificationControlButtonsView::AnimationCanceled( ...@@ -177,8 +293,9 @@ void NotificationControlButtonsView::AnimationCanceled(
NOTREACHED(); NOTREACHED();
bgcolor_origin_ = bgcolor_target_; bgcolor_origin_ = bgcolor_target_;
SetBackground(views::CreateSolidBackground(bgcolor_target_)); buttons_container_->SetBackground(
SchedulePaint(); views::CreateSolidBackground(bgcolor_target_));
buttons_container_->SchedulePaint();
} }
} // namespace message_center } // namespace message_center
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_CONTROL_BUTTONS_VIEW_H_ #define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_CONTROL_BUTTONS_VIEW_H_
#include "base/macros.h" #include "base/macros.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/animation/animation_delegate.h"
#include "ui/message_center/message_center_export.h" #include "ui/message_center/message_center_export.h"
...@@ -44,6 +45,10 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView ...@@ -44,6 +45,10 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView
// Set the background color of the view. // Set the background color of the view.
void SetBackgroundColor(const SkColor& target_bgcolor); void SetBackgroundColor(const SkColor& target_bgcolor);
// Set and get the visi8blity of buttons.
void SetButtonsVisible(bool visible);
bool GetButtonsVisible() const;
// Request the focus on the close button. // Request the focus on the close button.
void RequestFocusOnCloseButton(); void RequestFocusOnCloseButton();
...@@ -58,9 +63,18 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView ...@@ -58,9 +63,18 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView
message_center::PaddedButton* close_button_for_testing() const; message_center::PaddedButton* close_button_for_testing() const;
message_center::PaddedButton* settings_button_for_testing() const; message_center::PaddedButton* settings_button_for_testing() const;
#if defined(OS_CHROMEOS)
void ReparentToWidgetLayer();
void AdjustLayerBounds();
#endif // defined(OS_CHROMEOS)
// views::View // views::View
const char* GetClassName() const override; const char* GetClassName() const override;
void SetVisible(bool visible) override; #if defined(OS_CHROMEOS)
void ReorderChildLayers(ui::Layer* parent_layer) override;
gfx::Vector2d CalculateOffsetToAncestorWithLayer(
ui::Layer** layer_parent) override;
#endif // defined(OS_CHROMEOS)
// views::ButtonListener // views::ButtonListener
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
...@@ -71,8 +85,13 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView ...@@ -71,8 +85,13 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView
void AnimationCanceled(const gfx::Animation* animation) override; void AnimationCanceled(const gfx::Animation* animation) override;
private: private:
// InnerView is the container for buttons. NotificationControlButtonsView has
// only one child which is InnerView.
class InnerView;
MessageView* message_view_; MessageView* message_view_;
std::unique_ptr<InnerView> buttons_container_;
std::unique_ptr<message_center::PaddedButton> close_button_; std::unique_ptr<message_center::PaddedButton> close_button_;
std::unique_ptr<message_center::PaddedButton> settings_button_; std::unique_ptr<message_center::PaddedButton> settings_button_;
...@@ -80,6 +99,10 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView ...@@ -80,6 +99,10 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView
SkColor bgcolor_origin_; SkColor bgcolor_origin_;
SkColor bgcolor_target_; SkColor bgcolor_target_;
#if defined(OS_CHROMEOS)
bool is_layer_parent_widget_ = false;
#endif // defined(OS_CHROMEOS)
DISALLOW_COPY_AND_ASSIGN(NotificationControlButtonsView); DISALLOW_COPY_AND_ASSIGN(NotificationControlButtonsView);
}; };
......
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