Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "ash/shelf/shelf_tooltip_manager.h" | 5 #include "ash/shelf/shelf_tooltip_manager.h" |
| 6 | 6 |
| 7 #include "ash/shelf/shelf.h" | 7 #include "ash/shelf/shelf.h" |
| 8 #include "ash/shelf/shelf_layout_manager.h" | 8 #include "ash/shelf/shelf_layout_manager.h" |
| 9 #include "ash/shelf/shelf_view.h" | 9 #include "ash/shelf/shelf_view.h" |
| 10 #include "ash/shell.h" | 10 #include "ash/shell.h" |
| 11 #include "ash/shell_window_ids.h" | 11 #include "ash/shell_window_ids.h" |
| 12 #include "ash/wm/window_animations.h" | 12 #include "ash/wm/window_animations.h" |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
| 15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 16 #include "base/timer/timer.h" | |
| 17 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
| 18 #include "ui/aura/window_event_dispatcher.h" | |
| 19 #include "ui/events/event.h" | 17 #include "ui/events/event.h" |
| 20 #include "ui/events/event_constants.h" | 18 #include "ui/events/event_constants.h" |
| 21 #include "ui/gfx/geometry/insets.h" | 19 #include "ui/gfx/geometry/insets.h" |
| 22 #include "ui/views/bubble/bubble_delegate.h" | 20 #include "ui/views/bubble/bubble_delegate.h" |
| 23 #include "ui/views/bubble/bubble_frame_view.h" | |
| 24 #include "ui/views/controls/label.h" | 21 #include "ui/views/controls/label.h" |
| 25 #include "ui/views/layout/fill_layout.h" | 22 #include "ui/views/layout/fill_layout.h" |
| 26 #include "ui/views/widget/widget.h" | 23 #include "ui/views/widget/widget.h" |
| 27 | 24 |
| 28 namespace ash { | 25 namespace ash { |
| 29 namespace { | 26 namespace { |
| 30 const int kTooltipTopBottomMargin = 3; | 27 const int kTooltipTopBottomMargin = 3; |
| 31 const int kTooltipLeftRightMargin = 10; | 28 const int kTooltipLeftRightMargin = 10; |
| 32 const int kTooltipAppearanceDelay = 1000; // msec | 29 const int kTooltipAppearanceDelay = 1000; // msec |
| 33 const int kTooltipMinHeight = 29 - 2 * kTooltipTopBottomMargin; | 30 const int kTooltipMinHeight = 29 - 2 * kTooltipTopBottomMargin; |
| 34 const SkColor kTooltipTextColor = SkColorSetRGB(0x22, 0x22, 0x22); | 31 const SkColor kTooltipTextColor = SkColorSetRGB(0x22, 0x22, 0x22); |
| 35 | 32 |
| 36 // The maximum width of the tooltip bubble. Borrowed the value from | 33 // The maximum width of the tooltip bubble. Borrowed the value from |
| 37 // ash/tooltip/tooltip_controller.cc | 34 // ash/tooltip/tooltip_controller.cc |
| 38 const int kTooltipMaxWidth = 250; | 35 const int kTooltipMaxWidth = 250; |
| 39 | 36 |
| 40 // The offset for the tooltip bubble - making sure that the bubble is flush | 37 // The offset for the tooltip bubble - making sure that the bubble is flush |
| 41 // with the shelf. The offset includes the arrow size in pixels as well as | 38 // with the shelf. The offset includes the arrow size in pixels as well as |
| 42 // the activation bar and other spacing elements. | 39 // the activation bar and other spacing elements. |
| 43 const int kArrowOffsetLeftRight = 11; | 40 const int kArrowOffsetLeftRight = 11; |
| 44 const int kArrowOffsetTopBottom = 7; | 41 const int kArrowOffsetTopBottom = 7; |
| 45 | 42 |
| 46 } // namespace | 43 } // namespace |
| 47 | 44 |
| 48 // The implementation of tooltip of the launcher. | 45 // The implementation of tooltip of the launcher. |
| 49 class ShelfTooltipManager::ShelfTooltipBubble | 46 class ShelfTooltipManager::ShelfTooltipBubble |
| 50 : public views::BubbleDelegateView { | 47 : public views::BubbleDelegateView { |
| 51 public: | 48 public: |
| 52 ShelfTooltipBubble(views::View* anchor, | 49 ShelfTooltipBubble(views::View* anchor, |
| 53 views::BubbleBorder::Arrow arrow, | 50 views::BubbleBorder::Arrow arrow, |
| 54 ShelfTooltipManager* host); | 51 const base::string16& text); |
| 55 | |
| 56 void SetText(const base::string16& text); | |
| 57 void Close(); | |
| 58 | 52 |
| 59 private: | 53 private: |
| 60 // views::WidgetDelegate overrides: | |
| 61 void WindowClosing() override; | |
| 62 | |
| 63 // views::View overrides: | 54 // views::View overrides: |
| 64 gfx::Size GetPreferredSize() const override; | 55 gfx::Size GetPreferredSize() const override; |
| 65 | 56 |
| 66 ShelfTooltipManager* host_; | |
| 67 views::Label* label_; | |
| 68 | |
| 69 DISALLOW_COPY_AND_ASSIGN(ShelfTooltipBubble); | 57 DISALLOW_COPY_AND_ASSIGN(ShelfTooltipBubble); |
| 70 }; | 58 }; |
| 71 | 59 |
| 72 ShelfTooltipManager::ShelfTooltipBubble::ShelfTooltipBubble( | 60 ShelfTooltipManager::ShelfTooltipBubble::ShelfTooltipBubble( |
| 73 views::View* anchor, | 61 views::View* anchor, |
| 74 views::BubbleBorder::Arrow arrow, | 62 views::BubbleBorder::Arrow arrow, |
| 75 ShelfTooltipManager* host) | 63 const base::string16& text) |
| 76 : views::BubbleDelegateView(anchor, arrow), host_(host) { | 64 : views::BubbleDelegateView(anchor, arrow) { |
| 77 gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom, | 65 gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom, |
| 78 kArrowOffsetLeftRight, | |
| 79 kArrowOffsetTopBottom, | |
| 80 kArrowOffsetLeftRight); | 66 kArrowOffsetLeftRight); |
| 81 // Shelf items can have an asymmetrical border for spacing reasons. | 67 // Adjust the anchor location for asymmetrical borders of shelf item. |
| 82 // Adjust anchor location for this. | |
| 83 if (anchor->border()) | 68 if (anchor->border()) |
| 84 insets += anchor->border()->GetInsets(); | 69 insets += anchor->border()->GetInsets(); |
| 85 | 70 |
| 86 set_anchor_view_insets(insets); | 71 set_anchor_view_insets(insets); |
| 87 set_close_on_esc(false); | 72 set_close_on_esc(false); |
| 88 set_close_on_deactivate(false); | 73 set_close_on_deactivate(false); |
| 89 set_can_activate(false); | 74 set_can_activate(false); |
| 90 set_accept_events(false); | 75 set_accept_events(false); |
| 91 set_margins(gfx::Insets(kTooltipTopBottomMargin, kTooltipLeftRightMargin, | 76 set_margins(gfx::Insets(kTooltipTopBottomMargin, kTooltipLeftRightMargin)); |
| 92 kTooltipTopBottomMargin, kTooltipLeftRightMargin)); | |
| 93 set_shadow(views::BubbleBorder::SMALL_SHADOW); | 77 set_shadow(views::BubbleBorder::SMALL_SHADOW); |
| 94 SetLayoutManager(new views::FillLayout()); | 78 SetLayoutManager(new views::FillLayout()); |
| 95 // The anchor may not have the widget in tests. | 79 // The anchor may not have the widget in tests. |
| 96 if (anchor->GetWidget() && anchor->GetWidget()->GetNativeView()) { | 80 if (anchor->GetWidget() && anchor->GetWidget()->GetNativeWindow()) { |
| 97 aura::Window* root_window = | 81 set_parent_window(ash::Shell::GetContainer( |
| 98 anchor->GetWidget()->GetNativeView()->GetRootWindow(); | 82 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), |
| 99 set_parent_window(ash::Shell::GetInstance()->GetContainer( | 83 ash::kShellWindowId_SettingBubbleContainer)); |
| 100 root_window, ash::kShellWindowId_SettingBubbleContainer)); | |
| 101 } | 84 } |
| 102 label_ = new views::Label; | 85 views::Label* label = new views::Label(text); |
| 103 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 86 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 104 label_->SetEnabledColor(kTooltipTextColor); | 87 label->SetEnabledColor(kTooltipTextColor); |
| 105 AddChildView(label_); | 88 AddChildView(label); |
| 106 views::BubbleDelegateView::CreateBubble(this); | 89 views::BubbleDelegateView::CreateBubble(this); |
| 107 } | |
| 108 | |
| 109 void ShelfTooltipManager::ShelfTooltipBubble::SetText( | |
| 110 const base::string16& text) { | |
| 111 label_->SetText(text); | |
| 112 SizeToContents(); | 90 SizeToContents(); |
| 113 } | 91 } |
| 114 | 92 |
| 115 void ShelfTooltipManager::ShelfTooltipBubble::Close() { | 93 gfx::Size ShelfTooltipManager::ShelfTooltipBubble::GetPreferredSize() const { |
| 116 if (GetWidget()) { | 94 const gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); |
| 117 host_ = NULL; | 95 return gfx::Size(std::min(size.width(), kTooltipMaxWidth), |
| 118 GetWidget()->Close(); | 96 std::max(size.height(), kTooltipMinHeight)); |
| 119 } | |
| 120 } | 97 } |
| 121 | 98 |
| 122 void ShelfTooltipManager::ShelfTooltipBubble::WindowClosing() { | 99 ShelfTooltipManager::ShelfTooltipManager(ShelfView* shelf_view) |
| 123 views::BubbleDelegateView::WindowClosing(); | 100 : timer_delay_(kTooltipAppearanceDelay), |
| 124 if (host_) | 101 shelf_view_(shelf_view), |
| 125 host_->OnBubbleClosed(this); | 102 shelf_layout_manager_(nullptr), |
| 103 bubble_(nullptr), | |
| 104 weak_factory_(this) {} | |
| 105 | |
| 106 ShelfTooltipManager::~ShelfTooltipManager() {} | |
| 107 | |
| 108 void ShelfTooltipManager::Init() { | |
| 109 shelf_layout_manager_ = shelf_view_->shelf()->shelf_layout_manager(); | |
| 110 shelf_layout_manager_->AddObserver(this); | |
| 111 // TODO(msw): Capture events outside the shelf to close tooltips? | |
| 112 shelf_view_->GetWidget()->GetNativeWindow()->AddPreTargetHandler(this); | |
| 126 } | 113 } |
| 127 | 114 |
| 128 gfx::Size ShelfTooltipManager::ShelfTooltipBubble::GetPreferredSize() const { | 115 void ShelfTooltipManager::Close() { |
| 129 gfx::Size pref_size = views::BubbleDelegateView::GetPreferredSize(); | 116 timer_.Stop(); |
| 130 if (pref_size.height() < kTooltipMinHeight) | 117 if (bubble_) |
| 131 pref_size.set_height(kTooltipMinHeight); | 118 bubble_->GetWidget()->Close(); |
| 132 if (pref_size.width() > kTooltipMaxWidth) | 119 bubble_ = nullptr; |
| 133 pref_size.set_width(kTooltipMaxWidth); | |
| 134 return pref_size; | |
| 135 } | 120 } |
| 136 | 121 |
| 137 ShelfTooltipManager::ShelfTooltipManager( | 122 bool ShelfTooltipManager::IsVisible() const { |
| 138 ShelfLayoutManager* shelf_layout_manager, | 123 return bubble_ && bubble_->GetWidget()->IsVisible(); |
| 139 ShelfView* shelf_view) | |
| 140 : view_(NULL), | |
| 141 widget_(NULL), | |
| 142 anchor_(NULL), | |
| 143 shelf_layout_manager_(shelf_layout_manager), | |
| 144 shelf_view_(shelf_view), | |
| 145 weak_factory_(this) { | |
| 146 if (shelf_layout_manager) | |
| 147 shelf_layout_manager->AddObserver(this); | |
| 148 if (Shell::HasInstance()) | |
| 149 Shell::GetInstance()->AddPreTargetHandler(this); | |
| 150 } | 124 } |
| 151 | 125 |
| 152 ShelfTooltipManager::~ShelfTooltipManager() { | 126 views::View* ShelfTooltipManager::GetCurrentAnchorView() const { |
| 153 CancelHidingAnimation(); | 127 return bubble_ ? bubble_->GetAnchorView() : nullptr; |
| 154 Close(); | |
| 155 if (shelf_layout_manager_) | |
| 156 shelf_layout_manager_->RemoveObserver(this); | |
| 157 if (Shell::HasInstance()) | |
| 158 Shell::GetInstance()->RemovePreTargetHandler(this); | |
| 159 } | 128 } |
| 160 | 129 |
| 161 void ShelfTooltipManager::ShowDelayed(views::View* anchor, | 130 void ShelfTooltipManager::ShowTooltip(views::View* view) { |
| 162 const base::string16& text) { | 131 timer_.Stop(); |
| 163 if (view_) { | 132 if (bubble_) { |
| 164 if (timer_.get() && timer_->IsRunning()) { | 133 // Cancel the hiding animation to hide the old bubble immediately. |
| 165 return; | 134 gfx::NativeView native_view = bubble_->GetWidget()->GetNativeView(); |
| 166 } else { | 135 wm::SetWindowVisibilityAnimationTransition(native_view, wm::ANIMATE_NONE); |
| 167 CancelHidingAnimation(); | |
| 168 Close(); | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible()) | |
| 173 return; | |
| 174 | |
| 175 CreateBubble(anchor, text); | |
| 176 ResetTimer(); | |
| 177 } | |
| 178 | |
| 179 void ShelfTooltipManager::ShowImmediately(views::View* anchor, | |
| 180 const base::string16& text) { | |
| 181 if (view_) { | |
| 182 if (timer_.get() && timer_->IsRunning()) | |
| 183 StopTimer(); | |
| 184 CancelHidingAnimation(); | |
| 185 Close(); | 136 Close(); |
| 186 } | 137 } |
| 187 | 138 |
| 188 if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible()) | 139 if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible()) |
| 189 return; | 140 return; |
| 190 | 141 |
| 191 CreateBubble(anchor, text); | 142 Shelf* shelf = shelf_view_->shelf(); |
| 192 ShowInternal(); | 143 views::BubbleBorder::Arrow arrow = shelf->SelectValueForShelfAlignment( |
| 144 views::BubbleBorder::BOTTOM_CENTER, views::BubbleBorder::LEFT_CENTER, | |
| 145 views::BubbleBorder::RIGHT_CENTER, views::BubbleBorder::TOP_CENTER); | |
| 146 | |
| 147 base::string16 text = shelf_view_->GetTitleForView(view); | |
| 148 bubble_ = new ShelfTooltipBubble(view, arrow, text); | |
| 149 gfx::NativeView native_view = bubble_->GetWidget()->GetNativeView(); | |
| 150 wm::SetWindowVisibilityAnimationType( | |
| 151 native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); | |
| 152 wm::SetWindowVisibilityAnimationTransition(native_view, wm::ANIMATE_HIDE); | |
| 153 bubble_->GetWidget()->Show(); | |
| 193 } | 154 } |
| 194 | 155 |
| 195 void ShelfTooltipManager::Close() { | 156 void ShelfTooltipManager::ShowTooltipWithDelay(views::View* view) { |
| 196 StopTimer(); | 157 if (!shelf_layout_manager_ || shelf_layout_manager_->IsVisible()) { |
| 197 if (view_) { | 158 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(timer_delay_), |
| 198 view_->Close(); | 159 base::Bind(&ShelfTooltipManager::ShowTooltip, |
| 199 view_ = NULL; | 160 weak_factory_.GetWeakPtr(), view)); |
| 200 widget_ = NULL; | |
| 201 } | 161 } |
| 202 } | 162 } |
| 203 | 163 |
| 204 void ShelfTooltipManager::OnBubbleClosed(views::BubbleDelegateView* view) { | 164 void ShelfTooltipManager::OnEvent(ui::Event* event) { |
| 205 if (view == view_) { | 165 // Close the tooltip on mouse press or exit, and on most non-mouse events. |
| 206 view_ = NULL; | 166 if (event->type() == ui::ET_MOUSE_PRESSED || |
| 207 widget_ = NULL; | 167 event->type() == ui::ET_MOUSE_EXITED || !event->IsMouseEvent()) { |
| 168 if (!event->IsKeyEvent()) | |
|
sky
2016/03/23 17:53:03
Did you mean !IsMouseEvent here? If not, how come
msw
2016/03/23 18:58:01
This closes for non-mouse and non-kbd events (touc
| |
| 169 Close(); | |
| 170 return; | |
| 171 } | |
| 172 | |
| 173 gfx::Point point = static_cast<ui::LocatedEvent*>(event)->location(); | |
| 174 views::View::ConvertPointFromWidget(shelf_view_, &point); | |
| 175 if (IsVisible() && shelf_view_->ShouldHideTooltip(point)) { | |
| 176 Close(); | |
| 177 return; | |
| 178 } | |
| 179 | |
| 180 views::View* view = shelf_view_->GetTooltipHandlerForPoint(point); | |
| 181 const bool should_show = shelf_view_->ShouldShowTooltipForView(view); | |
| 182 if (IsVisible() && bubble_->GetAnchorView() != view && should_show) | |
| 183 ShowTooltip(view); | |
| 184 | |
| 185 if (!IsVisible() && event->type() == ui::ET_MOUSE_MOVED) { | |
| 186 timer_.Stop(); | |
| 187 if (should_show) | |
| 188 ShowTooltipWithDelay(view); | |
| 208 } | 189 } |
| 209 } | 190 } |
| 210 | 191 |
| 211 void ShelfTooltipManager::UpdateArrow() { | |
| 212 if (view_) { | |
| 213 CancelHidingAnimation(); | |
| 214 Close(); | |
| 215 ShowImmediately(anchor_, text_); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 void ShelfTooltipManager::ResetTimer() { | |
| 220 if (timer_.get() && timer_->IsRunning()) { | |
| 221 timer_->Reset(); | |
| 222 return; | |
| 223 } | |
| 224 | |
| 225 // We don't start the timer if the shelf isn't visible. | |
| 226 if (shelf_layout_manager_ && !shelf_layout_manager_->IsVisible()) | |
| 227 return; | |
| 228 | |
| 229 CreateTimer(kTooltipAppearanceDelay); | |
| 230 } | |
| 231 | |
| 232 void ShelfTooltipManager::StopTimer() { | |
| 233 timer_.reset(); | |
| 234 } | |
| 235 | |
| 236 bool ShelfTooltipManager::IsVisible() { | |
| 237 if (timer_.get() && timer_->IsRunning()) | |
| 238 return false; | |
| 239 | |
| 240 return widget_ && widget_->IsVisible(); | |
| 241 } | |
| 242 | |
| 243 void ShelfTooltipManager::CreateZeroDelayTimerForTest() { | |
| 244 CreateTimer(0); | |
| 245 } | |
| 246 | |
| 247 void ShelfTooltipManager::OnMouseEvent(ui::MouseEvent* event) { | |
| 248 DCHECK(event); | |
| 249 DCHECK(event->target()); | |
| 250 if (!widget_ || !widget_->IsVisible()) | |
| 251 return; | |
| 252 | |
| 253 DCHECK(view_); | |
| 254 DCHECK(shelf_view_); | |
| 255 | |
| 256 // Pressing the mouse button anywhere should close the tooltip. | |
| 257 if (event->type() == ui::ET_MOUSE_PRESSED) { | |
| 258 CloseSoon(); | |
| 259 return; | |
| 260 } | |
| 261 | |
| 262 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
| 263 if (widget_->GetNativeWindow()->GetRootWindow() != target->GetRootWindow()) { | |
| 264 CloseSoon(); | |
| 265 return; | |
| 266 } | |
| 267 | |
| 268 gfx::Point location_in_shelf_view = event->location(); | |
| 269 aura::Window::ConvertPointToTarget( | |
| 270 target, shelf_view_->GetWidget()->GetNativeWindow(), | |
| 271 &location_in_shelf_view); | |
| 272 | |
| 273 if (shelf_view_->ShouldHideTooltip(location_in_shelf_view)) { | |
| 274 // Because this mouse event may arrive to |view_|, here we just schedule | |
| 275 // the closing event rather than directly calling Close(). | |
| 276 CloseSoon(); | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 void ShelfTooltipManager::OnTouchEvent(ui::TouchEvent* event) { | |
| 281 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
| 282 if (widget_ && widget_->IsVisible() && widget_->GetNativeWindow() != target) | |
| 283 Close(); | |
| 284 } | |
| 285 | |
| 286 void ShelfTooltipManager::OnGestureEvent(ui::GestureEvent* event) { | |
| 287 if (widget_ && widget_->IsVisible()) { | |
| 288 // Because this mouse event may arrive to |view_|, here we just schedule | |
| 289 // the closing event rather than directly calling Close(). | |
| 290 CloseSoon(); | |
| 291 } | |
| 292 } | |
| 293 | |
| 294 void ShelfTooltipManager::OnCancelMode(ui::CancelModeEvent* event) { | |
| 295 Close(); | |
| 296 } | |
| 297 | |
| 298 void ShelfTooltipManager::WillDeleteShelf() { | 192 void ShelfTooltipManager::WillDeleteShelf() { |
|
sky
2016/03/23 17:53:03
Should this be called from the destructor too? I'm
msw
2016/03/23 18:58:01
Done with some added checks that avoid test crashe
| |
| 299 shelf_layout_manager_ = NULL; | 193 if (shelf_layout_manager_) |
| 194 shelf_layout_manager_->RemoveObserver(this); | |
| 195 if (shelf_view_->GetWidget()->GetNativeWindow()) | |
| 196 shelf_view_->GetWidget()->GetNativeWindow()->RemovePreTargetHandler(this); | |
| 300 } | 197 } |
| 301 | 198 |
| 302 void ShelfTooltipManager::WillChangeVisibilityState( | 199 void ShelfTooltipManager::WillChangeVisibilityState( |
| 303 ShelfVisibilityState new_state) { | 200 ShelfVisibilityState new_state) { |
| 304 if (new_state == SHELF_HIDDEN) { | 201 if (new_state == SHELF_HIDDEN) |
| 305 StopTimer(); | |
| 306 Close(); | 202 Close(); |
| 307 } | |
| 308 } | 203 } |
| 309 | 204 |
| 310 void ShelfTooltipManager::OnAutoHideStateChanged(ShelfAutoHideState new_state) { | 205 void ShelfTooltipManager::OnAutoHideStateChanged(ShelfAutoHideState new_state) { |
| 311 if (new_state == SHELF_AUTO_HIDE_HIDDEN) { | 206 if (new_state == SHELF_AUTO_HIDE_HIDDEN) { |
| 312 StopTimer(); | 207 timer_.Stop(); |
| 313 // AutoHide state change happens during an event filter, so immediate close | 208 // AutoHide state change happens during an event filter, so immediate close |
| 314 // may cause a crash in the HandleMouseEvent() after the filter. So we just | 209 // may cause a crash in the HandleMouseEvent() after the filter. So we just |
| 315 // schedule the Close here. | 210 // schedule the Close here. |
| 316 CloseSoon(); | 211 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 212 FROM_HERE, | |
| 213 base::Bind(&ShelfTooltipManager::Close, weak_factory_.GetWeakPtr())); | |
| 317 } | 214 } |
| 318 } | 215 } |
| 319 | 216 |
| 320 void ShelfTooltipManager::CancelHidingAnimation() { | |
| 321 if (!widget_ || !widget_->GetNativeView()) | |
| 322 return; | |
| 323 | |
| 324 gfx::NativeView native_view = widget_->GetNativeView(); | |
| 325 wm::SetWindowVisibilityAnimationTransition( | |
| 326 native_view, wm::ANIMATE_NONE); | |
| 327 } | |
| 328 | |
| 329 void ShelfTooltipManager::CloseSoon() { | |
| 330 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 331 FROM_HERE, | |
| 332 base::Bind(&ShelfTooltipManager::Close, weak_factory_.GetWeakPtr())); | |
| 333 } | |
| 334 | |
| 335 void ShelfTooltipManager::ShowInternal() { | |
| 336 if (view_) | |
| 337 view_->GetWidget()->Show(); | |
| 338 | |
| 339 timer_.reset(); | |
| 340 } | |
| 341 | |
| 342 void ShelfTooltipManager::CreateBubble(views::View* anchor, | |
| 343 const base::string16& text) { | |
| 344 DCHECK(!view_); | |
| 345 | |
| 346 anchor_ = anchor; | |
| 347 text_ = text; | |
| 348 Shelf* shelf = shelf_layout_manager_->shelf_widget()->shelf(); | |
| 349 views::BubbleBorder::Arrow arrow = shelf->SelectValueForShelfAlignment( | |
| 350 views::BubbleBorder::BOTTOM_CENTER, views::BubbleBorder::LEFT_CENTER, | |
| 351 views::BubbleBorder::RIGHT_CENTER, views::BubbleBorder::TOP_CENTER); | |
| 352 | |
| 353 view_ = new ShelfTooltipBubble(anchor, arrow, this); | |
| 354 widget_ = view_->GetWidget(); | |
| 355 view_->SetText(text_); | |
| 356 | |
| 357 gfx::NativeView native_view = widget_->GetNativeView(); | |
| 358 wm::SetWindowVisibilityAnimationType( | |
| 359 native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); | |
| 360 wm::SetWindowVisibilityAnimationTransition( | |
| 361 native_view, wm::ANIMATE_HIDE); | |
| 362 } | |
| 363 | |
| 364 void ShelfTooltipManager::CreateTimer(int delay_in_ms) { | |
| 365 base::OneShotTimer* new_timer = new base::OneShotTimer(); | |
| 366 new_timer->Start(FROM_HERE, | |
| 367 base::TimeDelta::FromMilliseconds(delay_in_ms), | |
| 368 this, | |
| 369 &ShelfTooltipManager::ShowInternal); | |
| 370 timer_.reset(new_timer); | |
| 371 } | |
| 372 | |
| 373 } // namespace ash | 217 } // namespace ash |
| OLD | NEW |