forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
desktop_popup_alignment_delegate.cc
128 lines (106 loc) · 4.56 KB
/
desktop_popup_alignment_delegate.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/message_center/views/desktop_popup_alignment_delegate.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/message_popup_collection.h"
namespace message_center {
DesktopPopupAlignmentDelegate::DesktopPopupAlignmentDelegate()
: alignment_(POPUP_ALIGNMENT_BOTTOM | POPUP_ALIGNMENT_RIGHT),
primary_display_id_(display::kInvalidDisplayId),
screen_(NULL) {}
DesktopPopupAlignmentDelegate::~DesktopPopupAlignmentDelegate() {
if (screen_)
screen_->RemoveObserver(this);
}
void DesktopPopupAlignmentDelegate::StartObserving(display::Screen* screen) {
if (screen_ || !screen)
return;
screen_ = screen;
screen_->AddObserver(this);
display::Display display = screen_->GetPrimaryDisplay();
primary_display_id_ = display.id();
RecomputeAlignment(display);
}
int DesktopPopupAlignmentDelegate::GetToastOriginX(
const gfx::Rect& toast_bounds) const {
if (IsFromLeft())
return work_area_.x() + kMarginBetweenItems;
return work_area_.right() - kMarginBetweenItems - toast_bounds.width();
}
int DesktopPopupAlignmentDelegate::GetBaseLine() const {
return IsTopDown()
? work_area_.y() + kMarginBetweenItems
: work_area_.bottom() - kMarginBetweenItems;
}
gfx::Rect DesktopPopupAlignmentDelegate::GetWorkArea() const {
return work_area_;
}
bool DesktopPopupAlignmentDelegate::IsTopDown() const {
return (alignment_ & POPUP_ALIGNMENT_TOP) != 0;
}
bool DesktopPopupAlignmentDelegate::IsFromLeft() const {
return (alignment_ & POPUP_ALIGNMENT_LEFT) != 0;
}
void DesktopPopupAlignmentDelegate::RecomputeAlignment(
const display::Display& display) {
if (work_area_ == display.work_area())
return;
work_area_ = display.work_area();
// If the taskbar is at the top, render notifications top down. Some platforms
// like Gnome can have taskbars at top and bottom. In this case it's more
// likely that the systray is on the top one.
alignment_ = work_area_.y() > display.bounds().y() ? POPUP_ALIGNMENT_TOP
: POPUP_ALIGNMENT_BOTTOM;
// If the taskbar is on the left show the notifications on the left. Otherwise
// show it on right since it's very likely that the systray is on the right if
// the taskbar is on the top or bottom.
// Since on some platforms like Ubuntu Unity there's also a launcher along
// with a taskbar (panel), we need to check that there is really nothing at
// the top before concluding that the taskbar is at the left.
alignment_ |= (work_area_.x() > display.bounds().x() &&
work_area_.y() == display.bounds().y())
? POPUP_ALIGNMENT_LEFT
: POPUP_ALIGNMENT_RIGHT;
}
void DesktopPopupAlignmentDelegate::ConfigureWidgetInitParamsForContainer(
views::Widget* widget,
views::Widget::InitParams* init_params) {
// Do nothing, which will use the default container.
}
// Anytime the display configuration changes, we need to recompute the alignment
// on the primary display. But, we get different events on different platforms.
// On Windows, for example, when switching from a laptop display to an external
// monitor, we get a OnDisplayMetricsChanged() event. On Linux, we get a
// OnDisplayRemoved() and a OnDisplayAdded() instead. In order to account for
// these slightly different abstractions, we update on every event.
void DesktopPopupAlignmentDelegate::UpdatePrimaryDisplay() {
display::Display primary_display = screen_->GetPrimaryDisplay();
if (primary_display.id() != primary_display_id_) {
primary_display_id_ = primary_display.id();
RecomputeAlignment(primary_display);
DoUpdateIfPossible();
}
}
void DesktopPopupAlignmentDelegate::OnDisplayAdded(
const display::Display& added_display) {
// The added display could be the new primary display.
UpdatePrimaryDisplay();
}
void DesktopPopupAlignmentDelegate::OnDisplayRemoved(
const display::Display& removed_display) {
// The removed display may have been the primary display.
UpdatePrimaryDisplay();
}
void DesktopPopupAlignmentDelegate::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t metrics) {
// Set to kInvalidDisplayId so the alignment is updated regardless of whether
// the primary display actually changed.
primary_display_id_ = display::kInvalidDisplayId;
UpdatePrimaryDisplay();
}
} // namespace message_center