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

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: Rebase 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_;
418 views::View* anchor_;
389 419
390 int autoclose_delay_; 420 int autoclose_delay_;
391 base::OneShotTimer<SystemTrayBubble> autoclose_; 421 base::OneShotTimer<SystemTrayBubble> autoclose_;
392 422
393 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubble); 423 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubble);
394 }; 424 };
395 425
396 // SystemTrayBubbleView 426 // SystemTrayBubbleView
397 427
398 SystemTrayBubbleView::SystemTrayBubbleView(views::View* anchor, 428 SystemTrayBubbleView::SystemTrayBubbleView(views::View* anchor,
(...skipping 13 matching lines...) Expand all
412 if (host_) 442 if (host_)
413 host_->DestroyItemViews(); 443 host_->DestroyItemViews();
414 } 444 }
415 445
416 void SystemTrayBubbleView::Init() { 446 void SystemTrayBubbleView::Init() {
417 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 1, 1, 1)); 447 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 1, 1, 1));
418 set_background(new SystemTrayBubbleBackground(this)); 448 set_background(new SystemTrayBubbleBackground(this));
419 } 449 }
420 450
421 gfx::Rect SystemTrayBubbleView::GetAnchorRect() { 451 gfx::Rect SystemTrayBubbleView::GetAnchorRect() {
422 if (host_) { 452 gfx::Rect rect;
423 views::Widget* widget = host_->GetTrayWidget(); 453 if (host_)
424 if (widget->IsVisible()) { 454 rect = host_->GetAnchorRect();
425 gfx::Rect rect = widget->GetWindowScreenBounds(); 455 if (rect.IsEmpty()) {
426 rect.Inset( 456 rect = gfx::Screen::GetPrimaryMonitor().bounds();
427 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : 0, 0, 457 rect = gfx::Rect(base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen :
428 base::i18n::IsRTL() ? 0 : kPaddingFromRightEdgeOfScreen, 458 rect.width() - kPaddingFromRightEdgeOfScreen,
429 kPaddingFromBottomOfScreen); 459 rect.height() - kPaddingFromBottomOfScreen,
430 return rect; 460 0, 0);
431 }
432 } 461 }
433 gfx::Rect rect = gfx::Screen::GetPrimaryMonitor().bounds(); 462 return rect;
434 return gfx::Rect(base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen :
435 rect.width() - kPaddingFromRightEdgeOfScreen,
436 rect.height() - kPaddingFromBottomOfScreen,
437 0, 0);
438 } 463 }
439 464
440 void SystemTrayBubbleView::ChildPreferredSizeChanged(View* child) { 465 void SystemTrayBubbleView::ChildPreferredSizeChanged(View* child) {
441 SizeToContents(); 466 SizeToContents();
442 } 467 }
443 468
444 void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { 469 void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) {
445 if (can_activate_) { 470 if (can_activate_) {
446 state->role = ui::AccessibilityTypes::ROLE_WINDOW; 471 state->role = ui::AccessibilityTypes::ROLE_WINDOW;
447 state->name = l10n_util::GetStringUTF16( 472 state->name = l10n_util::GetStringUTF16(
(...skipping 18 matching lines...) Expand all
466 void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) { 491 void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) {
467 if (host_) 492 if (host_)
468 host_->RestartAutoCloseTimer(); 493 host_->RestartAutoCloseTimer();
469 } 494 }
470 495
471 // SystemTrayBubble 496 // SystemTrayBubble
472 497
473 SystemTrayBubble::SystemTrayBubble( 498 SystemTrayBubble::SystemTrayBubble(
474 ash::SystemTray* tray, 499 ash::SystemTray* tray,
475 const std::vector<ash::SystemTrayItem*>& items, 500 const std::vector<ash::SystemTrayItem*>& items,
476 bool detailed) 501 BubbleType bubble_type)
477 : tray_(tray), 502 : tray_(tray),
478 bubble_view_(NULL), 503 bubble_view_(NULL),
479 bubble_widget_(NULL), 504 bubble_widget_(NULL),
480 items_(items), 505 items_(items),
481 detailed_(detailed), 506 bubble_type_(bubble_type),
507 anchor_type_(ANCHOR_TYPE_TRAY),
508 anchor_(NULL),
482 autoclose_delay_(0) { 509 autoclose_delay_(0) {
483 } 510 }
484 511
485 SystemTrayBubble::~SystemTrayBubble() { 512 SystemTrayBubble::~SystemTrayBubble() {
486 // The bubble may be closing without having been hidden first. So it may still 513 // The bubble may be closing without having been hidden first. So it may still
487 // be in the message-loop's observer list. 514 // be in the message-loop's observer list.
488 MessageLoopForUI::current()->RemoveObserver(this); 515 MessageLoopForUI::current()->RemoveObserver(this);
489 516
490 DestroyItemViews(); 517 DestroyItemViews();
491 // Reset the host pointer in bubble_view_ in case its destruction is deferred. 518 // Reset the host pointer in bubble_view_ in case its destruction is deferred.
492 if (bubble_view_) 519 if (bubble_view_)
493 bubble_view_->reset_host(); 520 bubble_view_->reset_host();
494 if (bubble_widget_) { 521 if (bubble_widget_) {
495 bubble_widget_->RemoveObserver(this); 522 bubble_widget_->RemoveObserver(this);
496 // This triggers the destruction of bubble_view_. 523 // This triggers the destruction of bubble_view_.
497 bubble_widget_->Close(); 524 bubble_widget_->Close();
498 } 525 }
499 } 526 }
500 527
501 void SystemTrayBubble::InitView(views::View* anchor, 528 void SystemTrayBubble::InitView(views::View* anchor,
529 AnchorType anchor_type,
502 bool can_activate, 530 bool can_activate,
503 ash::user::LoginStatus login_status) { 531 ash::user::LoginStatus login_status) {
504 DCHECK(bubble_view_ == NULL); 532 DCHECK(bubble_view_ == NULL);
533 anchor_type_ = anchor_type;
534 anchor_ = anchor;
505 bubble_view_ = new SystemTrayBubbleView(anchor, this, can_activate); 535 bubble_view_ = new SystemTrayBubbleView(anchor, this, can_activate);
506 536
507 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); 537 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin();
508 it != items_.end(); 538 it != items_.end();
509 ++it) { 539 ++it) {
510 views::View* view = detailed_ ? 540 views::View* view = NULL;
511 (*it)->CreateDetailedView(login_status) : 541 switch (bubble_type_) {
512 (*it)->CreateDefaultView(login_status); 542 case BUBBLE_TYPE_DEFAULT:
543 view = (*it)->CreateDefaultView(login_status);
544 break;
545 case BUBBLE_TYPE_DETAILED:
546 view = (*it)->CreateDetailedView(login_status);
547 break;
548 case BUBBLE_TYPE_NOTIFICATION:
549 view = (*it)->CreateNotificationView(login_status);
550 break;
551 }
513 if (view) 552 if (view)
514 bubble_view_->AddChildView(new TrayPopupItemContainer(view)); 553 bubble_view_->AddChildView(new TrayPopupItemContainer(view));
515 } 554 }
516 555
517 DCHECK(bubble_widget_ == NULL); 556 DCHECK(bubble_widget_ == NULL);
518 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); 557 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_);
519 558
520 // Must occur after call to CreateBubble() 559 // Must occur after call to CreateBubble()
521 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); 560 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
522 bubble_widget_->non_client_view()->frame_view()->set_background(NULL); 561 bubble_widget_->non_client_view()->frame_view()->set_background(NULL);
523 bubble_view_->SetBubbleBorder(new SystemTrayBubbleBorder(bubble_view_)); 562 SystemTrayBubbleBorder::ArrowType arrow_type;
563 if (anchor_type_ == ANCHOR_TYPE_TRAY)
564 arrow_type = SystemTrayBubbleBorder::ARROW_TYPE_BOTTOM;
565 else
566 arrow_type = SystemTrayBubbleBorder::ARROW_TYPE_NONE;
567 bubble_view_->SetBubbleBorder(
568 new SystemTrayBubbleBorder(bubble_view_, arrow_type));
524 569
525 bubble_widget_->AddObserver(this); 570 bubble_widget_->AddObserver(this);
526 571
527 // Setup animation. 572 // Setup animation.
528 ash::SetWindowVisibilityAnimationType( 573 ash::SetWindowVisibilityAnimationType(
529 bubble_widget_->GetNativeWindow(), 574 bubble_widget_->GetNativeWindow(),
530 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); 575 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
531 ash::SetWindowVisibilityAnimationTransition( 576 ash::SetWindowVisibilityAnimationTransition(
532 bubble_widget_->GetNativeWindow(), 577 bubble_widget_->GetNativeWindow(),
533 ash::ANIMATE_BOTH); 578 ash::ANIMATE_BOTH);
534 ash::SetWindowVisibilityAnimationDuration( 579 ash::SetWindowVisibilityAnimationDuration(
535 bubble_widget_->GetNativeWindow(), 580 bubble_widget_->GetNativeWindow(),
536 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); 581 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS));
537 582
538 bubble_view_->Show(); 583 bubble_view_->Show();
539 } 584 }
540 585
586 gfx::Rect SystemTrayBubble::GetAnchorRect() const {
587 gfx::Rect rect;
588 views::Widget* widget = anchor_->GetWidget();
sadrul 2012/05/08 19:40:17 I think instead of keeping anchor_ around, you can
stevenjb 2012/05/08 22:49:20 Good call. Done.
589 if (widget->IsVisible()) {
590 rect = widget->GetWindowScreenBounds();
591 if (anchor_type_ == ANCHOR_TYPE_TRAY) {
592 rect.Inset(
593 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : 0,
594 0,
595 base::i18n::IsRTL() ? 0 : kPaddingFromRightEdgeOfScreen,
596 kPaddingFromBottomOfScreen);
597 } else if (anchor_type_ == ANCHOR_TYPE_BUBBLE) {
598 rect.Inset(
599 base::i18n::IsRTL() ? kShadowThickness - 1 : 0,
600 0,
601 base::i18n::IsRTL() ? 0 : kShadowThickness - 1,
602 0);
603 }
604 }
605 return rect;
606 }
607
541 void SystemTrayBubble::DestroyItemViews() { 608 void SystemTrayBubble::DestroyItemViews() {
542 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); 609 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin();
543 it != items_.end(); 610 it != items_.end();
544 ++it) { 611 ++it) {
545 if (detailed_) 612 switch (bubble_type_) {
546 (*it)->DestroyDetailedView(); 613 case BUBBLE_TYPE_DEFAULT:
547 else 614 (*it)->DestroyDefaultView();
548 (*it)->DestroyDefaultView(); 615 break;
616 case BUBBLE_TYPE_DETAILED:
617 (*it)->DestroyDetailedView();
618 break;
619 case BUBBLE_TYPE_NOTIFICATION:
620 (*it)->DestroyNotificationView();
621 break;
622 }
549 } 623 }
550 } 624 }
551 625
552 views::Widget* SystemTrayBubble::GetTrayWidget() const {
553 return tray_->GetWidget();
554 }
555
556 void SystemTrayBubble::StartAutoCloseTimer(int seconds) { 626 void SystemTrayBubble::StartAutoCloseTimer(int seconds) {
557 autoclose_.Stop(); 627 autoclose_.Stop();
558 autoclose_delay_ = seconds; 628 autoclose_delay_ = seconds;
559 if (autoclose_delay_) { 629 if (autoclose_delay_) {
560 autoclose_.Start(FROM_HERE, 630 autoclose_.Start(FROM_HERE,
561 base::TimeDelta::FromSeconds(autoclose_delay_), 631 base::TimeDelta::FromSeconds(autoclose_delay_),
562 this, &SystemTrayBubble::Close); 632 this, &SystemTrayBubble::Close);
563 } 633 }
564 } 634 }
565 635
566 void SystemTrayBubble::StopAutoCloseTimer() { 636 void SystemTrayBubble::StopAutoCloseTimer() {
567 autoclose_.Stop(); 637 autoclose_.Stop();
568 } 638 }
569 639
570 void SystemTrayBubble::RestartAutoCloseTimer() { 640 void SystemTrayBubble::RestartAutoCloseTimer() {
571 if (autoclose_delay_) 641 if (autoclose_delay_)
572 StartAutoCloseTimer(autoclose_delay_); 642 StartAutoCloseTimer(autoclose_delay_);
573 } 643 }
574 644
575 void SystemTrayBubble::Close() { 645 void SystemTrayBubble::Close() {
576 if (bubble_widget_) 646 if (bubble_widget_)
577 bubble_widget_->Close(); 647 bubble_widget_->Close();
578 } 648 }
579 649
580 base::EventStatus SystemTrayBubble::WillProcessEvent( 650 base::EventStatus SystemTrayBubble::WillProcessEvent(
581 const base::NativeEvent& event) { 651 const base::NativeEvent& event) {
582 // Check if the user clicked outside of the bubble and close it if they did. 652 // Check if the user clicked outside of the bubble and close it if they did.
583 if (ui::EventTypeFromNative(event) == ui::ET_MOUSE_PRESSED) { 653 if (bubble_type_ != BUBBLE_TYPE_NOTIFICATION &&
654 ui::EventTypeFromNative(event) == ui::ET_MOUSE_PRESSED) {
584 gfx::Point cursor_in_view = ui::EventLocationFromNative(event); 655 gfx::Point cursor_in_view = ui::EventLocationFromNative(event);
585 views::View::ConvertPointFromScreen(bubble_view_, &cursor_in_view); 656 views::View::ConvertPointFromScreen(bubble_view_, &cursor_in_view);
586 if (!bubble_view_->HitTest(cursor_in_view)) { 657 if (!bubble_view_->HitTest(cursor_in_view)) {
587 bubble_widget_->Close(); 658 bubble_widget_->Close();
588 } 659 }
589 } 660 }
590 return base::EVENT_CONTINUE; 661 return base::EVENT_CONTINUE;
591 } 662 }
592 663
593 void SystemTrayBubble::DidProcessEvent(const base::NativeEvent& event) { 664 void SystemTrayBubble::DidProcessEvent(const base::NativeEvent& event) {
594 } 665 }
595 666
596 void SystemTrayBubble::OnWidgetClosing(views::Widget* widget) { 667 void SystemTrayBubble::OnWidgetClosing(views::Widget* widget) {
597 CHECK_EQ(bubble_widget_, widget); 668 CHECK_EQ(bubble_widget_, widget);
598 MessageLoopForUI::current()->RemoveObserver(this); 669 MessageLoopForUI::current()->RemoveObserver(this);
599 bubble_widget_ = NULL; 670 bubble_widget_ = NULL;
600 tray_->RemoveBubble(this); 671 tray_->RemoveBubble(this);
601 } 672 }
602 673
603 void SystemTrayBubble::OnWidgetVisibilityChanged(views::Widget* widget, 674 void SystemTrayBubble::OnWidgetVisibilityChanged(views::Widget* widget,
604 bool visible) { 675 bool visible) {
605 if (!visible) 676 if (!visible)
606 MessageLoopForUI::current()->RemoveObserver(this); 677 MessageLoopForUI::current()->RemoveObserver(this);
607 else 678 else
608 MessageLoopForUI::current()->AddObserver(this); 679 MessageLoopForUI::current()->AddObserver(this);
609 } 680 }
610 681
682 // Observe the tray layer animation and update the anchor when it changes.
683 // TODO(stevenjb): Observe or mirror the actual animation, not just the start
684 // and end points.
685 class SystemTrayLayerAnimationObserver : public ui::LayerAnimationObserver {
686 public:
687 explicit SystemTrayLayerAnimationObserver(SystemTray* host) : host_(host) {}
688
689 virtual void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) {
690 host_->UpdateNotificationAnchor();
691 }
692
693 virtual void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) {
694 host_->UpdateNotificationAnchor();
695 }
696
697 virtual void OnLayerAnimationScheduled(ui::LayerAnimationSequence* sequence) {
698 host_->UpdateNotificationAnchor();
699 }
700
701 private:
702 SystemTray* host_;
sadrul 2012/05/08 19:40:17 DISALLOW_COPY_AND_ASSIGN
stevenjb 2012/05/08 22:49:20 Done.
703 };
704
611 } // namespace internal 705 } // namespace internal
612 706
613 // SystemTray 707 // SystemTray
614 708
709 using internal::SystemTrayBubble;
710 using internal::SystemTrayLayerAnimationObserver;
711
615 SystemTray::SystemTray() 712 SystemTray::SystemTray()
616 : items_(), 713 : items_(),
617 accessibility_observer_(NULL), 714 accessibility_observer_(NULL),
618 audio_observer_(NULL), 715 audio_observer_(NULL),
619 bluetooth_observer_(NULL), 716 bluetooth_observer_(NULL),
620 brightness_observer_(NULL), 717 brightness_observer_(NULL),
621 caps_lock_observer_(NULL), 718 caps_lock_observer_(NULL),
622 clock_observer_(NULL), 719 clock_observer_(NULL),
623 drive_observer_(NULL), 720 drive_observer_(NULL),
624 ime_observer_(NULL), 721 ime_observer_(NULL),
625 network_observer_(NULL), 722 network_observer_(NULL),
626 power_status_observer_(NULL), 723 power_status_observer_(NULL),
627 update_observer_(NULL), 724 update_observer_(NULL),
628 user_observer_(NULL), 725 user_observer_(NULL),
629 widget_(NULL), 726 widget_(NULL),
630 background_(new internal::SystemTrayBackground), 727 background_(new internal::SystemTrayBackground),
631 should_show_launcher_(false), 728 should_show_launcher_(false),
632 ALLOW_THIS_IN_INITIALIZER_LIST(hide_background_animator_(this, 729 ALLOW_THIS_IN_INITIALIZER_LIST(hide_background_animator_(this,
633 0, kTrayBackgroundAlpha)), 730 0, kTrayBackgroundAlpha)),
634 ALLOW_THIS_IN_INITIALIZER_LIST(hover_background_animator_(this, 731 ALLOW_THIS_IN_INITIALIZER_LIST(hover_background_animator_(this,
635 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha)) { 732 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha)) {
636 container_ = new views::View; 733 tray_container_ = new views::View;
637 container_->SetLayoutManager(new views::BoxLayout( 734 tray_container_->SetLayoutManager(new views::BoxLayout(
638 views::BoxLayout::kHorizontal, 0, 0, 0)); 735 views::BoxLayout::kHorizontal, 0, 0, 0));
639 container_->set_background(background_); 736 tray_container_->set_background(background_);
640 container_->set_border( 737 tray_container_->set_border(
641 views::Border::CreateEmptyBorder(1, 1, 1, 1)); 738 views::Border::CreateEmptyBorder(1, 1, 1, 1));
642 set_border(views::Border::CreateEmptyBorder(0, 0, 739 set_border(views::Border::CreateEmptyBorder(0, 0,
643 kPaddingFromBottomOfScreen, kPaddingFromRightEdgeOfScreen)); 740 kPaddingFromBottomOfScreen, kPaddingFromRightEdgeOfScreen));
644 set_notify_enter_exit_on_child(true); 741 set_notify_enter_exit_on_child(true);
645 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); 742 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
646 AddChildView(container_); 743 AddChildView(tray_container_);
647 744
648 // Initially we want to paint the background, but without the hover effect. 745 // Initially we want to paint the background, but without the hover effect.
649 SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE); 746 SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE);
650 hover_background_animator_.SetPaintsBackground(false, 747 hover_background_animator_.SetPaintsBackground(false,
651 internal::BackgroundAnimator::CHANGE_IMMEDIATE); 748 internal::BackgroundAnimator::CHANGE_IMMEDIATE);
652 } 749 }
653 750
654 SystemTray::~SystemTray() { 751 SystemTray::~SystemTray() {
655 bubble_.reset(); 752 bubble_.reset();
656 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); 753 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; 815 params.delegate = status_area_view;
719 params.parent = Shell::GetInstance()->GetContainer( 816 params.parent = Shell::GetInstance()->GetContainer(
720 ash::internal::kShellWindowId_StatusContainer); 817 ash::internal::kShellWindowId_StatusContainer);
721 params.transparent = true; 818 params.transparent = true;
722 widget_->Init(params); 819 widget_->Init(params);
723 widget_->set_focus_on_creation(false); 820 widget_->set_focus_on_creation(false);
724 status_area_view->AddChildView(this); 821 status_area_view->AddChildView(this);
725 widget_->SetContentsView(status_area_view); 822 widget_->SetContentsView(status_area_view);
726 widget_->Show(); 823 widget_->Show();
727 widget_->GetNativeView()->SetName("StatusTrayWidget"); 824 widget_->GetNativeView()->SetName("StatusTrayWidget");
825
826 layer_animation_observer_.reset(new SystemTrayLayerAnimationObserver(this));
827 widget_->GetNativeView()->layer()->GetAnimator()->AddObserver(
828 layer_animation_observer_.get());
728 } 829 }
729 830
730 void SystemTray::AddTrayItem(SystemTrayItem* item) { 831 void SystemTray::AddTrayItem(SystemTrayItem* item) {
731 items_.push_back(item); 832 items_.push_back(item);
732 833
733 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); 834 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
734 views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus()); 835 views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus());
735 if (tray_item) { 836 if (tray_item) {
736 container_->AddChildViewAt(tray_item, 0); 837 tray_container_->AddChildViewAt(tray_item, 0);
737 PreferredSizeChanged(); 838 PreferredSizeChanged();
738 } 839 }
739 } 840 }
740 841
741 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { 842 void SystemTray::RemoveTrayItem(SystemTrayItem* item) {
742 NOTIMPLEMENTED(); 843 NOTIMPLEMENTED();
743 } 844 }
744 845
745 void SystemTray::ShowDefaultView() { 846 void SystemTray::ShowDefaultView() {
746 ShowItems(items_.get(), false, true); 847 ShowItems(items_.get(), false, true);
747 } 848 }
748 849
749 void SystemTray::ShowDetailedView(SystemTrayItem* item, 850 void SystemTray::ShowDetailedView(SystemTrayItem* item,
750 int close_delay, 851 int close_delay,
751 bool activate) { 852 bool activate) {
752 std::vector<SystemTrayItem*> items; 853 std::vector<SystemTrayItem*> items;
753 items.push_back(item); 854 items.push_back(item);
754 ShowItems(items, true, activate); 855 ShowItems(items, true, activate);
755 bubble_->StartAutoCloseTimer(close_delay); 856 bubble_->StartAutoCloseTimer(close_delay);
756 } 857 }
757 858
859 void SystemTray::ShowNotificationView(SystemTrayItem* item) {
860 if (std::find(notification_items_.begin(), notification_items_.end(), item)
861 != notification_items_.end())
862 return;
863 notification_items_.push_back(item);
864 ShowNotifications();
865 }
866
867 void SystemTray::HideNotificationView(SystemTrayItem* item) {
868 std::vector<SystemTrayItem*>::iterator found_iter =
869 std::find(notification_items_.begin(), notification_items_.end(), item);
870 if (found_iter == notification_items_.end())
871 return;
872 notification_items_.erase(found_iter);
873 ShowNotifications();
874 }
875
758 void SystemTray::SetDetailedViewCloseDelay(int close_delay) { 876 void SystemTray::SetDetailedViewCloseDelay(int close_delay) {
759 if (bubble_.get() && bubble_->detailed()) 877 if (bubble_.get() &&
878 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DETAILED)
760 bubble_->StartAutoCloseTimer(close_delay); 879 bubble_->StartAutoCloseTimer(close_delay);
761 } 880 }
762 881
763 void SystemTray::UpdateAfterLoginStatusChange(user::LoginStatus login_status) { 882 void SystemTray::UpdateAfterLoginStatusChange(user::LoginStatus login_status) {
764 bubble_.reset(); 883 bubble_.reset();
765 884
766 for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); 885 for (std::vector<SystemTrayItem*>::iterator it = items_.begin();
767 it != items_.end(); 886 it != items_.end();
768 ++it) { 887 ++it) {
769 (*it)->UpdateAfterLoginStatusChange(login_status); 888 (*it)->UpdateAfterLoginStatusChange(login_status);
770 } 889 }
771 890
772 SetVisible(true); 891 SetVisible(true);
773 PreferredSizeChanged(); 892 PreferredSizeChanged();
774 } 893 }
775 894
776 bool SystemTray::CloseBubbleForTest() const { 895 bool SystemTray::CloseBubbleForTest() const {
777 if (!bubble_.get()) 896 if (!bubble_.get())
778 return false; 897 return false;
779 bubble_->Close(); 898 bubble_->Close();
780 return true; 899 return true;
781 } 900 }
782 901
783 // Private methods. 902 // Private methods.
784 903
785 void SystemTray::RemoveBubble(internal::SystemTrayBubble* bubble) { 904 void SystemTray::RemoveBubble(SystemTrayBubble* bubble) {
786 CHECK_EQ(bubble_.get(), bubble); 905 if (bubble == bubble_.get()) {
787 bubble_.reset(); 906 bubble_.reset();
788 907 ShowNotifications(); // State changed, re-create notifications.
789 if (should_show_launcher_) { 908 if (should_show_launcher_) {
790 // No need to show the launcher if the mouse isn't over the status area 909 // No need to show the launcher if the mouse isn't over the status area
791 // anymore. 910 // anymore.
792 aura::RootWindow* root = GetWidget()->GetNativeView()->GetRootWindow(); 911 aura::RootWindow* root = GetWidget()->GetNativeView()->GetRootWindow();
793 should_show_launcher_ = GetWidget()->GetWindowScreenBounds().Contains( 912 should_show_launcher_ = GetWidget()->GetWindowScreenBounds().Contains(
794 root->last_mouse_location()); 913 root->last_mouse_location());
795 if (!should_show_launcher_) 914 if (!should_show_launcher_)
796 Shell::GetInstance()->shelf()->UpdateAutoHideState(); 915 Shell::GetInstance()->shelf()->UpdateAutoHideState();
916 }
917 } else if (bubble == notification_bubble_) {
918 notification_bubble_.reset();
919 } else {
920 NOTREACHED();
797 } 921 }
798 } 922 }
799 923
800 void SystemTray::SetPaintsBackground( 924 void SystemTray::SetPaintsBackground(
801 bool value, 925 bool value,
802 internal::BackgroundAnimator::ChangeType change_type) { 926 internal::BackgroundAnimator::ChangeType change_type) {
803 hide_background_animator_.SetPaintsBackground(value, change_type); 927 hide_background_animator_.SetPaintsBackground(value, change_type);
804 } 928 }
805 929
806 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, 930 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
807 bool detailed, 931 bool detailed,
808 bool can_activate) { 932 bool can_activate) {
809 // Destroy any existing bubble and create a new one. 933 // Destroy any existing bubble and create a new one.
810 bubble_.reset(new internal::SystemTrayBubble(this, items, detailed)); 934 SystemTrayBubble::BubbleType bubble_type = detailed ?
935 SystemTrayBubble::BUBBLE_TYPE_DETAILED :
936 SystemTrayBubble::BUBBLE_TYPE_DEFAULT;
937 bubble_.reset(new SystemTrayBubble(this, items, bubble_type));
811 ash::SystemTrayDelegate* delegate = 938 ash::SystemTrayDelegate* delegate =
812 ash::Shell::GetInstance()->tray_delegate(); 939 ash::Shell::GetInstance()->tray_delegate();
813 bubble_->InitView(container_, can_activate, delegate->GetUserLoginStatus()); 940 views::View* anchor = tray_container_;
941 bubble_->InitView(anchor, SystemTrayBubble::ANCHOR_TYPE_TRAY,
942 can_activate, delegate->GetUserLoginStatus());
814 // If we have focus the shelf should be visible and we need to continue 943 // If we have focus the shelf should be visible and we need to continue
815 // showing the shelf when the popup is shown. 944 // showing the shelf when the popup is shown.
816 if (GetWidget()->IsActive()) 945 if (GetWidget()->IsActive())
817 should_show_launcher_ = true; 946 should_show_launcher_ = true;
947 ShowNotifications(); // State changed, re-create notifications.
948 }
949
950 void SystemTray::ShowNotifications() {
sadrul 2012/05/08 19:40:17 Since this can hide the notifications in some case
stevenjb 2012/05/08 22:49:20 Done.
951 // Only show the notification buble if we have notifications and we are not
952 // showing the default bubble.
953 if (notification_items_.empty() ||
954 (bubble_.get() &&
955 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) {
956 notification_bubble_.reset();
957 return;
958 }
959 notification_bubble_.reset(
960 new SystemTrayBubble(this, notification_items_,
961 SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
962 views::View* anchor;
963 SystemTrayBubble::AnchorType anchor_type;
964 if (bubble_.get()) {
965 anchor = bubble_->bubble_view();
966 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE;
967 } else {
968 anchor = tray_container_;
969 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY;
970 }
971 notification_bubble_->InitView(
972 anchor, anchor_type,
973 false /* can_activate */,
974 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus());
975 }
976
977 void SystemTray::UpdateNotificationAnchor() {
978 if (!notification_bubble_.get())
979 return;
980 notification_bubble_->bubble_view()->UpdateAnchor();
981 // Ensure that the notification buble is above the launcher/status area.
982 notification_bubble_->bubble_view()->GetWidget()->StackAtTop();
818 } 983 }
819 984
820 bool SystemTray::PerformAction(const views::Event& event) { 985 bool SystemTray::PerformAction(const views::Event& event) {
821 // If we're already showing the default view, hide it; otherwise, show it 986 // If we're already showing the default view, hide it; otherwise, show it
822 // (and hide any popup that's currently shown). 987 // (and hide any popup that's currently shown).
823 if (bubble_.get() && !bubble_->detailed()) 988 if (bubble_.get() &&
989 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) {
824 bubble_->Close(); 990 bubble_->Close();
825 else 991 } else {
826 ShowDefaultView(); 992 ShowDefaultView();
993 }
827 return true; 994 return true;
828 } 995 }
829 996
830 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { 997 void SystemTray::OnMouseEntered(const views::MouseEvent& event) {
831 should_show_launcher_ = true; 998 should_show_launcher_ = true;
832 hover_background_animator_.SetPaintsBackground(true, 999 hover_background_animator_.SetPaintsBackground(true,
833 internal::BackgroundAnimator::CHANGE_ANIMATE); 1000 internal::BackgroundAnimator::CHANGE_ANIMATE);
834 } 1001 }
835 1002
836 void SystemTray::OnMouseExited(const views::MouseEvent& event) { 1003 void SystemTray::OnMouseExited(const views::MouseEvent& event) {
(...skipping 14 matching lines...) Expand all
851 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; 1018 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
852 state->name = l10n_util::GetStringUTF16( 1019 state->name = l10n_util::GetStringUTF16(
853 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); 1020 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME);
854 } 1021 }
855 1022
856 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { 1023 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) {
857 // The tray itself expands to the right and bottom edge of the screen to make 1024 // 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 1025 // sure clicking on the edges brings up the popup. However, the focus border
859 // should be only around the container. 1026 // should be only around the container.
860 if (GetWidget() && GetWidget()->IsActive()) 1027 if (GetWidget() && GetWidget()->IsActive())
861 canvas->DrawFocusRect(container_->bounds()); 1028 canvas->DrawFocusRect(tray_container_->bounds());
862 } 1029 }
863 1030
864 void SystemTray::UpdateBackground(int alpha) { 1031 void SystemTray::UpdateBackground(int alpha) {
865 background_->set_alpha(hide_background_animator_.alpha() + 1032 background_->set_alpha(hide_background_animator_.alpha() +
866 hover_background_animator_.alpha()); 1033 hover_background_animator_.alpha());
867 SchedulePaint(); 1034 SchedulePaint();
868 } 1035 }
869 1036
870 } // namespace ash 1037 } // 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