Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/system/tray/system_tray.h" | 5 #include "ash/system/tray/system_tray.h" |
| 6 | 6 |
| 7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
| 8 #include "ash/shell/panel_window.h" | 8 #include "ash/shell/panel_window.h" |
| 9 #include "ash/shell_window_ids.h" | 9 #include "ash/shell_window_ids.h" |
| 10 #include "ash/system/audio/tray_volume.h" | 10 #include "ash/system/audio/tray_volume.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 #include "ash/system/tray_caps_lock.h" | 26 #include "ash/system/tray_caps_lock.h" |
| 27 #include "ash/system/tray_update.h" | 27 #include "ash/system/tray_update.h" |
| 28 #include "ash/system/user/tray_user.h" | 28 #include "ash/system/user/tray_user.h" |
| 29 #include "ash/system/user/login_status.h" | 29 #include "ash/system/user/login_status.h" |
| 30 #include "ash/wm/shadow_types.h" | 30 #include "ash/wm/shadow_types.h" |
| 31 #include "ash/wm/shelf_layout_manager.h" | 31 #include "ash/wm/shelf_layout_manager.h" |
| 32 #include "ash/wm/window_animations.h" | 32 #include "ash/wm/window_animations.h" |
| 33 #include "base/i18n/rtl.h" | 33 #include "base/i18n/rtl.h" |
| 34 #include "base/logging.h" | 34 #include "base/logging.h" |
| 35 #include "base/message_loop.h" | 35 #include "base/message_loop.h" |
| 36 #include "base/message_pump_observer.h" | |
| 36 #include "base/timer.h" | 37 #include "base/timer.h" |
| 37 #include "base/utf_string_conversions.h" | 38 #include "base/utf_string_conversions.h" |
| 38 #include "grit/ash_strings.h" | 39 #include "grit/ash_strings.h" |
| 39 #include "third_party/skia/include/core/SkCanvas.h" | 40 #include "third_party/skia/include/core/SkCanvas.h" |
| 40 #include "third_party/skia/include/core/SkColor.h" | 41 #include "third_party/skia/include/core/SkColor.h" |
| 41 #include "third_party/skia/include/core/SkPaint.h" | 42 #include "third_party/skia/include/core/SkPaint.h" |
| 42 #include "third_party/skia/include/core/SkPath.h" | 43 #include "third_party/skia/include/core/SkPath.h" |
| 43 #include "ui/aura/root_window.h" | 44 #include "ui/aura/root_window.h" |
| 44 #include "ui/base/events.h" | 45 #include "ui/base/events.h" |
| 45 #include "ui/base/accessibility/accessible_view_state.h" | 46 #include "ui/base/accessibility/accessible_view_state.h" |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 SkScalar radius = SkIntToScalar(kTrayRoundedBorderRadius); | 247 SkScalar radius = SkIntToScalar(kTrayRoundedBorderRadius); |
| 247 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); | 248 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); |
| 248 canvas->DrawPath(path, paint); | 249 canvas->DrawPath(path, paint); |
| 249 } | 250 } |
| 250 | 251 |
| 251 int alpha_; | 252 int alpha_; |
| 252 | 253 |
| 253 DISALLOW_COPY_AND_ASSIGN(SystemTrayBackground); | 254 DISALLOW_COPY_AND_ASSIGN(SystemTrayBackground); |
| 254 }; | 255 }; |
| 255 | 256 |
| 256 class SystemTrayBubble : public views::BubbleDelegateView { | 257 class SystemTrayBubble; |
| 258 | |
| 259 class SystemTrayBubbleView : public views::BubbleDelegateView { | |
| 260 public: | |
| 261 SystemTrayBubbleView(views::View* anchor, | |
| 262 SystemTrayBubble* host, | |
| 263 bool can_activate); | |
| 264 virtual ~SystemTrayBubbleView(); | |
| 265 | |
| 266 // Called when the host is destroyed. | |
| 267 void reset_host() { host_ = NULL; } | |
| 268 | |
| 269 private: | |
| 270 // Overridden from views::BubbleDelegateView. | |
| 271 virtual void Init() OVERRIDE; | |
| 272 virtual gfx::Rect GetAnchorRect() OVERRIDE; | |
| 273 // Overridden from views::View. | |
| 274 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; | |
| 275 virtual bool CanActivate() const OVERRIDE; | |
| 276 virtual gfx::Size GetPreferredSize() OVERRIDE; | |
| 277 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; | |
| 278 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; | |
| 279 | |
| 280 SystemTrayBubble* host_; | |
| 281 bool can_activate_; | |
| 282 | |
| 283 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleView); | |
| 284 }; | |
| 285 | |
| 286 class SystemTrayBubble : public base::MessagePumpObserver, | |
| 287 public views::Widget::Observer { | |
| 257 public: | 288 public: |
| 258 SystemTrayBubble(ash::SystemTray* tray, | 289 SystemTrayBubble(ash::SystemTray* tray, |
| 259 views::View* anchor, | |
| 260 std::vector<ash::SystemTrayItem*>& items, | 290 std::vector<ash::SystemTrayItem*>& items, |
| 261 bool detailed) | 291 bool detailed); |
| 262 : views::BubbleDelegateView(anchor, views::BubbleBorder::BOTTOM_RIGHT), | 292 virtual ~SystemTrayBubble(); |
| 263 tray_(tray), | |
| 264 items_(items), | |
| 265 detailed_(detailed), | |
| 266 can_activate_(true), | |
| 267 autoclose_delay_(0) { | |
| 268 set_margin(0); | |
| 269 set_parent_window(ash::Shell::GetInstance()->GetContainer( | |
| 270 ash::internal::kShellWindowId_SettingBubbleContainer)); | |
| 271 set_notify_enter_exit_on_child(true); | |
| 272 } | |
| 273 | 293 |
| 274 virtual ~SystemTrayBubble() { | 294 // Creates |bubble_view_| and a child views for each member of |items_|. |
| 275 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); | 295 // Also creates |bubble_widget_| and sets up animations. |
| 276 it != items_.end(); | 296 void InitView(views::View* anchor, |
| 277 ++it) { | 297 bool can_activate, |
| 278 if (detailed_) | 298 ash::user::LoginStatus login_status); |
| 279 (*it)->DestroyDetailedView(); | |
| 280 else | |
| 281 (*it)->DestroyDefaultView(); | |
| 282 } | |
| 283 } | |
| 284 | 299 |
| 285 bool detailed() const { return detailed_; } | 300 bool detailed() const { return detailed_; } |
| 286 void set_can_activate(bool activate) { can_activate_ = activate; } | 301 SystemTrayBubbleView* bubble_view() const { return bubble_view_; } |
| 287 | 302 |
| 288 void StartAutoCloseTimer(int seconds) { | 303 void DestroyItemViews(); |
| 289 autoclose_.Stop(); | 304 views::Widget* GetTrayWidget() const; |
| 290 autoclose_delay_ = seconds; | 305 void StartAutoCloseTimer(int seconds); |
| 291 if (autoclose_delay_) { | 306 void StopAutoCloseTimer(); |
| 292 autoclose_.Start(FROM_HERE, | 307 void RestartAutoCloseTimer(); |
| 293 base::TimeDelta::FromSeconds(autoclose_delay_), | 308 void Hide(); |
| 294 this, &SystemTrayBubble::AutoClose); | 309 void Show(); |
| 295 } | 310 bool IsVisible() const; |
| 296 } | |
| 297 | 311 |
| 298 private: | 312 private: |
| 299 void AutoClose() { | 313 // Overridden from base::MessagePumpObserver. |
| 300 GetWidget()->Close(); | 314 virtual base::EventStatus WillProcessEvent( |
| 301 } | 315 const base::NativeEvent& event) OVERRIDE; |
| 316 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE; | |
| 317 // Overridden from views::Widget::Observer. | |
| 318 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; | |
| 319 virtual void OnWidgetVisibilityChanged(views::Widget* widget, | |
| 320 bool visible) OVERRIDE; | |
| 302 | 321 |
| 303 // Overridden from views::BubbleDelegateView. | 322 void AutoClose(); |
| 304 virtual void Init() OVERRIDE { | |
| 305 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, | |
| 306 1, 1, 1)); | |
| 307 set_background(new SystemTrayBubbleBackground(this)); | |
| 308 | 323 |
| 309 ash::SystemTrayDelegate* delegate = | 324 ash::SystemTray* tray_; |
| 310 ash::Shell::GetInstance()->tray_delegate(); | 325 SystemTrayBubbleView* bubble_view_; |
| 311 ash::user::LoginStatus login_status = delegate->GetUserLoginStatus(); | 326 views::Widget* bubble_widget_; |
| 312 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); | 327 std::vector<ash::SystemTrayItem*> items_; |
| 313 it != items_.end(); | 328 bool detailed_; |
| 314 ++it) { | |
| 315 views::View* view = detailed_ ? (*it)->CreateDetailedView(login_status) : | |
| 316 (*it)->CreateDefaultView(login_status); | |
| 317 if (view) | |
| 318 AddChildView(new TrayPopupItemContainer(view)); | |
| 319 } | |
| 320 } | |
| 321 | 329 |
| 322 virtual gfx::Rect GetAnchorRect() OVERRIDE { | 330 int autoclose_delay_; |
| 323 views::Widget* widget = tray_->GetWidget(); | 331 base::OneShotTimer<SystemTrayBubble> autoclose_; |
| 332 | |
| 333 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubble); | |
| 334 }; | |
| 335 | |
| 336 // SystemTrayBubbleView | |
| 337 | |
| 338 SystemTrayBubbleView::SystemTrayBubbleView(views::View* anchor, | |
| 339 SystemTrayBubble* host, | |
| 340 bool can_activate) | |
| 341 : views::BubbleDelegateView(anchor, views::BubbleBorder::BOTTOM_RIGHT), | |
| 342 host_(host), | |
| 343 can_activate_(can_activate) { | |
| 344 set_margin(0); | |
| 345 set_parent_window(ash::Shell::GetInstance()->GetContainer( | |
| 346 ash::internal::kShellWindowId_SettingBubbleContainer)); | |
| 347 set_notify_enter_exit_on_child(true); | |
| 348 } | |
| 349 | |
| 350 SystemTrayBubbleView::~SystemTrayBubbleView() { | |
| 351 // Inform host items (models) that their views are being destroyed. | |
| 352 if (host_) | |
| 353 host_->DestroyItemViews(); | |
| 354 } | |
| 355 | |
| 356 void SystemTrayBubbleView::Init() { | |
| 357 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 1, 1, 1)); | |
| 358 set_background(new SystemTrayBubbleBackground(this)); | |
| 359 } | |
| 360 | |
| 361 gfx::Rect SystemTrayBubbleView::GetAnchorRect() OVERRIDE { | |
| 362 if (host_) { | |
| 363 views::Widget* widget = host_->GetTrayWidget(); | |
| 324 if (widget->IsVisible()) { | 364 if (widget->IsVisible()) { |
| 325 gfx::Rect rect = widget->GetWindowScreenBounds(); | 365 gfx::Rect rect = widget->GetWindowScreenBounds(); |
| 326 rect.Inset( | 366 rect.Inset( |
| 327 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : 0, 0, | 367 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : 0, 0, |
| 328 base::i18n::IsRTL() ? 0 : kPaddingFromRightEdgeOfScreen, | 368 base::i18n::IsRTL() ? 0 : kPaddingFromRightEdgeOfScreen, |
| 329 kPaddingFromBottomOfScreen); | 369 kPaddingFromBottomOfScreen); |
| 330 return rect; | 370 return rect; |
| 331 } | 371 } |
| 332 gfx::Rect rect = gfx::Screen::GetPrimaryMonitor().bounds(); | 372 } |
| 333 return gfx::Rect(base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : | 373 gfx::Rect rect = gfx::Screen::GetPrimaryMonitor().bounds(); |
| 334 rect.width() - kPaddingFromRightEdgeOfScreen, | 374 return gfx::Rect(base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : |
| 335 rect.height() - kPaddingFromBottomOfScreen, | 375 rect.width() - kPaddingFromRightEdgeOfScreen, |
| 336 0, 0); | 376 rect.height() - kPaddingFromBottomOfScreen, |
| 377 0, 0); | |
| 378 } | |
| 379 | |
| 380 void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { | |
| 381 if (can_activate_) { | |
| 382 state->role = ui::AccessibilityTypes::ROLE_WINDOW; | |
| 383 state->name = l10n_util::GetStringUTF16( | |
| 384 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 bool SystemTrayBubbleView::CanActivate() const { | |
| 389 return can_activate_; | |
| 390 } | |
| 391 | |
| 392 gfx::Size SystemTrayBubbleView::GetPreferredSize() { | |
| 393 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); | |
| 394 return gfx::Size(kTrayPopupWidth, size.height()); | |
| 395 } | |
| 396 | |
| 397 void SystemTrayBubbleView::OnMouseEntered(const views::MouseEvent& event) { | |
| 398 if (host_) | |
| 399 host_->StopAutoCloseTimer(); | |
| 400 } | |
| 401 | |
| 402 void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) { | |
| 403 if (host_) | |
| 404 host_->RestartAutoCloseTimer(); | |
| 405 } | |
| 406 | |
| 407 // SystemTrayBubble | |
| 408 | |
| 409 SystemTrayBubble::SystemTrayBubble(ash::SystemTray* tray, | |
| 410 std::vector<ash::SystemTrayItem*>& items, | |
| 411 bool detailed) | |
| 412 : tray_(tray), | |
| 413 bubble_view_(NULL), | |
| 414 bubble_widget_(NULL), | |
| 415 items_(items), | |
| 416 detailed_(detailed), | |
| 417 autoclose_delay_(0) { | |
| 418 MessageLoopForUI::current()->AddObserver(this); | |
| 419 } | |
| 420 | |
| 421 SystemTrayBubble::~SystemTrayBubble() { | |
| 422 MessageLoopForUI::current()->RemoveObserver(this); | |
| 423 DestroyItemViews(); | |
| 424 // Reset the host pointer in bubble_view_ in case its destruction is deferred. | |
| 425 if (bubble_view_) | |
| 426 bubble_view_->reset_host(); | |
| 427 if (bubble_widget_) { | |
| 428 bubble_widget_->RemoveObserver(this); | |
| 429 // This triggers the destruction of bubble_view_. | |
| 430 bubble_widget_->Close(); | |
| 431 } | |
| 432 } | |
| 433 | |
| 434 void SystemTrayBubble::InitView(views::View* anchor, | |
| 435 bool can_activate, | |
| 436 ash::user::LoginStatus login_status) { | |
| 437 DCHECK(bubble_view_ == NULL); | |
| 438 bubble_view_ = new SystemTrayBubbleView(anchor, this, can_activate); | |
| 439 // Don't close this on deactivation, just hide it. | |
| 440 bubble_view_->set_close_on_deactivate(false); | |
|
sadrul
2012/04/30 17:46:19
Is there a reason for this change?
stevenjb
2012/04/30 19:09:54
Yes, as described, this makes the window hide on d
| |
| 441 | |
| 442 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); | |
| 443 it != items_.end(); | |
| 444 ++it) { | |
| 445 views::View* view = detailed_ ? | |
| 446 (*it)->CreateDetailedView(login_status) : | |
| 447 (*it)->CreateDefaultView(login_status); | |
| 448 if (view) | |
| 449 bubble_view_->AddChildView(new TrayPopupItemContainer(view)); | |
| 337 } | 450 } |
| 338 | 451 |
| 339 // Overridden from views::View. | 452 DCHECK(bubble_widget_ == NULL); |
| 340 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE { | 453 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); |
| 341 if (can_activate_) { | 454 |
| 342 state->role = ui::AccessibilityTypes::ROLE_WINDOW; | 455 // Must occur after call to CreateBubble() |
| 343 state->name = l10n_util::GetStringUTF16( | 456 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
| 344 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); | 457 bubble_widget_->non_client_view()->frame_view()->set_background(NULL); |
| 458 bubble_widget_->non_client_view()->frame_view()->set_border( | |
| 459 new SystemTrayBubbleBorder(bubble_view_)); | |
| 460 | |
| 461 bubble_widget_->AddObserver(this); | |
| 462 | |
| 463 // Setup animation. | |
| 464 ash::SetWindowVisibilityAnimationType( | |
| 465 bubble_widget_->GetNativeWindow(), | |
| 466 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); | |
| 467 ash::SetWindowVisibilityAnimationTransition( | |
| 468 bubble_widget_->GetNativeWindow(), | |
| 469 ash::ANIMATE_BOTH); | |
| 470 ash::SetWindowVisibilityAnimationDuration( | |
| 471 bubble_widget_->GetNativeWindow(), | |
| 472 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); | |
| 473 | |
| 474 bubble_view_->Show(); | |
| 475 } | |
| 476 | |
| 477 void SystemTrayBubble::DestroyItemViews() { | |
| 478 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); | |
| 479 it != items_.end(); | |
| 480 ++it) { | |
| 481 if (detailed_) | |
| 482 (*it)->DestroyDetailedView(); | |
| 483 else | |
| 484 (*it)->DestroyDefaultView(); | |
| 485 } | |
| 486 } | |
| 487 | |
| 488 views::Widget* SystemTrayBubble::GetTrayWidget() const { | |
| 489 return tray_->GetWidget(); | |
| 490 } | |
| 491 | |
| 492 void SystemTrayBubble::StartAutoCloseTimer(int seconds) { | |
| 493 autoclose_.Stop(); | |
| 494 autoclose_delay_ = seconds; | |
| 495 if (autoclose_delay_) { | |
| 496 autoclose_.Start(FROM_HERE, | |
| 497 base::TimeDelta::FromSeconds(autoclose_delay_), | |
| 498 this, &SystemTrayBubble::AutoClose); | |
| 499 } | |
| 500 } | |
| 501 | |
| 502 void SystemTrayBubble::StopAutoCloseTimer() { | |
| 503 autoclose_.Stop(); | |
| 504 } | |
| 505 | |
| 506 void SystemTrayBubble::RestartAutoCloseTimer() { | |
| 507 if (autoclose_delay_) | |
| 508 StartAutoCloseTimer(autoclose_delay_); | |
| 509 } | |
| 510 | |
| 511 void SystemTrayBubble::Hide() { | |
| 512 if (bubble_widget_) | |
| 513 bubble_widget_->Hide(); | |
| 514 } | |
| 515 | |
| 516 void SystemTrayBubble::Show() { | |
| 517 DCHECK(bubble_widget_); | |
| 518 bubble_widget_->Show(); | |
| 519 } | |
| 520 | |
| 521 bool SystemTrayBubble::IsVisible() const { | |
| 522 return bubble_widget_ && bubble_widget_->IsVisible(); | |
| 523 } | |
| 524 | |
| 525 base::EventStatus SystemTrayBubble::WillProcessEvent( | |
| 526 const base::NativeEvent& event) { | |
| 527 // Check if the user clicked outside of the bubble and hide it if they did. | |
| 528 if (ui::EventTypeFromNative(event) == ui::ET_MOUSE_PRESSED) { | |
| 529 gfx::Point cursor_in_view = ui::EventLocationFromNative(event); | |
| 530 views::View::ConvertPointFromScreen(bubble_view_, &cursor_in_view); | |
| 531 if (!bubble_view_->HitTest(cursor_in_view)) { | |
| 532 bubble_widget_->Hide(); | |
|
sadrul
2012/04/30 17:46:19
This should, in fact, close the bubble.
stevenjb
2012/04/30 19:09:54
Done. See above.
| |
| 345 } | 533 } |
| 346 } | 534 } |
| 535 return base::EVENT_CONTINUE; | |
| 536 } | |
| 347 | 537 |
| 348 virtual bool CanActivate() const OVERRIDE { | 538 void SystemTrayBubble::DidProcessEvent(const base::NativeEvent& event) { |
| 349 return can_activate_; | 539 } |
| 350 } | |
| 351 | 540 |
| 352 virtual gfx::Size GetPreferredSize() OVERRIDE { | 541 void SystemTrayBubble::OnWidgetClosing(views::Widget* widget) { |
| 353 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); | 542 CHECK_EQ(bubble_widget_, widget); |
| 354 return gfx::Size(kTrayPopupWidth, size.height()); | 543 MessageLoopForUI::current()->RemoveObserver(this); |
| 355 } | 544 bubble_widget_ = NULL; |
| 545 tray_->RemoveBubble(this); | |
| 546 } | |
| 356 | 547 |
| 357 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { | 548 void SystemTrayBubble::OnWidgetVisibilityChanged(views::Widget* widget, |
| 358 autoclose_.Stop(); | 549 bool visible) { |
| 359 } | 550 if (!visible) |
| 551 MessageLoopForUI::current()->RemoveObserver(this); | |
| 552 else | |
| 553 MessageLoopForUI::current()->AddObserver(this); | |
| 554 } | |
| 360 | 555 |
| 361 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { | 556 void SystemTrayBubble::AutoClose() { |
| 362 if (autoclose_delay_) { | 557 bubble_view_->GetWidget()->Close(); |
| 363 autoclose_.Stop(); | 558 } |
| 364 autoclose_.Start(FROM_HERE, | |
| 365 base::TimeDelta::FromSeconds(autoclose_delay_), | |
| 366 this, &SystemTrayBubble::AutoClose); | |
| 367 } | |
| 368 } | |
| 369 | |
| 370 ash::SystemTray* tray_; | |
| 371 std::vector<ash::SystemTrayItem*> items_; | |
| 372 bool detailed_; | |
| 373 bool can_activate_; | |
| 374 | |
| 375 int autoclose_delay_; | |
| 376 base::OneShotTimer<SystemTrayBubble> autoclose_; | |
| 377 | |
| 378 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubble); | |
| 379 }; | |
| 380 | 559 |
| 381 } // namespace internal | 560 } // namespace internal |
| 382 | 561 |
| 562 // From system_tray_delegate.h | |
| 563 | |
| 383 NetworkIconInfo::NetworkIconInfo() | 564 NetworkIconInfo::NetworkIconInfo() |
| 384 : highlight(false), | 565 : highlight(false), |
| 385 tray_icon_visible(true) { | 566 tray_icon_visible(true) { |
| 386 } | 567 } |
| 387 | 568 |
| 388 NetworkIconInfo::~NetworkIconInfo() { | 569 NetworkIconInfo::~NetworkIconInfo() { |
| 389 } | 570 } |
| 390 | 571 |
| 391 BluetoothDeviceInfo::BluetoothDeviceInfo() | 572 BluetoothDeviceInfo::BluetoothDeviceInfo() |
| 392 : connected(false) { | 573 : connected(false) { |
| 393 } | 574 } |
| 394 | 575 |
| 395 BluetoothDeviceInfo::~BluetoothDeviceInfo() { | 576 BluetoothDeviceInfo::~BluetoothDeviceInfo() { |
| 396 } | 577 } |
| 397 | 578 |
| 398 IMEInfo::IMEInfo() | 579 IMEInfo::IMEInfo() |
| 399 : selected(false) { | 580 : selected(false) { |
| 400 } | 581 } |
| 401 | 582 |
| 402 IMEInfo::~IMEInfo() { | 583 IMEInfo::~IMEInfo() { |
| 403 } | 584 } |
| 404 | 585 |
| 405 IMEPropertyInfo::IMEPropertyInfo() | 586 IMEPropertyInfo::IMEPropertyInfo() |
| 406 : selected(false) { | 587 : selected(false) { |
| 407 } | 588 } |
| 408 | 589 |
| 409 IMEPropertyInfo::~IMEPropertyInfo() { | 590 IMEPropertyInfo::~IMEPropertyInfo() { |
| 410 } | 591 } |
| 411 | 592 |
| 593 // SystemTray | |
| 594 | |
| 412 SystemTray::SystemTray() | 595 SystemTray::SystemTray() |
| 413 : items_(), | 596 : items_(), |
| 414 accessibility_observer_(NULL), | 597 accessibility_observer_(NULL), |
| 415 audio_observer_(NULL), | 598 audio_observer_(NULL), |
| 416 bluetooth_observer_(NULL), | 599 bluetooth_observer_(NULL), |
| 417 brightness_observer_(NULL), | 600 brightness_observer_(NULL), |
| 418 caps_lock_observer_(NULL), | 601 caps_lock_observer_(NULL), |
| 419 clock_observer_(NULL), | 602 clock_observer_(NULL), |
| 420 ime_observer_(NULL), | 603 ime_observer_(NULL), |
| 421 network_observer_(NULL), | 604 network_observer_(NULL), |
| 422 power_status_observer_(NULL), | 605 power_status_observer_(NULL), |
| 423 update_observer_(NULL), | 606 update_observer_(NULL), |
| 424 user_observer_(NULL), | 607 user_observer_(NULL), |
| 425 widget_(NULL), | 608 widget_(NULL), |
| 426 bubble_(NULL), | 609 bubble_(NULL), |
| 427 popup_(NULL), | |
| 428 background_(new internal::SystemTrayBackground), | 610 background_(new internal::SystemTrayBackground), |
| 429 should_show_launcher_(false), | 611 should_show_launcher_(false), |
| 430 ALLOW_THIS_IN_INITIALIZER_LIST(hide_background_animator_(this, | 612 ALLOW_THIS_IN_INITIALIZER_LIST(hide_background_animator_(this, |
| 431 0, kTrayBackgroundAlpha)), | 613 0, kTrayBackgroundAlpha)), |
| 432 ALLOW_THIS_IN_INITIALIZER_LIST(hover_background_animator_(this, | 614 ALLOW_THIS_IN_INITIALIZER_LIST(hover_background_animator_(this, |
| 433 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha)) { | 615 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha)) { |
| 434 container_ = new views::View; | 616 container_ = new views::View; |
| 435 container_->SetLayoutManager(new views::BoxLayout( | 617 container_->SetLayoutManager(new views::BoxLayout( |
| 436 views::BoxLayout::kHorizontal, 0, 0, 0)); | 618 views::BoxLayout::kHorizontal, 0, 0, 0)); |
| 437 container_->set_background(background_); | 619 container_->set_background(background_); |
| 438 container_->set_border( | 620 container_->set_border( |
| 439 views::Border::CreateEmptyBorder(1, 1, 1, 1)); | 621 views::Border::CreateEmptyBorder(1, 1, 1, 1)); |
| 440 set_border(views::Border::CreateEmptyBorder(0, 0, | 622 set_border(views::Border::CreateEmptyBorder(0, 0, |
| 441 kPaddingFromBottomOfScreen, kPaddingFromRightEdgeOfScreen)); | 623 kPaddingFromBottomOfScreen, kPaddingFromRightEdgeOfScreen)); |
| 442 set_notify_enter_exit_on_child(true); | 624 set_notify_enter_exit_on_child(true); |
| 443 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); | 625 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); |
| 444 AddChildView(container_); | 626 AddChildView(container_); |
| 445 | 627 |
| 446 // Initially we want to paint the background, but without the hover effect. | 628 // Initially we want to paint the background, but without the hover effect. |
| 447 SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE); | 629 SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE); |
| 448 hover_background_animator_.SetPaintsBackground(false, | 630 hover_background_animator_.SetPaintsBackground(false, |
| 449 internal::BackgroundAnimator::CHANGE_IMMEDIATE); | 631 internal::BackgroundAnimator::CHANGE_IMMEDIATE); |
| 450 } | 632 } |
| 451 | 633 |
| 452 SystemTray::~SystemTray() { | 634 SystemTray::~SystemTray() { |
| 635 delete bubble_; | |
| 453 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); | 636 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); |
| 454 it != items_.end(); | 637 it != items_.end(); |
| 455 ++it) { | 638 ++it) { |
| 456 (*it)->DestroyTrayView(); | 639 (*it)->DestroyTrayView(); |
| 457 } | 640 } |
| 458 if (popup_) | |
| 459 popup_->CloseNow(); | |
| 460 } | 641 } |
| 461 | 642 |
| 462 void SystemTray::CreateItems() { | 643 void SystemTray::CreateItems() { |
| 463 internal::TrayVolume* tray_volume = new internal::TrayVolume(); | 644 internal::TrayVolume* tray_volume = new internal::TrayVolume(); |
| 464 internal::TrayBluetooth* tray_bluetooth = new internal::TrayBluetooth(); | 645 internal::TrayBluetooth* tray_bluetooth = new internal::TrayBluetooth(); |
| 465 internal::TrayBrightness* tray_brightness = new internal::TrayBrightness(); | 646 internal::TrayBrightness* tray_brightness = new internal::TrayBrightness(); |
| 466 internal::TrayDate* tray_date = new internal::TrayDate(); | 647 internal::TrayDate* tray_date = new internal::TrayDate(); |
| 467 internal::TrayPower* tray_power = new internal::TrayPower(); | 648 internal::TrayPower* tray_power = new internal::TrayPower(); |
| 468 internal::TrayNetwork* tray_network = new internal::TrayNetwork; | 649 internal::TrayNetwork* tray_network = new internal::TrayNetwork; |
| 469 internal::TrayUser* tray_user = new internal::TrayUser; | 650 internal::TrayUser* tray_user = new internal::TrayUser; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 532 container_->AddChildViewAt(tray_item, 0); | 713 container_->AddChildViewAt(tray_item, 0); |
| 533 PreferredSizeChanged(); | 714 PreferredSizeChanged(); |
| 534 } | 715 } |
| 535 } | 716 } |
| 536 | 717 |
| 537 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { | 718 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { |
| 538 NOTIMPLEMENTED(); | 719 NOTIMPLEMENTED(); |
| 539 } | 720 } |
| 540 | 721 |
| 541 void SystemTray::ShowDefaultView() { | 722 void SystemTray::ShowDefaultView() { |
| 542 if (popup_) { | 723 if (bubble_ && !bubble_->detailed()) { |
| 543 MessageLoopForUI::current()->RemoveObserver(this); | 724 bubble_->Show(); |
| 544 popup_->RemoveObserver(this); | 725 return; |
| 545 popup_->Close(); | |
| 546 } | 726 } |
| 547 popup_ = NULL; | 727 delete bubble_; |
| 548 bubble_ = NULL; | 728 bubble_ = NULL; |
| 549 | |
| 550 ShowItems(items_.get(), false, true); | 729 ShowItems(items_.get(), false, true); |
| 551 } | 730 } |
| 552 | 731 |
| 553 void SystemTray::ShowDetailedView(SystemTrayItem* item, | 732 void SystemTray::ShowDetailedView(SystemTrayItem* item, |
| 554 int close_delay, | 733 int close_delay, |
| 555 bool activate) { | 734 bool activate) { |
| 556 if (popup_) { | 735 delete bubble_; |
| 557 MessageLoopForUI::current()->RemoveObserver(this); | |
| 558 popup_->RemoveObserver(this); | |
| 559 popup_->Close(); | |
| 560 } | |
| 561 popup_ = NULL; | |
| 562 bubble_ = NULL; | 736 bubble_ = NULL; |
| 563 | |
| 564 std::vector<SystemTrayItem*> items; | 737 std::vector<SystemTrayItem*> items; |
| 565 items.push_back(item); | 738 items.push_back(item); |
| 566 ShowItems(items, true, activate); | 739 ShowItems(items, true, activate); |
| 567 bubble_->StartAutoCloseTimer(close_delay); | 740 bubble_->StartAutoCloseTimer(close_delay); |
| 568 } | 741 } |
| 569 | 742 |
| 570 void SystemTray::SetDetailedViewCloseDelay(int close_delay) { | 743 void SystemTray::SetDetailedViewCloseDelay(int close_delay) { |
| 571 if (bubble_ && bubble_->detailed()) | 744 if (bubble_ && bubble_->detailed()) |
| 572 bubble_->StartAutoCloseTimer(close_delay); | 745 bubble_->StartAutoCloseTimer(close_delay); |
| 573 } | 746 } |
| 574 | 747 |
| 575 void SystemTray::UpdateAfterLoginStatusChange(user::LoginStatus login_status) { | 748 void SystemTray::UpdateAfterLoginStatusChange(user::LoginStatus login_status) { |
| 576 if (popup_) | 749 delete bubble_; |
| 577 popup_->CloseNow(); | 750 bubble_ = NULL; |
| 578 | 751 |
| 579 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); | 752 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); |
| 580 it != items_.end(); | 753 it != items_.end(); |
| 581 ++it) { | 754 ++it) { |
| 582 (*it)->UpdateAfterLoginStatusChange(login_status); | 755 (*it)->UpdateAfterLoginStatusChange(login_status); |
| 583 } | 756 } |
| 584 | 757 |
| 585 SetVisible(true); | 758 SetVisible(true); |
| 586 PreferredSizeChanged(); | 759 PreferredSizeChanged(); |
| 587 } | 760 } |
| 588 | 761 |
| 762 void SystemTray::RemoveBubble(internal::SystemTrayBubble* bubble) { | |
| 763 CHECK_EQ(bubble_, bubble); | |
| 764 delete bubble_; | |
| 765 bubble_ = NULL; | |
| 766 | |
| 767 if (should_show_launcher_) { | |
| 768 // No need to show the launcher if the mouse isn't over the status area | |
| 769 // anymore. | |
| 770 aura::RootWindow* root = GetWidget()->GetNativeView()->GetRootWindow(); | |
| 771 should_show_launcher_ = GetWidget()->GetWindowScreenBounds().Contains( | |
| 772 root->last_mouse_location()); | |
| 773 if (!should_show_launcher_) | |
| 774 Shell::GetInstance()->shelf()->UpdateAutoHideState(); | |
| 775 } | |
| 776 } | |
| 777 | |
| 589 void SystemTray::SetPaintsBackground( | 778 void SystemTray::SetPaintsBackground( |
| 590 bool value, | 779 bool value, |
| 591 internal::BackgroundAnimator::ChangeType change_type) { | 780 internal::BackgroundAnimator::ChangeType change_type) { |
| 592 hide_background_animator_.SetPaintsBackground(value, change_type); | 781 hide_background_animator_.SetPaintsBackground(value, change_type); |
| 593 } | 782 } |
| 594 | 783 |
| 595 void SystemTray::ShowItems(std::vector<SystemTrayItem*>& items, | 784 void SystemTray::ShowItems(std::vector<SystemTrayItem*>& items, |
| 596 bool detailed, | 785 bool detailed, |
| 597 bool activate) { | 786 bool can_activate) { |
| 598 CHECK(!popup_); | |
| 599 CHECK(!bubble_); | 787 CHECK(!bubble_); |
| 600 bubble_ = new internal::SystemTrayBubble(this, container_, items, detailed); | 788 bubble_ = new internal::SystemTrayBubble(this, items, detailed); |
| 601 bubble_->set_can_activate(activate); | 789 ash::SystemTrayDelegate* delegate = |
| 602 popup_ = views::BubbleDelegateView::CreateBubble(bubble_); | 790 ash::Shell::GetInstance()->tray_delegate(); |
| 791 bubble_->InitView(container_, can_activate, delegate->GetUserLoginStatus()); | |
| 603 // If we have focus the shelf should be visible and we need to continue | 792 // If we have focus the shelf should be visible and we need to continue |
| 604 // showing the shelf when the popup is shown. | 793 // showing the shelf when the popup is shown. |
| 605 if (GetWidget()->IsActive()) | 794 if (GetWidget()->IsActive()) |
| 606 should_show_launcher_ = true; | 795 should_show_launcher_ = true; |
| 607 bubble_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | |
| 608 popup_->non_client_view()->frame_view()->set_background(NULL); | |
| 609 popup_->non_client_view()->frame_view()->set_border( | |
| 610 new SystemTrayBubbleBorder(bubble_)); | |
| 611 MessageLoopForUI::current()->AddObserver(this); | |
| 612 popup_->AddObserver(this); | |
| 613 | |
| 614 // Setup animation. | |
| 615 ash::SetWindowVisibilityAnimationType(popup_->GetNativeWindow(), | |
| 616 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); | |
| 617 ash::SetWindowVisibilityAnimationTransition(popup_->GetNativeWindow(), | |
| 618 ash::ANIMATE_BOTH); | |
| 619 ash::SetWindowVisibilityAnimationDuration(popup_->GetNativeWindow(), | |
| 620 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); | |
| 621 | |
| 622 bubble_->Show(); | |
| 623 } | 796 } |
| 624 | 797 |
| 625 bool SystemTray::PerformAction(const views::Event& event) { | 798 bool SystemTray::PerformAction(const views::Event& event) { |
| 626 // If we're already showing the default view, hide it; otherwise, show it | 799 // If we're already showing the default view, hide it; otherwise, show it |
| 627 // (and hide any popup that's currently shown). | 800 // (and hide any popup that's currently shown). |
| 628 if (popup_ && bubble_ && !bubble_->detailed()) | 801 if (bubble_ && !bubble_->detailed() && bubble_->IsVisible()) |
| 629 popup_->Hide(); | 802 bubble_->Hide(); |
| 630 else | 803 else |
| 631 ShowDefaultView(); | 804 ShowDefaultView(); |
| 632 return true; | 805 return true; |
| 633 } | 806 } |
| 634 | 807 |
| 635 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { | 808 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { |
| 636 should_show_launcher_ = true; | 809 should_show_launcher_ = true; |
| 637 hover_background_animator_.SetPaintsBackground(true, | 810 hover_background_animator_.SetPaintsBackground(true, |
| 638 internal::BackgroundAnimator::CHANGE_ANIMATE); | 811 internal::BackgroundAnimator::CHANGE_ANIMATE); |
| 639 } | 812 } |
| 640 | 813 |
| 641 void SystemTray::OnMouseExited(const views::MouseEvent& event) { | 814 void SystemTray::OnMouseExited(const views::MouseEvent& event) { |
| 642 // When the popup closes we'll update |should_show_launcher_|. | 815 // When the popup closes we'll update |should_show_launcher_|. |
| 643 if (!popup_) | 816 if (!bubble_) |
| 644 should_show_launcher_ = false; | 817 should_show_launcher_ = false; |
| 645 hover_background_animator_.SetPaintsBackground(false, | 818 hover_background_animator_.SetPaintsBackground(false, |
| 646 internal::BackgroundAnimator::CHANGE_ANIMATE); | 819 internal::BackgroundAnimator::CHANGE_ANIMATE); |
| 647 } | 820 } |
| 648 | 821 |
| 649 void SystemTray::AboutToRequestFocusFromTabTraversal(bool reverse) { | 822 void SystemTray::AboutToRequestFocusFromTabTraversal(bool reverse) { |
| 650 views::View* v = GetNextFocusableView(); | 823 views::View* v = GetNextFocusableView(); |
| 651 if (v) | 824 if (v) |
| 652 v->AboutToRequestFocusFromTabTraversal(reverse); | 825 v->AboutToRequestFocusFromTabTraversal(reverse); |
| 653 } | 826 } |
| 654 | 827 |
| 655 void SystemTray::GetAccessibleState(ui::AccessibleViewState* state) { | 828 void SystemTray::GetAccessibleState(ui::AccessibleViewState* state) { |
| 656 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; | 829 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; |
| 657 state->name = l10n_util::GetStringUTF16( | 830 state->name = l10n_util::GetStringUTF16( |
| 658 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); | 831 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); |
| 659 } | 832 } |
| 660 | 833 |
| 661 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { | 834 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { |
| 662 // The tray itself expands to the right and bottom edge of the screen to make | 835 // The tray itself expands to the right and bottom edge of the screen to make |
| 663 // sure clicking on the edges brings up the popup. However, the focus border | 836 // sure clicking on the edges brings up the popup. However, the focus border |
| 664 // should be only around the container. | 837 // should be only around the container. |
| 665 if (GetWidget() && GetWidget()->IsActive()) | 838 if (GetWidget() && GetWidget()->IsActive()) |
| 666 canvas->DrawFocusRect(container_->bounds()); | 839 canvas->DrawFocusRect(container_->bounds()); |
| 667 } | 840 } |
| 668 | 841 |
| 669 void SystemTray::OnWidgetClosing(views::Widget* widget) { | |
| 670 CHECK_EQ(popup_, widget); | |
| 671 MessageLoopForUI::current()->RemoveObserver(this); | |
| 672 popup_ = NULL; | |
| 673 bubble_ = NULL; | |
| 674 if (should_show_launcher_) { | |
| 675 // No need to show the launcher if the mouse isn't over the status area | |
| 676 // anymore. | |
| 677 aura::RootWindow* root = GetWidget()->GetNativeView()->GetRootWindow(); | |
| 678 should_show_launcher_ = GetWidget()->GetWindowScreenBounds().Contains( | |
| 679 root->last_mouse_location()); | |
| 680 if (!should_show_launcher_) | |
| 681 Shell::GetInstance()->shelf()->UpdateAutoHideState(); | |
| 682 } | |
| 683 } | |
| 684 | |
| 685 void SystemTray::OnWidgetVisibilityChanged(views::Widget* widget, | |
| 686 bool visible) { | |
| 687 if (!visible) | |
| 688 MessageLoopForUI::current()->RemoveObserver(this); | |
| 689 } | |
| 690 | |
| 691 void SystemTray::UpdateBackground(int alpha) { | 842 void SystemTray::UpdateBackground(int alpha) { |
| 692 background_->set_alpha(hide_background_animator_.alpha() + | 843 background_->set_alpha(hide_background_animator_.alpha() + |
| 693 hover_background_animator_.alpha()); | 844 hover_background_animator_.alpha()); |
| 694 SchedulePaint(); | 845 SchedulePaint(); |
| 695 } | 846 } |
| 696 | 847 |
| 697 base::EventStatus SystemTray::WillProcessEvent(const base::NativeEvent& event) { | |
| 698 // Check if the user clicked outside of the system tray bubble and hide it | |
| 699 // if they did. | |
| 700 if (bubble_ && ui::EventTypeFromNative(event) == ui::ET_MOUSE_PRESSED) { | |
| 701 gfx::Point cursor_in_view = ui::EventLocationFromNative(event); | |
| 702 View::ConvertPointFromScreen(bubble_, &cursor_in_view); | |
| 703 if (!bubble_->HitTest(cursor_in_view)) { | |
| 704 popup_->Hide(); | |
| 705 } | |
| 706 } | |
| 707 return base::EVENT_CONTINUE; | |
| 708 } | |
| 709 | |
| 710 void SystemTray::DidProcessEvent(const base::NativeEvent& event) { | |
| 711 } | |
| 712 | |
| 713 } // namespace ash | 848 } // namespace ash |
| OLD | NEW |