1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/message_center/views/desktop_popup_alignment_delegate.h"
6
7#include "ui/gfx/display.h"
8#include "ui/gfx/geometry/rect.h"
9#include "ui/gfx/screen.h"
10#include "ui/message_center/message_center_style.h"
11#include "ui/message_center/views/message_popup_collection.h"
12
13namespace message_center {
14
15DesktopPopupAlignmentDelegate::DesktopPopupAlignmentDelegate()
16    : alignment_(POPUP_ALIGNMENT_BOTTOM | POPUP_ALIGNMENT_RIGHT),
17      display_id_(gfx::Display::kInvalidDisplayID),
18      screen_(NULL) {
19}
20
21DesktopPopupAlignmentDelegate::~DesktopPopupAlignmentDelegate() {
22  if (screen_)
23    screen_->RemoveObserver(this);
24}
25
26void DesktopPopupAlignmentDelegate::StartObserving(gfx::Screen* screen) {
27  if (screen_ || !screen)
28    return;
29
30  screen_ = screen;
31  screen_->AddObserver(this);
32  gfx::Display display = screen_->GetPrimaryDisplay();
33  display_id_ = display.id();
34  RecomputeAlignment(display);
35}
36
37int DesktopPopupAlignmentDelegate::GetToastOriginX(
38    const gfx::Rect& toast_bounds) const {
39  if (IsFromLeft())
40    return work_area_.x() + kMarginBetweenItems;
41  return work_area_.right() - kMarginBetweenItems - toast_bounds.width();
42}
43
44int DesktopPopupAlignmentDelegate::GetBaseLine() const {
45  return IsTopDown()
46      ? work_area_.y() + kMarginBetweenItems
47      : work_area_.bottom() - kMarginBetweenItems;
48}
49
50int DesktopPopupAlignmentDelegate::GetWorkAreaBottom() const {
51  return work_area_.bottom();
52}
53
54bool DesktopPopupAlignmentDelegate::IsTopDown() const {
55  return (alignment_ & POPUP_ALIGNMENT_TOP) != 0;
56}
57
58bool DesktopPopupAlignmentDelegate::IsFromLeft() const {
59  return (alignment_ & POPUP_ALIGNMENT_LEFT) != 0;
60}
61
62void DesktopPopupAlignmentDelegate::RecomputeAlignment(
63    const gfx::Display& display) {
64  if (work_area_ == display.work_area())
65    return;
66
67  work_area_ = display.work_area();
68
69  // If the taskbar is at the top, render notifications top down. Some platforms
70  // like Gnome can have taskbars at top and bottom. In this case it's more
71  // likely that the systray is on the top one.
72  alignment_ = work_area_.y() > display.bounds().y() ? POPUP_ALIGNMENT_TOP
73                                                     : POPUP_ALIGNMENT_BOTTOM;
74
75  // If the taskbar is on the left show the notifications on the left. Otherwise
76  // show it on right since it's very likely that the systray is on the right if
77  // the taskbar is on the top or bottom.
78  // Since on some platforms like Ubuntu Unity there's also a launcher along
79  // with a taskbar (panel), we need to check that there is really nothing at
80  // the top before concluding that the taskbar is at the left.
81  alignment_ |= (work_area_.x() > display.bounds().x() &&
82                 work_area_.y() == display.bounds().y())
83      ? POPUP_ALIGNMENT_LEFT
84      : POPUP_ALIGNMENT_RIGHT;
85}
86
87void DesktopPopupAlignmentDelegate::OnDisplayAdded(
88    const gfx::Display& new_display) {
89}
90
91void DesktopPopupAlignmentDelegate::OnDisplayRemoved(
92    const gfx::Display& old_display) {
93}
94
95void DesktopPopupAlignmentDelegate::OnDisplayMetricsChanged(
96    const gfx::Display& display,
97    uint32_t metrics) {
98  if (display.id() == display_id_) {
99    RecomputeAlignment(display);
100    DoUpdateIfPossible();
101  }
102}
103
104}  // namespace message_center
105