tray_bubble_wrapper.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/system/tray/tray_bubble_wrapper.h"
  5. #include "ash/app_list/app_list_controller_impl.h"
  6. #include "ash/shell.h"
  7. #include "ash/system/tray/tray_background_view.h"
  8. #include "ash/system/tray/tray_bubble_view.h"
  9. #include "ash/system/tray/tray_event_filter.h"
  10. #include "ui/aura/window.h"
  11. #include "ui/views/widget/widget.h"
  12. #include "ui/wm/core/transient_window_manager.h"
  13. #include "ui/wm/core/window_util.h"
  14. #include "ui/wm/public/activation_client.h"
  15. namespace ash {
  16. TrayBubbleWrapper::TrayBubbleWrapper(TrayBackgroundView* tray,
  17. TrayBubbleView* bubble_view,
  18. bool event_handling)
  19. : tray_(tray), bubble_view_(bubble_view), event_handling_(event_handling) {
  20. bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_);
  21. bubble_widget_->AddObserver(this);
  22. TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_);
  23. bubble_view_->InitializeAndShowBubble();
  24. if (!Shell::Get()->tablet_mode_controller()->InTabletMode())
  25. Shell::Get()->app_list_controller()->DismissAppList();
  26. if (event_handling_) {
  27. tray->tray_event_filter()->AddBubble(this);
  28. Shell::Get()->activation_client()->AddObserver(this);
  29. }
  30. }
  31. TrayBubbleWrapper::~TrayBubbleWrapper() {
  32. if (event_handling_) {
  33. Shell::Get()->activation_client()->RemoveObserver(this);
  34. tray_->tray_event_filter()->RemoveBubble(this);
  35. }
  36. if (bubble_widget_) {
  37. auto* transient_manager = ::wm::TransientWindowManager::GetOrCreate(
  38. bubble_widget_->GetNativeWindow());
  39. if (transient_manager) {
  40. for (auto* window : transient_manager->transient_children())
  41. transient_manager->RemoveTransientChild(window);
  42. }
  43. bubble_widget_->RemoveObserver(this);
  44. bubble_widget_->Close();
  45. }
  46. CHECK(!IsInObserverList());
  47. }
  48. TrayBackgroundView* TrayBubbleWrapper::GetTray() const {
  49. return tray_;
  50. }
  51. TrayBubbleView* TrayBubbleWrapper::GetBubbleView() const {
  52. return bubble_view_;
  53. }
  54. views::Widget* TrayBubbleWrapper::GetBubbleWidget() const {
  55. return bubble_widget_;
  56. }
  57. void TrayBubbleWrapper::OnWidgetDestroying(views::Widget* widget) {
  58. CHECK_EQ(bubble_widget_, widget);
  59. bubble_widget_->RemoveObserver(this);
  60. bubble_widget_ = NULL;
  61. // Although the bubble is already closed, the next mouse release event
  62. // will invoke PerformAction which reopens the bubble again. To prevent the
  63. // reopen, the mouse capture of |tray_| has to be released.
  64. // See crbug.com/177075
  65. tray_->GetWidget()->GetNativeWindow()->ReleaseCapture();
  66. tray_->HideBubbleWithView(bubble_view_); // May destroy |bubble_view_|
  67. }
  68. void TrayBubbleWrapper::OnWidgetBoundsChanged(views::Widget* widget,
  69. const gfx::Rect& new_bounds) {
  70. DCHECK_EQ(bubble_widget_, widget);
  71. tray_->BubbleResized(bubble_view_);
  72. }
  73. void TrayBubbleWrapper::OnWindowActivated(ActivationReason reason,
  74. aura::Window* gained_active,
  75. aura::Window* lost_active) {
  76. if (!gained_active)
  77. return;
  78. // Check for the CloseBubble() lock.
  79. if (!TrayBackgroundView::ShouldCloseBubbleOnWindowActivated())
  80. return;
  81. views::Widget* bubble_widget = bubble_view()->GetWidget();
  82. // Don't close the bubble if a transient child is gaining or losing
  83. // activation.
  84. if (bubble_widget == views::Widget::GetWidgetForNativeView(gained_active) ||
  85. ::wm::HasTransientAncestor(gained_active,
  86. bubble_widget->GetNativeWindow()) ||
  87. (lost_active && ::wm::HasTransientAncestor(
  88. lost_active, bubble_widget->GetNativeWindow()))) {
  89. return;
  90. }
  91. tray_->CloseBubble();
  92. }
  93. } // namespace ash