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

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: for #3 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
« no previous file with comments | « ui/arc/notification/arc_custom_notification_view.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 OnEvent(ui::Event* event) override { owner_->OnEvent(event); }
35
36 ArcCustomNotificationView* const owner_;
37
38 DISALLOW_COPY_AND_ASSIGN(EventForwarder);
39 };
40
41 class ArcCustomNotificationView::SlideHelper
42 : public ui::LayerAnimationObserver {
43 public:
44 explicit SlideHelper(ArcCustomNotificationView* owner) : owner_(owner) {
45 owner_->parent()->layer()->GetAnimator()->AddObserver(this);
46
47 // Reset opacity to 1 to handle to case when the surface is sliding before
48 // getting managed by this class, e.g. sliding in a popup before showing
49 // in a message center view.
50 if (owner_->surface_ && owner_->surface_->window())
51 owner_->surface_->window()->layer()->SetOpacity(1.0f);
52 }
53 ~SlideHelper() override {
54 owner_->parent()->layer()->GetAnimator()->RemoveObserver(this);
55 }
56
57 void Update() {
58 const bool has_animation =
59 owner_->parent()->layer()->GetAnimator()->is_animating();
60 const bool has_transform = !owner_->parent()->GetTransform().IsIdentity();
61 const bool sliding = has_transform || has_animation;
62 if (sliding_ == sliding)
63 return;
64
65 sliding_ = sliding;
66
67 if (sliding_)
68 OnSlideStart();
69 else
70 OnSlideEnd();
71 }
72
73 private:
74 void OnSlideStart() {
75 if (!owner_->surface_ || !owner_->surface_->window())
76 return;
77 surface_copy_ = ::wm::RecreateLayers(owner_->surface_->window(), nullptr);
78 owner_->layer()->Add(surface_copy_->root());
79 owner_->surface_->window()->layer()->SetOpacity(0.0f);
80 }
81
82 void OnSlideEnd() {
83 if (!owner_->surface_ || !owner_->surface_->window())
84 return;
85 owner_->surface_->window()->layer()->SetOpacity(1.0f);
86 owner_->Layout();
87 surface_copy_.reset();
88 }
89
90 // ui::LayerAnimationObserver
91 void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq) override {
92 Update();
93 }
94 void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq) override {
95 Update();
96 }
97 void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {}
98
99 ArcCustomNotificationView* const owner_;
100 bool sliding_ = false;
101 std::unique_ptr<ui::LayerTreeOwner> surface_copy_;
102
103 DISALLOW_COPY_AND_ASSIGN(SlideHelper);
104 };
105
22 ArcCustomNotificationView::ArcCustomNotificationView( 106 ArcCustomNotificationView::ArcCustomNotificationView(
23 ArcCustomNotificationItem* item, 107 ArcCustomNotificationItem* item,
24 exo::NotificationSurface* surface) 108 exo::NotificationSurface* surface)
25 : item_(item), surface_(surface) { 109 : item_(item), event_forwarder_(new EventForwarder(this)) {
110 SetSurface(surface);
26 item_->AddObserver(this); 111 item_->AddObserver(this);
27 OnItemPinnedChanged(); 112 OnItemPinnedChanged();
28 surface_->window()->AddObserver(this); 113
114 // Create a layer as an anchor to insert surface copy during a slide.
115 SetPaintToLayer(true);
29 } 116 }
30 117
31 ArcCustomNotificationView::~ArcCustomNotificationView() { 118 ArcCustomNotificationView::~ArcCustomNotificationView() {
119 SetSurface(nullptr);
32 if (item_) 120 if (item_)
33 item_->RemoveObserver(this); 121 item_->RemoveObserver(this);
34 if (surface_ && surface_->window())
35 surface_->window()->RemoveObserver(this);
36 } 122 }
37 123
38 void ArcCustomNotificationView::CreateFloatingCloseButton() { 124 void ArcCustomNotificationView::CreateFloatingCloseButton() {
39 floating_close_button_ = new views::ImageButton(this); 125 floating_close_button_ = new views::ImageButton(this);
40 floating_close_button_->set_background( 126 floating_close_button_->set_background(
41 views::Background::CreateSolidBackground(SK_ColorTRANSPARENT)); 127 views::Background::CreateSolidBackground(SK_ColorTRANSPARENT));
42 floating_close_button_->SetBorder( 128 floating_close_button_->SetBorder(
43 views::Border::CreateEmptyBorder(5, 5, 5, 5)); 129 views::Border::CreateEmptyBorder(5, 5, 5, 5));
44 130
45 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 131 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
(...skipping 11 matching lines...) Expand all
57 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME)); 143 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
58 144
59 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); 145 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
60 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 146 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
61 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 147 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
62 params.parent = surface_->window(); 148 params.parent = surface_->window();
63 149
64 floating_close_button_widget_.reset(new views::Widget); 150 floating_close_button_widget_.reset(new views::Widget);
65 floating_close_button_widget_->Init(params); 151 floating_close_button_widget_->Init(params);
66 floating_close_button_widget_->SetContentsView(floating_close_button_); 152 floating_close_button_widget_->SetContentsView(floating_close_button_);
67 floating_close_button_widget_->Show();
68 153
69 Layout(); 154 Layout();
70 } 155 }
71 156
157 void ArcCustomNotificationView::SetSurface(exo::NotificationSurface* surface) {
158 if (surface_ == surface)
159 return;
160
161 if (surface_ && surface_->window()) {
162 surface_->window()->RemoveObserver(this);
163 surface_->window()->RemovePreTargetHandler(event_forwarder_.get());
164 }
165
166 surface_ = surface;
167
168 if (surface_ && surface_->window()) {
169 surface_->window()->AddObserver(this);
170 surface_->window()->AddPreTargetHandler(event_forwarder_.get());
171 }
172 }
173
72 void ArcCustomNotificationView::UpdatePreferredSize() { 174 void ArcCustomNotificationView::UpdatePreferredSize() {
73 gfx::Size preferred_size = surface_->GetSize(); 175 gfx::Size preferred_size = surface_->GetSize();
74 if (preferred_size.width() != message_center::kNotificationWidth) { 176 if (preferred_size.width() != message_center::kNotificationWidth) {
75 const float scale = static_cast<float>(message_center::kNotificationWidth) / 177 const float scale = static_cast<float>(message_center::kNotificationWidth) /
76 preferred_size.width(); 178 preferred_size.width();
77 preferred_size.SetSize(message_center::kNotificationWidth, 179 preferred_size.SetSize(message_center::kNotificationWidth,
78 preferred_size.height() * scale); 180 preferred_size.height() * scale);
79 } 181 }
80 182
81 SetPreferredSize(preferred_size); 183 SetPreferredSize(preferred_size);
82 } 184 }
83 185
186 void ArcCustomNotificationView::UpdateCloseButtonVisiblity() {
187 if (!surface_ || !floating_close_button_widget_)
188 return;
189
190 const bool target_visiblity =
191 surface_->window()->GetBoundsInScreen().Contains(
192 display::Screen::GetScreen()->GetCursorScreenPoint());
193 if (target_visiblity == floating_close_button_widget_->IsVisible())
194 return;
195
196 if (target_visiblity)
197 floating_close_button_widget_->Show();
198 else
199 floating_close_button_widget_->Hide();
200 }
201
84 void ArcCustomNotificationView::ViewHierarchyChanged( 202 void ArcCustomNotificationView::ViewHierarchyChanged(
85 const views::View::ViewHierarchyChangedDetails& details) { 203 const views::View::ViewHierarchyChangedDetails& details) {
86 views::Widget* widget = GetWidget(); 204 views::Widget* widget = GetWidget();
87 205
206 if (!details.is_add) {
207 // Resets slide helper when this view is removed from its parent.
208 slide_helper_.reset();
209 }
210
88 // Bail if native_view() has attached to a different widget. 211 // Bail if native_view() has attached to a different widget.
89 if (widget && native_view() && 212 if (widget && native_view() &&
90 views::Widget::GetTopLevelWidgetForNativeView(native_view()) != widget) { 213 views::Widget::GetTopLevelWidgetForNativeView(native_view()) != widget) {
91 return; 214 return;
92 } 215 }
93 216
94 views::NativeViewHost::ViewHierarchyChanged(details); 217 views::NativeViewHost::ViewHierarchyChanged(details);
95 218
96 if (!widget || !surface_ || !details.is_add) 219 if (!widget || !surface_ || !details.is_add)
97 return; 220 return;
98 221
99 UpdatePreferredSize(); 222 UpdatePreferredSize();
100 Attach(surface_->window()); 223 Attach(surface_->window());
224
225 // Creates slide helper after this view is added to its parent.
226 slide_helper_.reset(new SlideHelper(this));
101 } 227 }
102 228
103 void ArcCustomNotificationView::Layout() { 229 void ArcCustomNotificationView::Layout() {
104 views::NativeViewHost::Layout(); 230 views::NativeViewHost::Layout();
105 231
106 if (!surface_ || !GetWidget()) 232 if (!surface_ || !GetWidget())
107 return; 233 return;
108 234
109 // Scale notification surface if necessary. 235 // Scale notification surface if necessary.
110 gfx::Transform transform; 236 gfx::Transform transform;
111 const gfx::Size surface_size = surface_->GetSize(); 237 const gfx::Size surface_size = surface_->GetSize();
112 const gfx::Size contents_size = GetContentsBounds().size(); 238 const gfx::Size contents_size = GetContentsBounds().size();
113 if (!surface_size.IsEmpty() && !contents_size.IsEmpty()) { 239 if (!surface_size.IsEmpty() && !contents_size.IsEmpty()) {
114 transform.Scale( 240 transform.Scale(
115 static_cast<float>(contents_size.width()) / surface_size.width(), 241 static_cast<float>(contents_size.width()) / surface_size.width(),
116 static_cast<float>(contents_size.height()) / surface_size.height()); 242 static_cast<float>(contents_size.height()) / surface_size.height());
117 } 243 }
118 surface_->window()->SetTransform(transform); 244 surface_->window()->SetTransform(transform);
119 245
120 if (!floating_close_button_widget_) 246 if (!floating_close_button_widget_)
121 return; 247 return;
122 248
123 gfx::Rect surface_local_bounds(surface_->GetSize()); 249 gfx::Rect surface_local_bounds(surface_->GetSize());
124 gfx::Rect close_button_bounds(floating_close_button_->GetPreferredSize()); 250 gfx::Rect close_button_bounds(floating_close_button_->GetPreferredSize());
125 close_button_bounds.set_x(surface_local_bounds.right() - 251 close_button_bounds.set_x(surface_local_bounds.right() -
126 close_button_bounds.width()); 252 close_button_bounds.width());
127 close_button_bounds.set_y(surface_local_bounds.y()); 253 close_button_bounds.set_y(surface_local_bounds.y());
128 floating_close_button_widget_->SetBounds(close_button_bounds); 254 floating_close_button_widget_->SetBounds(close_button_bounds);
255
256 UpdateCloseButtonVisiblity();
257 }
258
259 void ArcCustomNotificationView::OnKeyEvent(ui::KeyEvent* event) {
260 // Forward to parent CustomNotificationView to handle keyboard dismissal.
261 parent()->OnKeyEvent(event);
262 }
263
264 void ArcCustomNotificationView::OnGestureEvent(ui::GestureEvent* event) {
265 // Forward to parent CustomNotificationView to handle sliding out.
266 parent()->OnGestureEvent(event);
267 slide_helper_->Update();
268 }
269
270 void ArcCustomNotificationView::OnMouseEntered(const ui::MouseEvent&) {
271 UpdateCloseButtonVisiblity();
272 }
273
274 void ArcCustomNotificationView::OnMouseExited(const ui::MouseEvent&) {
275 UpdateCloseButtonVisiblity();
129 } 276 }
130 277
131 void ArcCustomNotificationView::ButtonPressed(views::Button* sender, 278 void ArcCustomNotificationView::ButtonPressed(views::Button* sender,
132 const ui::Event& event) { 279 const ui::Event& event) {
133 if (item_ && !item_->pinned() && sender == floating_close_button_) { 280 if (item_ && !item_->pinned() && sender == floating_close_button_) {
134 item_->CloseFromCloseButton(); 281 item_->CloseFromCloseButton();
135 } 282 }
136 } 283 }
137 284
138 void ArcCustomNotificationView::OnWindowBoundsChanged(aura::Window* window, 285 void ArcCustomNotificationView::OnWindowBoundsChanged(
139 const gfx::Rect& old_bounds, 286 aura::Window* window,
140 const gfx::Rect& new_bounds) { 287 const gfx::Rect& old_bounds,
288 const gfx::Rect& new_bounds) {
141 UpdatePreferredSize(); 289 UpdatePreferredSize();
142 } 290 }
143 291
144 void ArcCustomNotificationView::OnWindowDestroying(aura::Window* window) { 292 void ArcCustomNotificationView::OnWindowDestroying(aura::Window* window) {
145 window->RemoveObserver(this); 293 window->RemoveObserver(this);
146 } 294 }
147 295
148 void ArcCustomNotificationView::OnItemDestroying() { 296 void ArcCustomNotificationView::OnItemDestroying() {
149 item_->RemoveObserver(this); 297 item_->RemoveObserver(this);
150 item_ = nullptr; 298 item_ = nullptr;
151 299
152 // Reset |surface_| with |item_| since no one is observing the |surface_| 300 // Reset |surface_| with |item_| since no one is observing the |surface_|
153 // after |item_| is gone and this view should be removed soon. 301 // after |item_| is gone and this view should be removed soon.
154 surface_ = nullptr; 302 SetSurface(nullptr);
155 } 303 }
156 304
157 void ArcCustomNotificationView::OnItemPinnedChanged() { 305 void ArcCustomNotificationView::OnItemPinnedChanged() {
158 if (item_->pinned() && floating_close_button_widget_) { 306 if (item_->pinned() && floating_close_button_widget_) {
159 floating_close_button_widget_.reset(); 307 floating_close_button_widget_.reset();
160 } else if (!item_->pinned() && !floating_close_button_widget_) { 308 } else if (!item_->pinned() && !floating_close_button_widget_) {
161 CreateFloatingCloseButton(); 309 CreateFloatingCloseButton();
162 } 310 }
163 } 311 }
164 312
165 void ArcCustomNotificationView::OnItemNotificationSurfaceRemoved() { 313 void ArcCustomNotificationView::OnItemNotificationSurfaceRemoved() {
166 surface_ = nullptr; 314 SetSurface(nullptr);
167 } 315 }
168 316
169 } // namespace arc 317 } // namespace arc
OLDNEW
« no previous file with comments | « 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