Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: ash/system/tray/system_tray.cc

Issue 10383045: Add support to SystemTray for a second notification bubble. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address nits Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ash/system/tray/system_tray.h ('k') | ash/system/tray/system_tray_item.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 } 203 }
204 } 204 }
205 205
206 views::View* owner_; 206 views::View* owner_;
207 207
208 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBackground); 208 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBackground);
209 }; 209 };
210 210
211 class SystemTrayBubbleBorder : public views::BubbleBorder { 211 class SystemTrayBubbleBorder : public views::BubbleBorder {
212 public: 212 public:
213 explicit SystemTrayBubbleBorder(views::View* owner) 213 enum ArrowType {
214 ARROW_TYPE_NONE,
215 ARROW_TYPE_BOTTOM,
216 };
217
218 SystemTrayBubbleBorder(views::View* owner, ArrowType arrow_type)
214 : views::BubbleBorder(views::BubbleBorder::BOTTOM_RIGHT, 219 : views::BubbleBorder(views::BubbleBorder::BOTTOM_RIGHT,
215 views::BubbleBorder::NO_SHADOW), 220 views::BubbleBorder::NO_SHADOW),
216 owner_(owner) { 221 owner_(owner),
222 arrow_type_(arrow_type) {
217 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); 223 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
218 } 224 }
219 225
220 virtual ~SystemTrayBubbleBorder() {} 226 virtual ~SystemTrayBubbleBorder() {}
221 227
222 private: 228 private:
223 // Overridden from views::Border. 229 // Overridden from views::Border.
224 virtual void Paint(const views::View& view, 230 virtual void Paint(const views::View& view,
225 gfx::Canvas* canvas) const OVERRIDE { 231 gfx::Canvas* canvas) const OVERRIDE {
226 views::View* first = NULL, *last = NULL; 232 views::View* first = NULL, *last = NULL;
(...skipping 22 matching lines...) Expand all
249 255
250 // Draw the bottom line. 256 // Draw the bottom line.
251 int y = owner_->height() + 1; 257 int y = owner_->height() + 1;
252 canvas->FillRect(gfx::Rect(kLeftPadding, y, owner_->width(), 258 canvas->FillRect(gfx::Rect(kLeftPadding, y, owner_->width(),
253 kBottomLineHeight), kBorderDarkColor); 259 kBottomLineHeight), kBorderDarkColor);
254 260
255 if (!Shell::GetInstance()->shelf()->IsVisible()) 261 if (!Shell::GetInstance()->shelf()->IsVisible())
256 return; 262 return;
257 263
258 // Draw the arrow. 264 // Draw the arrow.
259 int left_base_x = base::i18n::IsRTL() ? kArrowWidth : 265 if (arrow_type_ == ARROW_TYPE_BOTTOM) {
260 owner_->width() - kArrowPaddingFromRight - kArrowWidth; 266 int left_base_x = base::i18n::IsRTL() ? kArrowWidth :
261 int left_base_y = y; 267 owner_->width() - kArrowPaddingFromRight - kArrowWidth;
262 int tip_x = left_base_x + kArrowWidth / 2; 268 int left_base_y = y;
263 int tip_y = left_base_y + kArrowHeight; 269 int tip_x = left_base_x + kArrowWidth / 2;
264 SkPath path; 270 int tip_y = left_base_y + kArrowHeight;
265 path.incReserve(4); 271 SkPath path;
266 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); 272 path.incReserve(4);
267 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); 273 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y));
268 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), 274 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y));
269 SkIntToScalar(left_base_y)); 275 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth),
276 SkIntToScalar(left_base_y));
270 277
271 SkPaint paint; 278 SkPaint paint;
272 paint.setStyle(SkPaint::kFill_Style); 279 paint.setStyle(SkPaint::kFill_Style);
273 paint.setColor(kBackgroundColor); 280 paint.setColor(kBackgroundColor);
274 canvas->DrawPath(path, paint); 281 canvas->DrawPath(path, paint);
275 282
276 // Now draw the arrow border. 283 // Now draw the arrow border.
277 paint.setStyle(SkPaint::kStroke_Style); 284 paint.setStyle(SkPaint::kStroke_Style);
278 paint.setColor(kBorderDarkColor); 285 paint.setColor(kBorderDarkColor);
279 canvas->DrawPath(path, paint); 286 canvas->DrawPath(path, paint);
287 }
280 } 288 }
281 289
282 views::View* owner_; 290 views::View* owner_;
291 ArrowType arrow_type_;
283 292
284 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBorder); 293 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBorder);
285 }; 294 };
286 295
287 } // namespace 296 } // namespace
288 297
289 namespace internal { 298 namespace internal {
290 299
291 class SystemTrayBackground : public views::Background { 300 class SystemTrayBackground : public views::Background {
292 public: 301 public:
(...skipping 27 matching lines...) Expand all
320 public: 329 public:
321 SystemTrayBubbleView(views::View* anchor, 330 SystemTrayBubbleView(views::View* anchor,
322 SystemTrayBubble* host, 331 SystemTrayBubble* host,
323 bool can_activate); 332 bool can_activate);
324 virtual ~SystemTrayBubbleView(); 333 virtual ~SystemTrayBubbleView();
325 334
326 void SetBubbleBorder(views::BubbleBorder* border) { 335 void SetBubbleBorder(views::BubbleBorder* border) {
327 GetBubbleFrameView()->SetBubbleBorder(border); 336 GetBubbleFrameView()->SetBubbleBorder(border);
328 } 337 }
329 338
339 void UpdateAnchor() {
340 SizeToContents();
341 GetWidget()->GetRootView()->SchedulePaint();
342 }
343
330 // Called when the host is destroyed. 344 // Called when the host is destroyed.
331 void reset_host() { host_ = NULL; } 345 void reset_host() { host_ = NULL; }
332 346
333 private: 347 private:
334 // Overridden from views::BubbleDelegateView. 348 // Overridden from views::BubbleDelegateView.
335 virtual void Init() OVERRIDE; 349 virtual void Init() OVERRIDE;
336 virtual gfx::Rect GetAnchorRect() OVERRIDE; 350 virtual gfx::Rect GetAnchorRect() OVERRIDE;
337 // Overridden from views::View. 351 // Overridden from views::View.
338 virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; 352 virtual void ChildPreferredSizeChanged(View* child) OVERRIDE;
339 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; 353 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
340 virtual bool CanActivate() const OVERRIDE; 354 virtual bool CanActivate() const OVERRIDE;
341 virtual gfx::Size GetPreferredSize() OVERRIDE; 355 virtual gfx::Size GetPreferredSize() OVERRIDE;
342 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE; 356 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE;
343 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE; 357 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE;
344 358
345 SystemTrayBubble* host_; 359 SystemTrayBubble* host_;
346 bool can_activate_; 360 bool can_activate_;
347 361
348 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleView); 362 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleView);
349 }; 363 };
350 364
351 class SystemTrayBubble : public base::MessagePumpObserver, 365 class SystemTrayBubble : public base::MessagePumpObserver,
352 public views::Widget::Observer { 366 public views::Widget::Observer {
353 public: 367 public:
368 enum BubbleType {
369 BUBBLE_TYPE_DEFAULT,
370 BUBBLE_TYPE_DETAILED,
371 BUBBLE_TYPE_NOTIFICATION
372 };
373
374 enum AnchorType {
375 ANCHOR_TYPE_TRAY,
376 ANCHOR_TYPE_BUBBLE
377 };
378
354 SystemTrayBubble(ash::SystemTray* tray, 379 SystemTrayBubble(ash::SystemTray* tray,
355 const std::vector<ash::SystemTrayItem*>& items, 380 const std::vector<ash::SystemTrayItem*>& items,
356 bool detailed); 381 BubbleType bubble_type);
357 virtual ~SystemTrayBubble(); 382 virtual ~SystemTrayBubble();
358 383
359 // Creates |bubble_view_| and a child views for each member of |items_|. 384 // Creates |bubble_view_| and a child views for each member of |items_|.
360 // Also creates |bubble_widget_| and sets up animations. 385 // Also creates |bubble_widget_| and sets up animations.
361 void InitView(views::View* anchor, 386 void InitView(views::View* anchor,
387 AnchorType anchor_type,
362 bool can_activate, 388 bool can_activate,
363 ash::user::LoginStatus login_status); 389 ash::user::LoginStatus login_status);
364 390
365 bool detailed() const { return detailed_; } 391 gfx::Rect GetAnchorRect() const;
392
393 BubbleType bubble_type() const { return bubble_type_; }
394 SystemTrayBubbleView* bubble_view() const { return bubble_view_; }
366 395
367 void DestroyItemViews(); 396 void DestroyItemViews();
368 views::Widget* GetTrayWidget() const;
369 void StartAutoCloseTimer(int seconds); 397 void StartAutoCloseTimer(int seconds);
370 void StopAutoCloseTimer(); 398 void StopAutoCloseTimer();
371 void RestartAutoCloseTimer(); 399 void RestartAutoCloseTimer();
372 void Close(); 400 void Close();
373 401
374 private: 402 private:
375 // Overridden from base::MessagePumpObserver. 403 // Overridden from base::MessagePumpObserver.
376 virtual base::EventStatus WillProcessEvent( 404 virtual base::EventStatus WillProcessEvent(
377 const base::NativeEvent& event) OVERRIDE; 405 const base::NativeEvent& event) OVERRIDE;
378 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE; 406 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
379 // Overridden from views::Widget::Observer. 407 // Overridden from views::Widget::Observer.
380 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; 408 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE;
381 virtual void OnWidgetVisibilityChanged(views::Widget* widget, 409 virtual void OnWidgetVisibilityChanged(views::Widget* widget,
382 bool visible) OVERRIDE; 410 bool visible) OVERRIDE;
383 411
384 ash::SystemTray* tray_; 412 ash::SystemTray* tray_;
385 SystemTrayBubbleView* bubble_view_; 413 SystemTrayBubbleView* bubble_view_;
386 views::Widget* bubble_widget_; 414 views::Widget* bubble_widget_;
387 std::vector<ash::SystemTrayItem*> items_; 415 std::vector<ash::SystemTrayItem*> items_;
388 bool detailed_; 416 BubbleType bubble_type_;
417 AnchorType anchor_type_;
389 418
390 int autoclose_delay_; 419 int autoclose_delay_;
391 base::OneShotTimer<SystemTrayBubble> autoclose_; 420 base::OneShotTimer<SystemTrayBubble> autoclose_;
392 421
393 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubble); 422 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubble);
394 }; 423 };
395 424
396 // SystemTrayBubbleView 425 // SystemTrayBubbleView
397 426
398 SystemTrayBubbleView::SystemTrayBubbleView(views::View* anchor, 427 SystemTrayBubbleView::SystemTrayBubbleView(views::View* anchor,
(...skipping 13 matching lines...) Expand all
412 if (host_) 441 if (host_)
413 host_->DestroyItemViews(); 442 host_->DestroyItemViews();
414 } 443 }
415 444
416 void SystemTrayBubbleView::Init() { 445 void SystemTrayBubbleView::Init() {
417 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 1, 1, 1)); 446 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 1, 1, 1));
418 set_background(new SystemTrayBubbleBackground(this)); 447 set_background(new SystemTrayBubbleBackground(this));
419 } 448 }
420 449
421 gfx::Rect SystemTrayBubbleView::GetAnchorRect() { 450 gfx::Rect SystemTrayBubbleView::GetAnchorRect() {
422 if (host_) { 451 gfx::Rect rect;
423 views::Widget* widget = host_->GetTrayWidget(); 452 if (host_)
424 if (widget->IsVisible()) { 453 rect = host_->GetAnchorRect();
425 gfx::Rect rect = widget->GetWindowScreenBounds(); 454 if (rect.IsEmpty()) {
426 rect.Inset( 455 rect = gfx::Screen::GetPrimaryMonitor().bounds();
427 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : 0, 0, 456 rect = gfx::Rect(base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen :
428 base::i18n::IsRTL() ? 0 : kPaddingFromRightEdgeOfScreen, 457 rect.width() - kPaddingFromRightEdgeOfScreen,
429 kPaddingFromBottomOfScreen); 458 rect.height() - kPaddingFromBottomOfScreen,
430 return rect; 459 0, 0);
431 }
432 } 460 }
433 gfx::Rect rect = gfx::Screen::GetPrimaryMonitor().bounds(); 461 return rect;
434 return gfx::Rect(base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen :
435 rect.width() - kPaddingFromRightEdgeOfScreen,
436 rect.height() - kPaddingFromBottomOfScreen,
437 0, 0);
438 } 462 }
439 463
440 void SystemTrayBubbleView::ChildPreferredSizeChanged(View* child) { 464 void SystemTrayBubbleView::ChildPreferredSizeChanged(View* child) {
441 SizeToContents(); 465 SizeToContents();
442 } 466 }
443 467
444 void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { 468 void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) {
445 if (can_activate_) { 469 if (can_activate_) {
446 state->role = ui::AccessibilityTypes::ROLE_WINDOW; 470 state->role = ui::AccessibilityTypes::ROLE_WINDOW;
447 state->name = l10n_util::GetStringUTF16( 471 state->name = l10n_util::GetStringUTF16(
(...skipping 18 matching lines...) Expand all
466 void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) { 490 void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) {
467 if (host_) 491 if (host_)
468 host_->RestartAutoCloseTimer(); 492 host_->RestartAutoCloseTimer();
469 } 493 }
470 494
471 // SystemTrayBubble 495 // SystemTrayBubble
472 496
473 SystemTrayBubble::SystemTrayBubble( 497 SystemTrayBubble::SystemTrayBubble(
474 ash::SystemTray* tray, 498 ash::SystemTray* tray,
475 const std::vector<ash::SystemTrayItem*>& items, 499 const std::vector<ash::SystemTrayItem*>& items,
476 bool detailed) 500 BubbleType bubble_type)
477 : tray_(tray), 501 : tray_(tray),
478 bubble_view_(NULL), 502 bubble_view_(NULL),
479 bubble_widget_(NULL), 503 bubble_widget_(NULL),
480 items_(items), 504 items_(items),
481 detailed_(detailed), 505 bubble_type_(bubble_type),
506 anchor_type_(ANCHOR_TYPE_TRAY),
482 autoclose_delay_(0) { 507 autoclose_delay_(0) {
483 } 508 }
484 509
485 SystemTrayBubble::~SystemTrayBubble() { 510 SystemTrayBubble::~SystemTrayBubble() {
486 // The bubble may be closing without having been hidden first. So it may still 511 // The bubble may be closing without having been hidden first. So it may still
487 // be in the message-loop's observer list. 512 // be in the message-loop's observer list.
488 MessageLoopForUI::current()->RemoveObserver(this); 513 MessageLoopForUI::current()->RemoveObserver(this);
489 514
490 DestroyItemViews(); 515 DestroyItemViews();
491 // Reset the host pointer in bubble_view_ in case its destruction is deferred. 516 // Reset the host pointer in bubble_view_ in case its destruction is deferred.
492 if (bubble_view_) 517 if (bubble_view_)
493 bubble_view_->reset_host(); 518 bubble_view_->reset_host();
494 if (bubble_widget_) { 519 if (bubble_widget_) {
495 bubble_widget_->RemoveObserver(this); 520 bubble_widget_->RemoveObserver(this);
496 // This triggers the destruction of bubble_view_. 521 // This triggers the destruction of bubble_view_.
497 bubble_widget_->Close(); 522 bubble_widget_->Close();
498 } 523 }
499 } 524 }
500 525
501 void SystemTrayBubble::InitView(views::View* anchor, 526 void SystemTrayBubble::InitView(views::View* anchor,
527 AnchorType anchor_type,
502 bool can_activate, 528 bool can_activate,
503 ash::user::LoginStatus login_status) { 529 ash::user::LoginStatus login_status) {
504 DCHECK(bubble_view_ == NULL); 530 DCHECK(bubble_view_ == NULL);
531 anchor_type_ = anchor_type;
505 bubble_view_ = new SystemTrayBubbleView(anchor, this, can_activate); 532 bubble_view_ = new SystemTrayBubbleView(anchor, this, can_activate);
506 533
507 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); 534 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin();
508 it != items_.end(); 535 it != items_.end();
509 ++it) { 536 ++it) {
510 views::View* view = detailed_ ? 537 views::View* view = NULL;
511 (*it)->CreateDetailedView(login_status) : 538 switch (bubble_type_) {
512 (*it)->CreateDefaultView(login_status); 539 case BUBBLE_TYPE_DEFAULT:
540 view = (*it)->CreateDefaultView(login_status);
541 break;
542 case BUBBLE_TYPE_DETAILED:
543 view = (*it)->CreateDetailedView(login_status);
544 break;
545 case BUBBLE_TYPE_NOTIFICATION:
546 view = (*it)->CreateNotificationView(login_status);
547 break;
548 }
513 if (view) 549 if (view)
514 bubble_view_->AddChildView(new TrayPopupItemContainer(view)); 550 bubble_view_->AddChildView(new TrayPopupItemContainer(view));
515 } 551 }
516 552
517 DCHECK(bubble_widget_ == NULL); 553 DCHECK(bubble_widget_ == NULL);
518 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); 554 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_);
519 555
520 // Must occur after call to CreateBubble() 556 // Must occur after call to CreateBubble()
521 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); 557 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
522 bubble_widget_->non_client_view()->frame_view()->set_background(NULL); 558 bubble_widget_->non_client_view()->frame_view()->set_background(NULL);
523 bubble_view_->SetBubbleBorder(new SystemTrayBubbleBorder(bubble_view_)); 559 SystemTrayBubbleBorder::ArrowType arrow_type;
560 if (anchor_type_ == ANCHOR_TYPE_TRAY)
561 arrow_type = SystemTrayBubbleBorder::ARROW_TYPE_BOTTOM;
562 else
563 arrow_type = SystemTrayBubbleBorder::ARROW_TYPE_NONE;
564 bubble_view_->SetBubbleBorder(
565 new SystemTrayBubbleBorder(bubble_view_, arrow_type));
524 566
525 bubble_widget_->AddObserver(this); 567 bubble_widget_->AddObserver(this);
526 568
527 // Setup animation. 569 // Setup animation.
528 ash::SetWindowVisibilityAnimationType( 570 ash::SetWindowVisibilityAnimationType(
529 bubble_widget_->GetNativeWindow(), 571 bubble_widget_->GetNativeWindow(),
530 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); 572 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
531 ash::SetWindowVisibilityAnimationTransition( 573 ash::SetWindowVisibilityAnimationTransition(
532 bubble_widget_->GetNativeWindow(), 574 bubble_widget_->GetNativeWindow(),
533 ash::ANIMATE_BOTH); 575 ash::ANIMATE_BOTH);
534 ash::SetWindowVisibilityAnimationDuration( 576 ash::SetWindowVisibilityAnimationDuration(
535 bubble_widget_->GetNativeWindow(), 577 bubble_widget_->GetNativeWindow(),
536 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); 578 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS));
537 579
538 bubble_view_->Show(); 580 bubble_view_->Show();
539 } 581 }
540 582
583 gfx::Rect SystemTrayBubble::GetAnchorRect() const {
584 gfx::Rect rect;
585 views::Widget* widget = bubble_view()->anchor_widget();
586 if (widget->IsVisible()) {
587 rect = widget->GetWindowScreenBounds();
588 if (anchor_type_ == ANCHOR_TYPE_TRAY) {
589 rect.Inset(
590 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : 0,
591 0,
592 base::i18n::IsRTL() ? 0 : kPaddingFromRightEdgeOfScreen,
593 kPaddingFromBottomOfScreen);
594 } else if (anchor_type_ == ANCHOR_TYPE_BUBBLE) {
595 rect.Inset(
596 base::i18n::IsRTL() ? kShadowThickness - 1 : 0,
597 0,
598 base::i18n::IsRTL() ? 0 : kShadowThickness - 1,
599 0);
600 }
601 }
602 return rect;
603 }
604
541 void SystemTrayBubble::DestroyItemViews() { 605 void SystemTrayBubble::DestroyItemViews() {
542 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); 606 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin();
543 it != items_.end(); 607 it != items_.end();
544 ++it) { 608 ++it) {
545 if (detailed_) 609 switch (bubble_type_) {
546 (*it)->DestroyDetailedView(); 610 case BUBBLE_TYPE_DEFAULT:
547 else 611 (*it)->DestroyDefaultView();
548 (*it)->DestroyDefaultView(); 612 break;
613 case BUBBLE_TYPE_DETAILED:
614 (*it)->DestroyDetailedView();
615 break;
616 case BUBBLE_TYPE_NOTIFICATION:
617 (*it)->DestroyNotificationView();
618 break;
619 }
549 } 620 }
550 } 621 }
551 622
552 views::Widget* SystemTrayBubble::GetTrayWidget() const {
553 return tray_->GetWidget();
554 }
555
556 void SystemTrayBubble::StartAutoCloseTimer(int seconds) { 623 void SystemTrayBubble::StartAutoCloseTimer(int seconds) {
557 autoclose_.Stop(); 624 autoclose_.Stop();
558 autoclose_delay_ = seconds; 625 autoclose_delay_ = seconds;
559 if (autoclose_delay_) { 626 if (autoclose_delay_) {
560 autoclose_.Start(FROM_HERE, 627 autoclose_.Start(FROM_HERE,
561 base::TimeDelta::FromSeconds(autoclose_delay_), 628 base::TimeDelta::FromSeconds(autoclose_delay_),
562 this, &SystemTrayBubble::Close); 629 this, &SystemTrayBubble::Close);
563 } 630 }
564 } 631 }
565 632
566 void SystemTrayBubble::StopAutoCloseTimer() { 633 void SystemTrayBubble::StopAutoCloseTimer() {
567 autoclose_.Stop(); 634 autoclose_.Stop();
568 } 635 }
569 636
570 void SystemTrayBubble::RestartAutoCloseTimer() { 637 void SystemTrayBubble::RestartAutoCloseTimer() {
571 if (autoclose_delay_) 638 if (autoclose_delay_)
572 StartAutoCloseTimer(autoclose_delay_); 639 StartAutoCloseTimer(autoclose_delay_);
573 } 640 }
574 641
575 void SystemTrayBubble::Close() { 642 void SystemTrayBubble::Close() {
576 if (bubble_widget_) 643 if (bubble_widget_)
577 bubble_widget_->Close(); 644 bubble_widget_->Close();
578 } 645 }
579 646
580 base::EventStatus SystemTrayBubble::WillProcessEvent( 647 base::EventStatus SystemTrayBubble::WillProcessEvent(
581 const base::NativeEvent& event) { 648 const base::NativeEvent& event) {
582 // Check if the user clicked outside of the bubble and close it if they did. 649 // Check if the user clicked outside of the bubble and close it if they did.
583 if (ui::EventTypeFromNative(event) == ui::ET_MOUSE_PRESSED) { 650 if (bubble_type_ != BUBBLE_TYPE_NOTIFICATION &&
651 ui::EventTypeFromNative(event) == ui::ET_MOUSE_PRESSED) {
584 gfx::Point cursor_in_view = ui::EventLocationFromNative(event); 652 gfx::Point cursor_in_view = ui::EventLocationFromNative(event);
585 views::View::ConvertPointFromScreen(bubble_view_, &cursor_in_view); 653 views::View::ConvertPointFromScreen(bubble_view_, &cursor_in_view);
586 if (!bubble_view_->HitTest(cursor_in_view)) { 654 if (!bubble_view_->HitTest(cursor_in_view)) {
587 bubble_widget_->Close(); 655 bubble_widget_->Close();
588 } 656 }
589 } 657 }
590 return base::EVENT_CONTINUE; 658 return base::EVENT_CONTINUE;
591 } 659 }
592 660
593 void SystemTrayBubble::DidProcessEvent(const base::NativeEvent& event) { 661 void SystemTrayBubble::DidProcessEvent(const base::NativeEvent& event) {
594 } 662 }
595 663
596 void SystemTrayBubble::OnWidgetClosing(views::Widget* widget) { 664 void SystemTrayBubble::OnWidgetClosing(views::Widget* widget) {
597 CHECK_EQ(bubble_widget_, widget); 665 CHECK_EQ(bubble_widget_, widget);
598 MessageLoopForUI::current()->RemoveObserver(this); 666 MessageLoopForUI::current()->RemoveObserver(this);
599 bubble_widget_ = NULL; 667 bubble_widget_ = NULL;
600 tray_->RemoveBubble(this); 668 tray_->RemoveBubble(this);
601 } 669 }
602 670
603 void SystemTrayBubble::OnWidgetVisibilityChanged(views::Widget* widget, 671 void SystemTrayBubble::OnWidgetVisibilityChanged(views::Widget* widget,
604 bool visible) { 672 bool visible) {
605 if (!visible) 673 if (!visible)
606 MessageLoopForUI::current()->RemoveObserver(this); 674 MessageLoopForUI::current()->RemoveObserver(this);
607 else 675 else
608 MessageLoopForUI::current()->AddObserver(this); 676 MessageLoopForUI::current()->AddObserver(this);
609 } 677 }
610 678
679 // Observe the tray layer animation and update the anchor when it changes.
680 // TODO(stevenjb): Observe or mirror the actual animation, not just the start
681 // and end points.
682 class SystemTrayLayerAnimationObserver : public ui::LayerAnimationObserver {
683 public:
684 explicit SystemTrayLayerAnimationObserver(SystemTray* host) : host_(host) {}
685
686 virtual void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) {
687 host_->UpdateNotificationAnchor();
688 }
689
690 virtual void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) {
691 host_->UpdateNotificationAnchor();
692 }
693
694 virtual void OnLayerAnimationScheduled(ui::LayerAnimationSequence* sequence) {
695 host_->UpdateNotificationAnchor();
696 }
697
698 private:
699 SystemTray* host_;
700
701 DISALLOW_COPY_AND_ASSIGN(SystemTrayLayerAnimationObserver);
702 };
703
611 } // namespace internal 704 } // namespace internal
612 705
613 // SystemTray 706 // SystemTray
614 707
708 using internal::SystemTrayBubble;
709 using internal::SystemTrayLayerAnimationObserver;
710
615 SystemTray::SystemTray() 711 SystemTray::SystemTray()
616 : items_(), 712 : items_(),
617 accessibility_observer_(NULL), 713 accessibility_observer_(NULL),
618 audio_observer_(NULL), 714 audio_observer_(NULL),
619 bluetooth_observer_(NULL), 715 bluetooth_observer_(NULL),
620 brightness_observer_(NULL), 716 brightness_observer_(NULL),
621 caps_lock_observer_(NULL), 717 caps_lock_observer_(NULL),
622 clock_observer_(NULL), 718 clock_observer_(NULL),
623 drive_observer_(NULL), 719 drive_observer_(NULL),
624 ime_observer_(NULL), 720 ime_observer_(NULL),
625 network_observer_(NULL), 721 network_observer_(NULL),
626 power_status_observer_(NULL), 722 power_status_observer_(NULL),
627 update_observer_(NULL), 723 update_observer_(NULL),
628 user_observer_(NULL), 724 user_observer_(NULL),
629 widget_(NULL), 725 widget_(NULL),
630 background_(new internal::SystemTrayBackground), 726 background_(new internal::SystemTrayBackground),
631 should_show_launcher_(false), 727 should_show_launcher_(false),
632 ALLOW_THIS_IN_INITIALIZER_LIST(hide_background_animator_(this, 728 ALLOW_THIS_IN_INITIALIZER_LIST(hide_background_animator_(this,
633 0, kTrayBackgroundAlpha)), 729 0, kTrayBackgroundAlpha)),
634 ALLOW_THIS_IN_INITIALIZER_LIST(hover_background_animator_(this, 730 ALLOW_THIS_IN_INITIALIZER_LIST(hover_background_animator_(this,
635 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha)) { 731 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha)) {
636 container_ = new views::View; 732 tray_container_ = new views::View;
637 container_->SetLayoutManager(new views::BoxLayout( 733 tray_container_->SetLayoutManager(new views::BoxLayout(
638 views::BoxLayout::kHorizontal, 0, 0, 0)); 734 views::BoxLayout::kHorizontal, 0, 0, 0));
639 container_->set_background(background_); 735 tray_container_->set_background(background_);
640 container_->set_border( 736 tray_container_->set_border(
641 views::Border::CreateEmptyBorder(1, 1, 1, 1)); 737 views::Border::CreateEmptyBorder(1, 1, 1, 1));
642 set_border(views::Border::CreateEmptyBorder(0, 0, 738 set_border(views::Border::CreateEmptyBorder(0, 0,
643 kPaddingFromBottomOfScreen, kPaddingFromRightEdgeOfScreen)); 739 kPaddingFromBottomOfScreen, kPaddingFromRightEdgeOfScreen));
644 set_notify_enter_exit_on_child(true); 740 set_notify_enter_exit_on_child(true);
645 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); 741 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
646 AddChildView(container_); 742 AddChildView(tray_container_);
647 743
648 // Initially we want to paint the background, but without the hover effect. 744 // Initially we want to paint the background, but without the hover effect.
649 SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE); 745 SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE);
650 hover_background_animator_.SetPaintsBackground(false, 746 hover_background_animator_.SetPaintsBackground(false,
651 internal::BackgroundAnimator::CHANGE_IMMEDIATE); 747 internal::BackgroundAnimator::CHANGE_IMMEDIATE);
652 } 748 }
653 749
654 SystemTray::~SystemTray() { 750 SystemTray::~SystemTray() {
655 bubble_.reset(); 751 bubble_.reset();
656 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); 752 for (std::vector<SystemTrayItem*>::iterator it = items_.begin();
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 params.delegate = status_area_view; 814 params.delegate = status_area_view;
719 params.parent = Shell::GetInstance()->GetContainer( 815 params.parent = Shell::GetInstance()->GetContainer(
720 ash::internal::kShellWindowId_StatusContainer); 816 ash::internal::kShellWindowId_StatusContainer);
721 params.transparent = true; 817 params.transparent = true;
722 widget_->Init(params); 818 widget_->Init(params);
723 widget_->set_focus_on_creation(false); 819 widget_->set_focus_on_creation(false);
724 status_area_view->AddChildView(this); 820 status_area_view->AddChildView(this);
725 widget_->SetContentsView(status_area_view); 821 widget_->SetContentsView(status_area_view);
726 widget_->Show(); 822 widget_->Show();
727 widget_->GetNativeView()->SetName("StatusTrayWidget"); 823 widget_->GetNativeView()->SetName("StatusTrayWidget");
824
825 layer_animation_observer_.reset(new SystemTrayLayerAnimationObserver(this));
826 widget_->GetNativeView()->layer()->GetAnimator()->AddObserver(
827 layer_animation_observer_.get());
728 } 828 }
729 829
730 void SystemTray::AddTrayItem(SystemTrayItem* item) { 830 void SystemTray::AddTrayItem(SystemTrayItem* item) {
731 items_.push_back(item); 831 items_.push_back(item);
732 832
733 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); 833 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
734 views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus()); 834 views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus());
735 if (tray_item) { 835 if (tray_item) {
736 container_->AddChildViewAt(tray_item, 0); 836 tray_container_->AddChildViewAt(tray_item, 0);
737 PreferredSizeChanged(); 837 PreferredSizeChanged();
738 } 838 }
739 } 839 }
740 840
741 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { 841 void SystemTray::RemoveTrayItem(SystemTrayItem* item) {
742 NOTIMPLEMENTED(); 842 NOTIMPLEMENTED();
743 } 843 }
744 844
745 void SystemTray::ShowDefaultView() { 845 void SystemTray::ShowDefaultView() {
746 ShowItems(items_.get(), false, true); 846 ShowItems(items_.get(), false, true);
747 } 847 }
748 848
749 void SystemTray::ShowDetailedView(SystemTrayItem* item, 849 void SystemTray::ShowDetailedView(SystemTrayItem* item,
750 int close_delay, 850 int close_delay,
751 bool activate) { 851 bool activate) {
752 std::vector<SystemTrayItem*> items; 852 std::vector<SystemTrayItem*> items;
753 items.push_back(item); 853 items.push_back(item);
754 ShowItems(items, true, activate); 854 ShowItems(items, true, activate);
755 bubble_->StartAutoCloseTimer(close_delay); 855 bubble_->StartAutoCloseTimer(close_delay);
756 } 856 }
757 857
858 void SystemTray::ShowNotificationView(SystemTrayItem* item) {
859 if (std::find(notification_items_.begin(), notification_items_.end(), item)
860 != notification_items_.end())
861 return;
862 notification_items_.push_back(item);
863 UpdateNotificationBubble();
864 }
865
866 void SystemTray::HideNotificationView(SystemTrayItem* item) {
867 std::vector<SystemTrayItem*>::iterator found_iter =
868 std::find(notification_items_.begin(), notification_items_.end(), item);
869 if (found_iter == notification_items_.end())
870 return;
871 notification_items_.erase(found_iter);
872 UpdateNotificationBubble();
873 }
874
758 void SystemTray::SetDetailedViewCloseDelay(int close_delay) { 875 void SystemTray::SetDetailedViewCloseDelay(int close_delay) {
759 if (bubble_.get() && bubble_->detailed()) 876 if (bubble_.get() &&
877 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DETAILED)
760 bubble_->StartAutoCloseTimer(close_delay); 878 bubble_->StartAutoCloseTimer(close_delay);
761 } 879 }
762 880
763 void SystemTray::UpdateAfterLoginStatusChange(user::LoginStatus login_status) { 881 void SystemTray::UpdateAfterLoginStatusChange(user::LoginStatus login_status) {
764 bubble_.reset(); 882 bubble_.reset();
765 883
766 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); 884 for (std::vector<SystemTrayItem*>::iterator it = items_.begin();
767 it != items_.end(); 885 it != items_.end();
768 ++it) { 886 ++it) {
769 (*it)->UpdateAfterLoginStatusChange(login_status); 887 (*it)->UpdateAfterLoginStatusChange(login_status);
770 } 888 }
771 889
772 SetVisible(true); 890 SetVisible(true);
773 PreferredSizeChanged(); 891 PreferredSizeChanged();
774 } 892 }
775 893
776 bool SystemTray::CloseBubbleForTest() const { 894 bool SystemTray::CloseBubbleForTest() const {
777 if (!bubble_.get()) 895 if (!bubble_.get())
778 return false; 896 return false;
779 bubble_->Close(); 897 bubble_->Close();
780 return true; 898 return true;
781 } 899 }
782 900
783 // Private methods. 901 // Private methods.
784 902
785 void SystemTray::RemoveBubble(internal::SystemTrayBubble* bubble) { 903 void SystemTray::RemoveBubble(SystemTrayBubble* bubble) {
786 CHECK_EQ(bubble_.get(), bubble); 904 if (bubble == bubble_.get()) {
787 bubble_.reset(); 905 bubble_.reset();
788 906 UpdateNotificationBubble(); // State changed, re-create notifications.
789 if (should_show_launcher_) { 907 if (should_show_launcher_) {
790 // No need to show the launcher if the mouse isn't over the status area 908 // No need to show the launcher if the mouse isn't over the status area
791 // anymore. 909 // anymore.
792 aura::RootWindow* root = GetWidget()->GetNativeView()->GetRootWindow(); 910 aura::RootWindow* root = GetWidget()->GetNativeView()->GetRootWindow();
793 should_show_launcher_ = GetWidget()->GetWindowScreenBounds().Contains( 911 should_show_launcher_ = GetWidget()->GetWindowScreenBounds().Contains(
794 root->last_mouse_location()); 912 root->last_mouse_location());
795 if (!should_show_launcher_) 913 if (!should_show_launcher_)
796 Shell::GetInstance()->shelf()->UpdateAutoHideState(); 914 Shell::GetInstance()->shelf()->UpdateAutoHideState();
915 }
916 } else if (bubble == notification_bubble_) {
917 notification_bubble_.reset();
918 } else {
919 NOTREACHED();
797 } 920 }
798 } 921 }
799 922
800 void SystemTray::SetPaintsBackground( 923 void SystemTray::SetPaintsBackground(
801 bool value, 924 bool value,
802 internal::BackgroundAnimator::ChangeType change_type) { 925 internal::BackgroundAnimator::ChangeType change_type) {
803 hide_background_animator_.SetPaintsBackground(value, change_type); 926 hide_background_animator_.SetPaintsBackground(value, change_type);
804 } 927 }
805 928
806 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, 929 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
807 bool detailed, 930 bool detailed,
808 bool can_activate) { 931 bool can_activate) {
809 // Destroy any existing bubble and create a new one. 932 // Destroy any existing bubble and create a new one.
810 bubble_.reset(new internal::SystemTrayBubble(this, items, detailed)); 933 SystemTrayBubble::BubbleType bubble_type = detailed ?
934 SystemTrayBubble::BUBBLE_TYPE_DETAILED :
935 SystemTrayBubble::BUBBLE_TYPE_DEFAULT;
936 bubble_.reset(new SystemTrayBubble(this, items, bubble_type));
811 ash::SystemTrayDelegate* delegate = 937 ash::SystemTrayDelegate* delegate =
812 ash::Shell::GetInstance()->tray_delegate(); 938 ash::Shell::GetInstance()->tray_delegate();
813 bubble_->InitView(container_, can_activate, delegate->GetUserLoginStatus()); 939 views::View* anchor = tray_container_;
940 bubble_->InitView(anchor, SystemTrayBubble::ANCHOR_TYPE_TRAY,
941 can_activate, delegate->GetUserLoginStatus());
814 // If we have focus the shelf should be visible and we need to continue 942 // If we have focus the shelf should be visible and we need to continue
815 // showing the shelf when the popup is shown. 943 // showing the shelf when the popup is shown.
816 if (GetWidget()->IsActive()) 944 if (GetWidget()->IsActive())
817 should_show_launcher_ = true; 945 should_show_launcher_ = true;
946 UpdateNotificationBubble(); // State changed, re-create notifications.
947 }
948
949 void SystemTray::UpdateNotificationBubble() {
950 // Only show the notification buble if we have notifications and we are not
951 // showing the default bubble.
952 if (notification_items_.empty() ||
953 (bubble_.get() &&
954 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) {
955 notification_bubble_.reset();
956 return;
957 }
958 notification_bubble_.reset(
959 new SystemTrayBubble(this, notification_items_,
960 SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
961 views::View* anchor;
962 SystemTrayBubble::AnchorType anchor_type;
963 if (bubble_.get()) {
964 anchor = bubble_->bubble_view();
965 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE;
966 } else {
967 anchor = tray_container_;
968 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY;
969 }
970 notification_bubble_->InitView(
971 anchor, anchor_type,
972 false /* can_activate */,
973 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus());
974 }
975
976 void SystemTray::UpdateNotificationAnchor() {
977 if (!notification_bubble_.get())
978 return;
979 notification_bubble_->bubble_view()->UpdateAnchor();
980 // Ensure that the notification buble is above the launcher/status area.
981 notification_bubble_->bubble_view()->GetWidget()->StackAtTop();
818 } 982 }
819 983
820 bool SystemTray::PerformAction(const views::Event& event) { 984 bool SystemTray::PerformAction(const views::Event& event) {
821 // If we're already showing the default view, hide it; otherwise, show it 985 // If we're already showing the default view, hide it; otherwise, show it
822 // (and hide any popup that's currently shown). 986 // (and hide any popup that's currently shown).
823 if (bubble_.get() && !bubble_->detailed()) 987 if (bubble_.get() &&
988 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) {
824 bubble_->Close(); 989 bubble_->Close();
825 else 990 } else {
826 ShowDefaultView(); 991 ShowDefaultView();
992 }
827 return true; 993 return true;
828 } 994 }
829 995
830 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { 996 void SystemTray::OnMouseEntered(const views::MouseEvent& event) {
831 should_show_launcher_ = true; 997 should_show_launcher_ = true;
832 hover_background_animator_.SetPaintsBackground(true, 998 hover_background_animator_.SetPaintsBackground(true,
833 internal::BackgroundAnimator::CHANGE_ANIMATE); 999 internal::BackgroundAnimator::CHANGE_ANIMATE);
834 } 1000 }
835 1001
836 void SystemTray::OnMouseExited(const views::MouseEvent& event) { 1002 void SystemTray::OnMouseExited(const views::MouseEvent& event) {
(...skipping 14 matching lines...) Expand all
851 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; 1017 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
852 state->name = l10n_util::GetStringUTF16( 1018 state->name = l10n_util::GetStringUTF16(
853 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); 1019 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME);
854 } 1020 }
855 1021
856 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { 1022 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) {
857 // The tray itself expands to the right and bottom edge of the screen to make 1023 // The tray itself expands to the right and bottom edge of the screen to make
858 // sure clicking on the edges brings up the popup. However, the focus border 1024 // sure clicking on the edges brings up the popup. However, the focus border
859 // should be only around the container. 1025 // should be only around the container.
860 if (GetWidget() && GetWidget()->IsActive()) 1026 if (GetWidget() && GetWidget()->IsActive())
861 canvas->DrawFocusRect(container_->bounds()); 1027 canvas->DrawFocusRect(tray_container_->bounds());
862 } 1028 }
863 1029
864 void SystemTray::UpdateBackground(int alpha) { 1030 void SystemTray::UpdateBackground(int alpha) {
865 background_->set_alpha(hide_background_animator_.alpha() + 1031 background_->set_alpha(hide_background_animator_.alpha() +
866 hover_background_animator_.alpha()); 1032 hover_background_animator_.alpha());
867 SchedulePaint(); 1033 SchedulePaint();
868 } 1034 }
869 1035
870 } // namespace ash 1036 } // namespace ash
OLDNEW
« no previous file with comments | « ash/system/tray/system_tray.h ('k') | ash/system/tray/system_tray_item.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698