Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: ui/arc/notification/arc_custom_notification_view.cc

Issue 2221073002: arc: Custom notification improvements (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments in #2 Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/arc/notification/arc_custom_notification_view.h" 5 #include "ui/arc/notification/arc_custom_notification_view.h"
6 6
7 #include "components/exo/notification_surface.h" 7 #include "components/exo/notification_surface.h"
8 #include "components/exo/surface.h" 8 #include "components/exo/surface.h"
9 #include "third_party/skia/include/core/SkColor.h" 9 #include "third_party/skia/include/core/SkColor.h"
10 #include "ui/base/l10n/l10n_util.h" 10 #include "ui/base/l10n/l10n_util.h"
11 #include "ui/base/resource/resource_bundle.h" 11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/compositor/layer_animation_observer.h"
13 #include "ui/display/screen.h"
14 #include "ui/events/event_handler.h"
15 #include "ui/gfx/transform.h"
12 #include "ui/message_center/message_center_style.h" 16 #include "ui/message_center/message_center_style.h"
13 #include "ui/resources/grit/ui_resources.h" 17 #include "ui/resources/grit/ui_resources.h"
14 #include "ui/strings/grit/ui_strings.h" 18 #include "ui/strings/grit/ui_strings.h"
15 #include "ui/views/background.h" 19 #include "ui/views/background.h"
16 #include "ui/views/border.h" 20 #include "ui/views/border.h"
17 #include "ui/views/controls/button/image_button.h" 21 #include "ui/views/controls/button/image_button.h"
18 #include "ui/views/widget/widget.h" 22 #include "ui/views/widget/widget.h"
23 #include "ui/wm/core/window_util.h"
19 24
20 namespace arc { 25 namespace arc {
21 26
27 class ArcCustomNotificationView::EventForwarder : public ui::EventHandler {
28 public:
29 explicit EventForwarder(ArcCustomNotificationView* owner) : owner_(owner) {}
30 ~EventForwarder() override = default;
31
32 private:
33 // ui::EventHandler
34 void OnKeyEvent(ui::KeyEvent* event) override { owner_->OnKeyEvent(event); }
35 void OnMouseEvent(ui::MouseEvent* event) override {
36 owner_->OnMouseEvent(event);
37 }
38 void OnGestureEvent(ui::GestureEvent* event) override {
39 owner_->OnGestureEvent(event);
40 }
sadrul 2016/08/10 03:26:39 Do you only care about these events, or do you wan
xiyuan 2016/08/10 16:28:07 OnEvent makes more sense. Replace individual handl
41
42 ArcCustomNotificationView* const owner_;
43
44 DISALLOW_COPY_AND_ASSIGN(EventForwarder);
45 };
46
47 class ArcCustomNotificationView::SlideHelper
48 : public ui::LayerAnimationObserver {
49 public:
50 SlideHelper(ArcCustomNotificationView* owner) : owner_(owner) {
sadrul 2016/08/10 03:26:39 explicit
xiyuan 2016/08/10 16:28:07 Done.
51 owner_->parent()->layer()->GetAnimator()->AddObserver(this);
52
53 // Reset opacity to 1 to handle to case when the surface is sliding before
54 // getting managed by this class, e.g. sliding in a popup before showing
55 // in a message center view.
56 if (owner_->surface_ && owner_->surface_->window())
57 owner_->surface_->window()->layer()->SetOpacity(1.0f);
58 }
59 ~SlideHelper() override {
60 owner_->parent()->layer()->GetAnimator()->RemoveObserver(this);
61 }
62
63 void Update() {
64 const bool has_animation =
65 owner_->parent()->layer()->GetAnimator()->is_animating();
66 const bool has_transform = !owner_->parent()->GetTransform().IsIdentity();
67 const bool sliding = has_transform || has_animation;
68 if (sliding_ == sliding)
69 return;
70
71 sliding_ = sliding;
72
73 if (sliding_)
74 OnSlideStart();
75 else
76 OnSlideEnd();
77 }
78
79 private:
80 void OnSlideStart() {
81 if (!owner_->surface_ || !owner_->surface_->window())
82 return;
83 surface_copy_ = ::wm::RecreateLayers(owner_->surface_->window(), nullptr);
84 owner_->layer()->Add(surface_copy_->root());
85 owner_->surface_->window()->layer()->SetOpacity(0.0f);
86 }
87
88 void OnSlideEnd() {
89 if (!owner_->surface_ || !owner_->surface_->window())
90 return;
91 owner_->surface_->window()->layer()->SetOpacity(1.0f);
92 owner_->Layout();
93 surface_copy_.reset();
94 }
95
96 // ui::LayerAnimationObserver
97 void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq) override {
98 Update();
99 }
100 void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq) override {
101 Update();
102 }
103 void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {}
104
105 ArcCustomNotificationView* const owner_;
106 bool sliding_ = false;
107 std::unique_ptr<ui::LayerTreeOwner> surface_copy_;
108
109 DISALLOW_COPY_AND_ASSIGN(SlideHelper);
110 };
111
22 ArcCustomNotificationView::ArcCustomNotificationView( 112 ArcCustomNotificationView::ArcCustomNotificationView(
23 ArcCustomNotificationItem* item, 113 ArcCustomNotificationItem* item,
24 exo::NotificationSurface* surface) 114 exo::NotificationSurface* surface)
25 : item_(item), surface_(surface) { 115 : item_(item), event_forwarder_(new EventForwarder(this)) {
116 SetSurface(surface);
26 item_->AddObserver(this); 117 item_->AddObserver(this);
27 OnItemPinnedChanged(); 118 OnItemPinnedChanged();
28 surface_->window()->AddObserver(this); 119
120 // Create a layer as an anchor to insert surface copy during a slide.
121 SetPaintToLayer(true);
29 } 122 }
30 123
31 ArcCustomNotificationView::~ArcCustomNotificationView() { 124 ArcCustomNotificationView::~ArcCustomNotificationView() {
125 SetSurface(nullptr);
32 if (item_) 126 if (item_)
33 item_->RemoveObserver(this); 127 item_->RemoveObserver(this);
34 if (surface_ && surface_->window())
35 surface_->window()->RemoveObserver(this);
36 } 128 }
37 129
38 void ArcCustomNotificationView::CreateFloatingCloseButton() { 130 void ArcCustomNotificationView::CreateFloatingCloseButton() {
39 floating_close_button_ = new views::ImageButton(this); 131 floating_close_button_ = new views::ImageButton(this);
40 floating_close_button_->set_background( 132 floating_close_button_->set_background(
41 views::Background::CreateSolidBackground(SK_ColorTRANSPARENT)); 133 views::Background::CreateSolidBackground(SK_ColorTRANSPARENT));
42 floating_close_button_->SetBorder( 134 floating_close_button_->SetBorder(
43 views::Border::CreateEmptyBorder(5, 5, 5, 5)); 135 views::Border::CreateEmptyBorder(5, 5, 5, 5));
44 136
45 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 137 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
(...skipping 11 matching lines...) Expand all
57 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME)); 149 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
58 150
59 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); 151 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
60 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 152 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
61 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 153 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
62 params.parent = surface_->window(); 154 params.parent = surface_->window();
63 155
64 floating_close_button_widget_.reset(new views::Widget); 156 floating_close_button_widget_.reset(new views::Widget);
65 floating_close_button_widget_->Init(params); 157 floating_close_button_widget_->Init(params);
66 floating_close_button_widget_->SetContentsView(floating_close_button_); 158 floating_close_button_widget_->SetContentsView(floating_close_button_);
67 floating_close_button_widget_->Show();
68 159
69 Layout(); 160 Layout();
70 } 161 }
71 162
163 void ArcCustomNotificationView::SetSurface(exo::NotificationSurface* surface) {
164 if (surface_ == surface)
165 return;
166
167 if (surface_ && surface_->window()) {
168 surface_->window()->RemoveObserver(this);
169 surface_->window()->RemovePreTargetHandler(event_forwarder_.get());
170 }
171
172 surface_ = surface;
173
174 if (surface_ && surface_->window()) {
175 surface_->window()->AddObserver(this);
176 surface_->window()->AddPreTargetHandler(event_forwarder_.get());
sadrul 2016/08/10 03:26:39 Can you clarify why we need a pre-target handler f
xiyuan 2016/08/10 16:28:07 This is because |surface_| has children aura::Wind
177 }
178 }
179
72 void ArcCustomNotificationView::UpdatePreferredSize() { 180 void ArcCustomNotificationView::UpdatePreferredSize() {
73 gfx::Size preferred_size = surface_->GetSize(); 181 gfx::Size preferred_size = surface_->GetSize();
74 if (preferred_size.width() != message_center::kNotificationWidth) { 182 if (preferred_size.width() != message_center::kNotificationWidth) {
75 const float scale = static_cast<float>(message_center::kNotificationWidth) / 183 const float scale = static_cast<float>(message_center::kNotificationWidth) /
76 preferred_size.width(); 184 preferred_size.width();
77 preferred_size.SetSize(message_center::kNotificationWidth, 185 preferred_size.SetSize(message_center::kNotificationWidth,
78 preferred_size.height() * scale); 186 preferred_size.height() * scale);
79 } 187 }
80 188
81 SetPreferredSize(preferred_size); 189 SetPreferredSize(preferred_size);
82 } 190 }
83 191
192 void ArcCustomNotificationView::UpdateCloseButtonVisiblity() {
193 if (!surface_ || !floating_close_button_widget_)
194 return;
195
196 const bool target_visiblity =
197 surface_->window()->GetBoundsInScreen().Contains(
198 display::Screen::GetScreen()->GetCursorScreenPoint());
199 if (target_visiblity == floating_close_button_widget_->IsVisible())
200 return;
201
202 if (target_visiblity)
203 floating_close_button_widget_->Show();
204 else
205 floating_close_button_widget_->Hide();
206 }
sadrul 2016/08/10 03:26:39 Consider using views::MouseWatcher (with MouseWatc
xiyuan 2016/08/10 16:28:07 Contains() is needed for determining the visibilit
207
84 void ArcCustomNotificationView::ViewHierarchyChanged( 208 void ArcCustomNotificationView::ViewHierarchyChanged(
85 const views::View::ViewHierarchyChangedDetails& details) { 209 const views::View::ViewHierarchyChangedDetails& details) {
86 views::Widget* widget = GetWidget(); 210 views::Widget* widget = GetWidget();
87 211
212 if (!details.is_add) {
213 // Resets slide helper when this view is removed from its parent.
214 slide_helper_.reset();
215 }
216
88 // Bail if native_view() has attached to a different widget. 217 // Bail if native_view() has attached to a different widget.
89 if (widget && native_view() && 218 if (widget && native_view() &&
90 views::Widget::GetTopLevelWidgetForNativeView(native_view()) != widget) { 219 views::Widget::GetTopLevelWidgetForNativeView(native_view()) != widget) {
91 return; 220 return;
92 } 221 }
93 222
94 views::NativeViewHost::ViewHierarchyChanged(details); 223 views::NativeViewHost::ViewHierarchyChanged(details);
95 224
96 if (!widget || !surface_ || !details.is_add) 225 if (!widget || !surface_ || !details.is_add)
97 return; 226 return;
98 227
99 UpdatePreferredSize(); 228 UpdatePreferredSize();
100 Attach(surface_->window()); 229 Attach(surface_->window());
230
231 // Creates slide helper after this view is added to its parent.
232 slide_helper_.reset(new SlideHelper(this));
101 } 233 }
102 234
103 void ArcCustomNotificationView::Layout() { 235 void ArcCustomNotificationView::Layout() {
104 views::NativeViewHost::Layout(); 236 views::NativeViewHost::Layout();
105 237
106 if (!surface_ || !GetWidget()) 238 if (!surface_ || !GetWidget())
107 return; 239 return;
108 240
109 // Scale notification surface if necessary. 241 // Scale notification surface if necessary.
110 gfx::Transform transform; 242 gfx::Transform transform;
111 const gfx::Size surface_size = surface_->GetSize(); 243 const gfx::Size surface_size = surface_->GetSize();
112 const gfx::Size contents_size = GetContentsBounds().size(); 244 const gfx::Size contents_size = GetContentsBounds().size();
113 if (!surface_size.IsEmpty() && !contents_size.IsEmpty()) { 245 if (!surface_size.IsEmpty() && !contents_size.IsEmpty()) {
114 transform.Scale( 246 transform.Scale(
115 static_cast<float>(contents_size.width()) / surface_size.width(), 247 static_cast<float>(contents_size.width()) / surface_size.width(),
116 static_cast<float>(contents_size.height()) / surface_size.height()); 248 static_cast<float>(contents_size.height()) / surface_size.height());
117 } 249 }
118 surface_->window()->SetTransform(transform); 250 surface_->window()->SetTransform(transform);
119 251
120 if (!floating_close_button_widget_) 252 if (!floating_close_button_widget_)
121 return; 253 return;
122 254
123 gfx::Rect surface_local_bounds(surface_->GetSize()); 255 gfx::Rect surface_local_bounds(surface_->GetSize());
124 gfx::Rect close_button_bounds(floating_close_button_->GetPreferredSize()); 256 gfx::Rect close_button_bounds(floating_close_button_->GetPreferredSize());
125 close_button_bounds.set_x(surface_local_bounds.right() - 257 close_button_bounds.set_x(surface_local_bounds.right() -
126 close_button_bounds.width()); 258 close_button_bounds.width());
127 close_button_bounds.set_y(surface_local_bounds.y()); 259 close_button_bounds.set_y(surface_local_bounds.y());
128 floating_close_button_widget_->SetBounds(close_button_bounds); 260 floating_close_button_widget_->SetBounds(close_button_bounds);
261
262 UpdateCloseButtonVisiblity();
263 }
264
265 void ArcCustomNotificationView::OnKeyEvent(ui::KeyEvent* event) {
266 // Forward to parent CustomNotificationView to handle keyboard dismissal.
267 parent()->OnKeyEvent(event);
268 }
269
270 void ArcCustomNotificationView::OnGestureEvent(ui::GestureEvent* event) {
271 // Forward to parent CustomNotificationView to handle sliding out.
272 parent()->OnGestureEvent(event);
273 slide_helper_->Update();
274 }
275
276 void ArcCustomNotificationView::OnMouseEntered(const ui::MouseEvent&) {
277 UpdateCloseButtonVisiblity();
278 }
279
280 void ArcCustomNotificationView::OnMouseExited(const ui::MouseEvent&) {
281 UpdateCloseButtonVisiblity();
129 } 282 }
130 283
131 void ArcCustomNotificationView::ButtonPressed(views::Button* sender, 284 void ArcCustomNotificationView::ButtonPressed(views::Button* sender,
132 const ui::Event& event) { 285 const ui::Event& event) {
133 if (item_ && !item_->pinned() && sender == floating_close_button_) { 286 if (item_ && !item_->pinned() && sender == floating_close_button_) {
134 item_->CloseFromCloseButton(); 287 item_->CloseFromCloseButton();
135 } 288 }
136 } 289 }
137 290
138 void ArcCustomNotificationView::OnWindowBoundsChanged(aura::Window* window, 291 void ArcCustomNotificationView::OnWindowBoundsChanged(
139 const gfx::Rect& old_bounds, 292 aura::Window* window,
140 const gfx::Rect& new_bounds) { 293 const gfx::Rect& old_bounds,
294 const gfx::Rect& new_bounds) {
141 UpdatePreferredSize(); 295 UpdatePreferredSize();
142 } 296 }
143 297
144 void ArcCustomNotificationView::OnWindowDestroying(aura::Window* window) { 298 void ArcCustomNotificationView::OnWindowDestroying(aura::Window* window) {
145 window->RemoveObserver(this); 299 window->RemoveObserver(this);
146 } 300 }
147 301
148 void ArcCustomNotificationView::OnItemDestroying() { 302 void ArcCustomNotificationView::OnItemDestroying() {
149 item_->RemoveObserver(this); 303 item_->RemoveObserver(this);
150 item_ = nullptr; 304 item_ = nullptr;
151 305
152 // Reset |surface_| with |item_| since no one is observing the |surface_| 306 // Reset |surface_| with |item_| since no one is observing the |surface_|
153 // after |item_| is gone and this view should be removed soon. 307 // after |item_| is gone and this view should be removed soon.
154 surface_ = nullptr; 308 SetSurface(nullptr);
155 } 309 }
156 310
157 void ArcCustomNotificationView::OnItemPinnedChanged() { 311 void ArcCustomNotificationView::OnItemPinnedChanged() {
158 if (item_->pinned() && floating_close_button_widget_) { 312 if (item_->pinned() && floating_close_button_widget_) {
159 floating_close_button_widget_.reset(); 313 floating_close_button_widget_.reset();
160 } else if (!item_->pinned() && !floating_close_button_widget_) { 314 } else if (!item_->pinned() && !floating_close_button_widget_) {
161 CreateFloatingCloseButton(); 315 CreateFloatingCloseButton();
162 } 316 }
163 } 317 }
164 318
165 void ArcCustomNotificationView::OnItemNotificationSurfaceRemoved() { 319 void ArcCustomNotificationView::OnItemNotificationSurfaceRemoved() {
166 surface_ = nullptr; 320 SetSurface(nullptr);
167 } 321 }
168 322
169 } // namespace arc 323 } // namespace arc
OLDNEW
« ui/arc/BUILD.gn ('K') | « ui/arc/notification/arc_custom_notification_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698