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