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