| OLD | NEW |
| 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" | 12 #include "ui/compositor/layer_animation_observer.h" |
| 13 #include "ui/display/screen.h" | 13 #include "ui/display/screen.h" |
| 14 #include "ui/events/event_handler.h" | 14 #include "ui/events/event_handler.h" |
| 15 #include "ui/gfx/canvas.h" |
| 16 #include "ui/gfx/image/image_skia.h" |
| 15 #include "ui/gfx/transform.h" | 17 #include "ui/gfx/transform.h" |
| 16 #include "ui/message_center/message_center_style.h" | 18 #include "ui/message_center/message_center_style.h" |
| 17 #include "ui/resources/grit/ui_resources.h" | 19 #include "ui/resources/grit/ui_resources.h" |
| 18 #include "ui/strings/grit/ui_strings.h" | 20 #include "ui/strings/grit/ui_strings.h" |
| 19 #include "ui/views/background.h" | 21 #include "ui/views/background.h" |
| 20 #include "ui/views/border.h" | 22 #include "ui/views/border.h" |
| 21 #include "ui/views/controls/button/image_button.h" | 23 #include "ui/views/controls/button/image_button.h" |
| 22 #include "ui/views/widget/widget.h" | 24 #include "ui/views/widget/widget.h" |
| 23 #include "ui/wm/core/window_util.h" | 25 #include "ui/wm/core/window_util.h" |
| 24 | 26 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {} | 109 void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {} |
| 108 | 110 |
| 109 ArcCustomNotificationView* const owner_; | 111 ArcCustomNotificationView* const owner_; |
| 110 bool sliding_ = false; | 112 bool sliding_ = false; |
| 111 std::unique_ptr<ui::LayerTreeOwner> surface_copy_; | 113 std::unique_ptr<ui::LayerTreeOwner> surface_copy_; |
| 112 | 114 |
| 113 DISALLOW_COPY_AND_ASSIGN(SlideHelper); | 115 DISALLOW_COPY_AND_ASSIGN(SlideHelper); |
| 114 }; | 116 }; |
| 115 | 117 |
| 116 ArcCustomNotificationView::ArcCustomNotificationView( | 118 ArcCustomNotificationView::ArcCustomNotificationView( |
| 117 ArcCustomNotificationItem* item, | 119 ArcCustomNotificationItem* item) |
| 118 exo::NotificationSurface* surface) | 120 : item_(item), |
| 119 : item_(item), event_forwarder_(new EventForwarder(this)) { | 121 notification_key_(item->notification_key()), |
| 120 SetSurface(surface); | 122 event_forwarder_(new EventForwarder(this)) { |
| 123 item_->IncrementWindowRefCount(); |
| 121 item_->AddObserver(this); | 124 item_->AddObserver(this); |
| 122 OnItemPinnedChanged(); | 125 |
| 126 ArcNotificationSurfaceManager::Get()->AddObserver(this); |
| 127 exo::NotificationSurface* surface = |
| 128 ArcNotificationSurfaceManager::Get()->GetSurface(notification_key_); |
| 129 if (surface) |
| 130 OnNotificationSurfaceAdded(surface); |
| 123 | 131 |
| 124 // Create a layer as an anchor to insert surface copy during a slide. | 132 // Create a layer as an anchor to insert surface copy during a slide. |
| 125 SetPaintToLayer(true); | 133 SetPaintToLayer(true); |
| 134 UpdatePreferredSize(); |
| 126 } | 135 } |
| 127 | 136 |
| 128 ArcCustomNotificationView::~ArcCustomNotificationView() { | 137 ArcCustomNotificationView::~ArcCustomNotificationView() { |
| 129 SetSurface(nullptr); | 138 SetSurface(nullptr); |
| 130 if (item_) | 139 if (item_) { |
| 140 item_->DecrementWindowRefCount(); |
| 131 item_->RemoveObserver(this); | 141 item_->RemoveObserver(this); |
| 142 } |
| 143 |
| 144 if (ArcNotificationSurfaceManager::Get()) |
| 145 ArcNotificationSurfaceManager::Get()->RemoveObserver(this); |
| 132 } | 146 } |
| 133 | 147 |
| 134 void ArcCustomNotificationView::CreateFloatingCloseButton() { | 148 void ArcCustomNotificationView::CreateFloatingCloseButton() { |
| 149 if (!surface_) |
| 150 return; |
| 151 |
| 135 floating_close_button_ = new views::ImageButton(this); | 152 floating_close_button_ = new views::ImageButton(this); |
| 136 floating_close_button_->set_background( | 153 floating_close_button_->set_background( |
| 137 views::Background::CreateSolidBackground(SK_ColorTRANSPARENT)); | 154 views::Background::CreateSolidBackground(SK_ColorTRANSPARENT)); |
| 138 | 155 |
| 139 // The sizes below are in DIPs. | 156 // The sizes below are in DIPs. |
| 140 constexpr int kPaddingFromBorder = 4; | 157 constexpr int kPaddingFromBorder = 4; |
| 141 constexpr int kImageSize = 16; | 158 constexpr int kImageSize = 16; |
| 142 constexpr int kTouchExtendedPadding = | 159 constexpr int kTouchExtendedPadding = |
| 143 message_center::kControlButtonSize - kImageSize - kPaddingFromBorder; | 160 message_center::kControlButtonSize - kImageSize - kPaddingFromBorder; |
| 144 floating_close_button_->SetBorder(views::Border::CreateEmptyBorder( | 161 floating_close_button_->SetBorder(views::Border::CreateEmptyBorder( |
| (...skipping 27 matching lines...) Expand all Loading... |
| 172 if (surface_ && surface_->window()) { | 189 if (surface_ && surface_->window()) { |
| 173 surface_->window()->RemoveObserver(this); | 190 surface_->window()->RemoveObserver(this); |
| 174 surface_->window()->RemovePreTargetHandler(event_forwarder_.get()); | 191 surface_->window()->RemovePreTargetHandler(event_forwarder_.get()); |
| 175 } | 192 } |
| 176 | 193 |
| 177 surface_ = surface; | 194 surface_ = surface; |
| 178 | 195 |
| 179 if (surface_ && surface_->window()) { | 196 if (surface_ && surface_->window()) { |
| 180 surface_->window()->AddObserver(this); | 197 surface_->window()->AddObserver(this); |
| 181 surface_->window()->AddPreTargetHandler(event_forwarder_.get()); | 198 surface_->window()->AddPreTargetHandler(event_forwarder_.get()); |
| 199 |
| 200 if (GetWidget()) |
| 201 AttachSurface(); |
| 202 |
| 203 UpdatePinnedState(); |
| 182 } | 204 } |
| 183 } | 205 } |
| 184 | 206 |
| 185 void ArcCustomNotificationView::UpdatePreferredSize() { | 207 void ArcCustomNotificationView::UpdatePreferredSize() { |
| 186 gfx::Size preferred_size = surface_->GetSize(); | 208 gfx::Size preferred_size = |
| 209 surface_ ? surface_->GetSize() : item_ ? item_->snapshot().size() |
| 210 : gfx::Size(); |
| 211 if (preferred_size.IsEmpty()) |
| 212 return; |
| 213 |
| 187 if (preferred_size.width() != message_center::kNotificationWidth) { | 214 if (preferred_size.width() != message_center::kNotificationWidth) { |
| 188 const float scale = static_cast<float>(message_center::kNotificationWidth) / | 215 const float scale = static_cast<float>(message_center::kNotificationWidth) / |
| 189 preferred_size.width(); | 216 preferred_size.width(); |
| 190 preferred_size.SetSize(message_center::kNotificationWidth, | 217 preferred_size.SetSize(message_center::kNotificationWidth, |
| 191 preferred_size.height() * scale); | 218 preferred_size.height() * scale); |
| 192 } | 219 } |
| 193 | 220 |
| 194 SetPreferredSize(preferred_size); | 221 SetPreferredSize(preferred_size); |
| 195 } | 222 } |
| 196 | 223 |
| 197 void ArcCustomNotificationView::UpdateCloseButtonVisiblity() { | 224 void ArcCustomNotificationView::UpdateCloseButtonVisiblity() { |
| 198 if (!surface_ || !floating_close_button_widget_) | 225 if (!surface_ || !floating_close_button_widget_) |
| 199 return; | 226 return; |
| 200 | 227 |
| 201 const bool target_visiblity = | 228 const bool target_visiblity = |
| 202 surface_->window()->GetBoundsInScreen().Contains( | 229 surface_->window()->GetBoundsInScreen().Contains( |
| 203 display::Screen::GetScreen()->GetCursorScreenPoint()); | 230 display::Screen::GetScreen()->GetCursorScreenPoint()); |
| 204 if (target_visiblity == floating_close_button_widget_->IsVisible()) | 231 if (target_visiblity == floating_close_button_widget_->IsVisible()) |
| 205 return; | 232 return; |
| 206 | 233 |
| 207 if (target_visiblity) | 234 if (target_visiblity) |
| 208 floating_close_button_widget_->Show(); | 235 floating_close_button_widget_->Show(); |
| 209 else | 236 else |
| 210 floating_close_button_widget_->Hide(); | 237 floating_close_button_widget_->Hide(); |
| 211 } | 238 } |
| 212 | 239 |
| 240 void ArcCustomNotificationView::UpdatePinnedState() { |
| 241 if (item_->pinned() && floating_close_button_widget_) { |
| 242 floating_close_button_widget_.reset(); |
| 243 } else if (!item_->pinned() && !floating_close_button_widget_) { |
| 244 CreateFloatingCloseButton(); |
| 245 } |
| 246 } |
| 247 |
| 248 void ArcCustomNotificationView::UpdateSnapshot() { |
| 249 // Bail if we have a |surface_| because it controls the sizes and paints UI. |
| 250 if (surface_) |
| 251 return; |
| 252 |
| 253 UpdatePreferredSize(); |
| 254 SchedulePaint(); |
| 255 } |
| 256 |
| 257 void ArcCustomNotificationView::AttachSurface() { |
| 258 if (!GetWidget()) |
| 259 return; |
| 260 |
| 261 UpdatePreferredSize(); |
| 262 Attach(surface_->window()); |
| 263 |
| 264 // Creates slide helper after this view is added to its parent. |
| 265 slide_helper_.reset(new SlideHelper(this)); |
| 266 } |
| 267 |
| 213 void ArcCustomNotificationView::ViewHierarchyChanged( | 268 void ArcCustomNotificationView::ViewHierarchyChanged( |
| 214 const views::View::ViewHierarchyChangedDetails& details) { | 269 const views::View::ViewHierarchyChangedDetails& details) { |
| 215 views::Widget* widget = GetWidget(); | 270 views::Widget* widget = GetWidget(); |
| 216 | 271 |
| 217 if (!details.is_add) { | 272 if (!details.is_add) { |
| 218 // Resets slide helper when this view is removed from its parent. | 273 // Resets slide helper when this view is removed from its parent. |
| 219 slide_helper_.reset(); | 274 slide_helper_.reset(); |
| 220 } | 275 } |
| 221 | 276 |
| 222 // Bail if native_view() has attached to a different widget. | 277 // Bail if native_view() has attached to a different widget. |
| 223 if (widget && native_view() && | 278 if (widget && native_view() && |
| 224 views::Widget::GetTopLevelWidgetForNativeView(native_view()) != widget) { | 279 views::Widget::GetTopLevelWidgetForNativeView(native_view()) != widget) { |
| 225 return; | 280 return; |
| 226 } | 281 } |
| 227 | 282 |
| 228 views::NativeViewHost::ViewHierarchyChanged(details); | 283 views::NativeViewHost::ViewHierarchyChanged(details); |
| 229 | 284 |
| 230 if (!widget || !surface_ || !details.is_add) | 285 if (!widget || !surface_ || !details.is_add) |
| 231 return; | 286 return; |
| 232 | 287 |
| 233 UpdatePreferredSize(); | 288 AttachSurface(); |
| 234 Attach(surface_->window()); | |
| 235 | |
| 236 // Creates slide helper after this view is added to its parent. | |
| 237 slide_helper_.reset(new SlideHelper(this)); | |
| 238 } | 289 } |
| 239 | 290 |
| 240 void ArcCustomNotificationView::Layout() { | 291 void ArcCustomNotificationView::Layout() { |
| 241 views::NativeViewHost::Layout(); | 292 views::NativeViewHost::Layout(); |
| 242 | 293 |
| 243 if (!surface_ || !GetWidget()) | 294 if (!surface_ || !GetWidget()) |
| 244 return; | 295 return; |
| 245 | 296 |
| 246 // Scale notification surface if necessary. | 297 // Scale notification surface if necessary. |
| 247 gfx::Transform transform; | 298 gfx::Transform transform; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 260 gfx::Rect surface_local_bounds(surface_->GetSize()); | 311 gfx::Rect surface_local_bounds(surface_->GetSize()); |
| 261 gfx::Rect close_button_bounds(floating_close_button_->GetPreferredSize()); | 312 gfx::Rect close_button_bounds(floating_close_button_->GetPreferredSize()); |
| 262 close_button_bounds.set_x(surface_local_bounds.right() - | 313 close_button_bounds.set_x(surface_local_bounds.right() - |
| 263 close_button_bounds.width()); | 314 close_button_bounds.width()); |
| 264 close_button_bounds.set_y(surface_local_bounds.y()); | 315 close_button_bounds.set_y(surface_local_bounds.y()); |
| 265 floating_close_button_widget_->SetBounds(close_button_bounds); | 316 floating_close_button_widget_->SetBounds(close_button_bounds); |
| 266 | 317 |
| 267 UpdateCloseButtonVisiblity(); | 318 UpdateCloseButtonVisiblity(); |
| 268 } | 319 } |
| 269 | 320 |
| 321 void ArcCustomNotificationView::OnPaint(gfx::Canvas* canvas) { |
| 322 views::NativeViewHost::OnPaint(canvas); |
| 323 |
| 324 // Bail if there is a |surface_| or no item or no snapshot image. |
| 325 if (surface_ || !item_ || item_->snapshot().isNull()) |
| 326 return; |
| 327 const gfx::Rect contents_bounds = GetContentsBounds(); |
| 328 canvas->DrawImageInt(item_->snapshot(), 0, 0, item_->snapshot().width(), |
| 329 item_->snapshot().height(), contents_bounds.x(), |
| 330 contents_bounds.y(), contents_bounds.width(), |
| 331 contents_bounds.height(), false); |
| 332 } |
| 333 |
| 270 void ArcCustomNotificationView::OnKeyEvent(ui::KeyEvent* event) { | 334 void ArcCustomNotificationView::OnKeyEvent(ui::KeyEvent* event) { |
| 271 // Forward to parent CustomNotificationView to handle keyboard dismissal. | 335 // Forward to parent CustomNotificationView to handle keyboard dismissal. |
| 272 parent()->OnKeyEvent(event); | 336 parent()->OnKeyEvent(event); |
| 273 } | 337 } |
| 274 | 338 |
| 275 void ArcCustomNotificationView::OnGestureEvent(ui::GestureEvent* event) { | 339 void ArcCustomNotificationView::OnGestureEvent(ui::GestureEvent* event) { |
| 276 // Forward to parent CustomNotificationView to handle sliding out. | 340 // Forward to parent CustomNotificationView to handle sliding out. |
| 277 parent()->OnGestureEvent(event); | 341 parent()->OnGestureEvent(event); |
| 278 slide_helper_->Update(); | 342 slide_helper_->Update(); |
| 279 } | 343 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 294 } | 358 } |
| 295 | 359 |
| 296 void ArcCustomNotificationView::OnWindowBoundsChanged( | 360 void ArcCustomNotificationView::OnWindowBoundsChanged( |
| 297 aura::Window* window, | 361 aura::Window* window, |
| 298 const gfx::Rect& old_bounds, | 362 const gfx::Rect& old_bounds, |
| 299 const gfx::Rect& new_bounds) { | 363 const gfx::Rect& new_bounds) { |
| 300 UpdatePreferredSize(); | 364 UpdatePreferredSize(); |
| 301 } | 365 } |
| 302 | 366 |
| 303 void ArcCustomNotificationView::OnWindowDestroying(aura::Window* window) { | 367 void ArcCustomNotificationView::OnWindowDestroying(aura::Window* window) { |
| 304 window->RemoveObserver(this); | 368 SetSurface(nullptr); |
| 305 } | 369 } |
| 306 | 370 |
| 307 void ArcCustomNotificationView::OnItemDestroying() { | 371 void ArcCustomNotificationView::OnItemDestroying() { |
| 308 item_->RemoveObserver(this); | 372 item_->RemoveObserver(this); |
| 309 item_ = nullptr; | 373 item_ = nullptr; |
| 310 | 374 |
| 311 // Reset |surface_| with |item_| since no one is observing the |surface_| | 375 // Reset |surface_| with |item_| since no one is observing the |surface_| |
| 312 // after |item_| is gone and this view should be removed soon. | 376 // after |item_| is gone and this view should be removed soon. |
| 313 SetSurface(nullptr); | 377 SetSurface(nullptr); |
| 314 } | 378 } |
| 315 | 379 |
| 316 void ArcCustomNotificationView::OnItemPinnedChanged() { | 380 void ArcCustomNotificationView::OnItemUpdated() { |
| 317 if (item_->pinned() && floating_close_button_widget_) { | 381 UpdatePinnedState(); |
| 318 floating_close_button_widget_.reset(); | 382 UpdateSnapshot(); |
| 319 } else if (!item_->pinned() && !floating_close_button_widget_) { | |
| 320 CreateFloatingCloseButton(); | |
| 321 } | |
| 322 } | 383 } |
| 323 | 384 |
| 324 void ArcCustomNotificationView::OnItemNotificationSurfaceRemoved() { | 385 void ArcCustomNotificationView::OnNotificationSurfaceAdded( |
| 386 exo::NotificationSurface* surface) { |
| 387 if (surface->notification_id() != notification_key_) |
| 388 return; |
| 389 |
| 390 SetSurface(surface); |
| 391 } |
| 392 |
| 393 void ArcCustomNotificationView::OnNotificationSurfaceRemoved( |
| 394 exo::NotificationSurface* surface) { |
| 395 if (surface->notification_id() != notification_key_) |
| 396 return; |
| 397 |
| 325 SetSurface(nullptr); | 398 SetSurface(nullptr); |
| 326 } | 399 } |
| 327 | 400 |
| 328 } // namespace arc | 401 } // namespace arc |
| OLD | NEW |