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