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

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

Issue 10808066: Fix position of web notification bubble and arrow (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase without unrelated changes + address comments Created 8 years, 4 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
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/tray_bubble_view.h" 5 #include "ash/system/tray/tray_bubble_view.h"
6 6
7 #include "ash/shell.h" 7 #include "ash/shell.h"
8 #include "ash/shell_window_ids.h" 8 #include "ash/shell_window_ids.h"
9 #include "ash/system/tray/tray_constants.h" 9 #include "ash/system/tray/tray_constants.h"
10 #include "ash/wm/shelf_layout_manager.h" 10 #include "ash/wm/shelf_layout_manager.h"
11 #include "ash/wm/window_animations.h"
11 #include "grit/ash_strings.h" 12 #include "grit/ash_strings.h"
12 #include "third_party/skia/include/core/SkCanvas.h" 13 #include "third_party/skia/include/core/SkCanvas.h"
13 #include "third_party/skia/include/core/SkColor.h" 14 #include "third_party/skia/include/core/SkColor.h"
14 #include "third_party/skia/include/core/SkPaint.h" 15 #include "third_party/skia/include/core/SkPaint.h"
15 #include "third_party/skia/include/core/SkPath.h" 16 #include "third_party/skia/include/core/SkPath.h"
16 #include "third_party/skia/include/effects/SkBlurImageFilter.h" 17 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
17 #include "ui/aura/event.h" 18 #include "ui/aura/event.h"
18 #include "ui/aura/window.h" 19 #include "ui/aura/window.h"
19 #include "ui/base/accessibility/accessible_view_state.h" 20 #include "ui/base/accessibility/accessible_view_state.h"
20 #include "ui/base/l10n/l10n_util.h" 21 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/gfx/canvas.h" 22 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/insets.h" 23 #include "ui/gfx/insets.h"
23 #include "ui/gfx/screen.h" 24 #include "ui/gfx/screen.h"
24 #include "ui/views/bubble/bubble_frame_view.h" 25 #include "ui/views/bubble/bubble_frame_view.h"
25 #include "ui/views/layout/box_layout.h" 26 #include "ui/views/layout/box_layout.h"
26 27
27 namespace ash { 28 namespace ash {
28 29
29 namespace { 30 namespace {
30 31
31 const int kShadowThickness = 4; 32 const int kShadowThickness = 4;
32 const int kBottomLineHeight = 1; 33 const int kBottomLineHeight = 1;
33 const int kSystemTrayBubbleHorizontalInset = 1; 34 const int kSystemTrayBubbleHorizontalInset = 1;
34 const int kSystemTrayBubbleVerticalInset = 1; 35 const int kSystemTrayBubbleVerticalInset = 1;
35 36
36 const int kArrowHeight = 10; 37 const int kArrowHeight = 10;
37 const int kArrowWidth = 20; 38 const int kArrowWidth = 20;
38 39
39 // Inset the arrow a bit from the edge. 40 // Inset the arrow a bit from the edge.
40 const int kArrowMinOffset = kArrowWidth / 2 + 4; 41 const int kArrowEdgeMargin = 12;
42 const int kArrowMinOffset = kArrowWidth / 2 + kArrowEdgeMargin;
41 43
42 const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0); 44 const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0);
43 45
46 const int kAnimationDurationForPopupMS = 200;
47
44 void DrawBlurredShadowAroundView(gfx::Canvas* canvas, 48 void DrawBlurredShadowAroundView(gfx::Canvas* canvas,
45 int top, 49 int top,
46 int bottom, 50 int bottom,
47 int width, 51 int width,
48 const gfx::Insets& inset) { 52 const gfx::Insets& inset) {
49 SkPath path; 53 SkPath path;
50 path.incReserve(4); 54 path.incReserve(4);
51 path.moveTo(SkIntToScalar(inset.left() + kShadowThickness), 55 path.moveTo(SkIntToScalar(inset.left() + kShadowThickness),
52 SkIntToScalar(top + kShadowThickness + 1)); 56 SkIntToScalar(top + kShadowThickness + 1));
53 path.lineTo(SkIntToScalar(inset.left() + kShadowThickness), 57 path.lineTo(SkIntToScalar(inset.left() + kShadowThickness),
(...skipping 11 matching lines...) Expand all
65 paint.setImageFilter(new SkBlurImageFilter( 69 paint.setImageFilter(new SkBlurImageFilter(
66 SkIntToScalar(3), SkIntToScalar(3)))->unref(); 70 SkIntToScalar(3), SkIntToScalar(3)))->unref();
67 canvas->sk_canvas()->drawPath(path, paint); 71 canvas->sk_canvas()->drawPath(path, paint);
68 } 72 }
69 73
70 class TrayBubbleBorder : public views::BubbleBorder { 74 class TrayBubbleBorder : public views::BubbleBorder {
71 public: 75 public:
72 TrayBubbleBorder(views::View* owner, 76 TrayBubbleBorder(views::View* owner,
73 views::View* anchor, 77 views::View* anchor,
74 views::BubbleBorder::ArrowLocation arrow_location, 78 views::BubbleBorder::ArrowLocation arrow_location,
75 int arrow_offset) 79 int arrow_offset,
76 : views::BubbleBorder(arrow_location, 80 const SkColor& arrow_color)
77 views::BubbleBorder::NO_SHADOW), 81 : views::BubbleBorder(arrow_location, views::BubbleBorder::NO_SHADOW),
78 owner_(owner), 82 owner_(owner),
79 anchor_(anchor), 83 anchor_(anchor),
80 tray_arrow_offset_(arrow_offset) { 84 tray_arrow_offset_(arrow_offset) {
81 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); 85 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
86 set_background_color(arrow_color);
82 } 87 }
83 88
84 virtual ~TrayBubbleBorder() {} 89 virtual ~TrayBubbleBorder() {}
85 90
86 private:
87 views::Background* FindAppropriateBackground(views::View* view,
88 const gfx::Point& point) const {
89 views::Background* background = NULL;
90 views::View* target = view->GetEventHandlerForPoint(point);
91 for (; target && !background; target = target->parent())
92 background = target->background();
93 return background;
94 }
jennyz 2012/07/31 02:29:47 I wonder if the arrow color will be right after re
stevenjb 2012/07/31 16:35:28 I think sadrul's CL predates the current design wh
95
96 // Overridden from views::BubbleBorder. 91 // Overridden from views::BubbleBorder.
97 // Override views::BubbleBorder to set the bubble on top of the anchor when 92 // Override views::BubbleBorder to set the bubble on top of the anchor when
98 // it has no arrow. 93 // it has no arrow.
99 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, 94 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
100 const gfx::Size& contents_size) const OVERRIDE { 95 const gfx::Size& contents_size) const OVERRIDE {
101 if (arrow_location() != NONE) { 96 if (arrow_location() != NONE) {
102 return views::BubbleBorder::GetBounds(position_relative_to, 97 return views::BubbleBorder::GetBounds(position_relative_to,
103 contents_size); 98 contents_size);
104 } 99 }
105 100
106 gfx::Size border_size(contents_size); 101 gfx::Size border_size(contents_size);
107 gfx::Insets insets; 102 gfx::Insets insets;
108 GetInsets(&insets); 103 GetInsets(&insets);
109 border_size.Enlarge(insets.width(), insets.height()); 104 border_size.Enlarge(insets.width(), insets.height());
110 105
111 const int kArrowOverlap = 3; 106 const int kArrowOverlap = 3;
112 int x = position_relative_to.x() + 107 int x = position_relative_to.x() +
113 position_relative_to.width() / 2 - border_size.width() / 2; 108 position_relative_to.width() / 2 - border_size.width() / 2;
114 // Position the bubble on top of the anchor. 109 // Position the bubble on top of the anchor.
115 int y = position_relative_to.y() + 110 int y = position_relative_to.y() +
116 kArrowOverlap - border_size.height(); 111 kArrowOverlap - border_size.height();
117 return gfx::Rect(x, y, border_size.width(), border_size.height()); 112 return gfx::Rect(x, y, border_size.width(), border_size.height());
118 } 113 }
119 114
115 // TrayBubbleView supports dynamically updated bubbles. This does not
msw 2012/07/31 14:41:56 FYI: Check out chrome/browser/ui/views/page_info_b
stevenjb 2012/07/31 16:35:28 I'll take a look. As discussed, I plan to write un
116 // behave well with BubbleFrameView which expects arrow_location to be
117 // unmirrored during initial layout (when ClientView is constructed),
118 // then mirrored after SizeToContents() gets called.
119 // So, instead of mirroring the arrow in CreateNonClientFrameView,
120 // mirror it here instead.
121 virtual void GetInsets(gfx::Insets* insets) const OVERRIDE {
122 ArrowLocation arrow_loc = arrow_location();
123 if (base::i18n::IsRTL())
124 arrow_loc = horizontal_mirror(arrow_loc);
125 return GetInsetsForArrowLocation(insets, arrow_loc);
jennyz 2012/07/31 02:29:47 It seems make more sense for bubble infrastructure
stevenjb 2012/07/31 16:35:28 Yes, this is a work around until we have more/bett
126 }
127
120 // Overridden from views::Border. 128 // Overridden from views::Border.
121 virtual void Paint(const views::View& view, 129 virtual void Paint(const views::View& view,
122 gfx::Canvas* canvas) const OVERRIDE { 130 gfx::Canvas* canvas) const OVERRIDE {
123 gfx::Insets inset; 131 gfx::Insets inset;
124 GetInsets(&inset); 132 // Get the unmirrored insets for the arrow location.
jennyz 2012/07/31 02:29:47 Can you add some comments to explain why we need t
stevenjb 2012/07/31 16:35:28 Added a little to the comment here, mostly see the
133 GetInsetsForArrowLocation(&inset, arrow_location());
125 DrawBlurredShadowAroundView( 134 DrawBlurredShadowAroundView(
126 canvas, 0, owner_->height(), owner_->width(), inset); 135 canvas, 0, owner_->height(), owner_->width(), inset);
127 136
128 // Draw the bottom line. 137 // Draw the bottom line.
129 int y = owner_->height() + inset.top(); 138 int y = owner_->height() + inset.top();
130 canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(), 139 canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(),
131 kBottomLineHeight), kBorderDarkColor); 140 kBottomLineHeight), kBorderDarkColor);
132 141
133 if (!Shell::GetInstance()->shelf()->IsVisible() || 142 if (!Shell::GetInstance()->shelf()->IsVisible() ||
134 arrow_location() == views::BubbleBorder::NONE) 143 arrow_location() == views::BubbleBorder::NONE)
135 return; 144 return;
136 145
137 gfx::Point arrow_reference; 146 gfx::Point arrow_reference;
138 147
139 // Draw the arrow after drawing child borders, so that the arrow can cover 148 // Draw the arrow after drawing child borders, so that the arrow can cover
140 // the its overlap section with child border. 149 // its overlap section with child border.
141 SkPath path; 150 SkPath path;
142 path.incReserve(4); 151 path.incReserve(4);
143 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT || 152 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT ||
144 arrow_location() == views::BubbleBorder::BOTTOM_LEFT) { 153 arrow_location() == views::BubbleBorder::BOTTOM_LEFT) {
145 // Do not let the arrow too close to the edge of the bubble and 154 // Note: tray_arrow_offset_ is relative to the anchor widget.
146 // and the edge of the anchor. 155 int tip_x;
147 int tip_x = base::i18n::IsRTL() ? 156 if (tray_arrow_offset_ ==
148 std::min(std::max(tray_arrow_offset_, kArrowMinOffset), 157 internal::TrayBubbleView::InitParams::kArrowDefaultOffset) {
149 std::min(owner_->width(), anchor_->width()) 158 if (arrow_location() == views::BubbleBorder::BOTTOM_LEFT)
150 - kArrowMinOffset) : 159 tip_x = kArrowMinOffset;
151 std::min(std::max(owner_->width() - tray_arrow_offset_, 160 else
152 owner_->width() - 161 tip_x = owner_->width() - kArrowMinOffset;
153 std::min(owner_->width(), anchor_->width()) + 162 } else {
154 kArrowMinOffset), 163 gfx::Point pt(tray_arrow_offset_, 0);
155 owner_->width() - kArrowMinOffset); 164 views::View::ConvertPointToScreen(
165 anchor_->GetWidget()->GetRootView(), &pt);
166 views::View::ConvertPointFromScreen(
167 owner_->GetWidget()->GetRootView(), &pt);
168 tip_x = std::min(pt.x(), owner_->width() - kArrowMinOffset);
169 tip_x = std::max(tip_x, kArrowMinOffset);
170 }
156 int left_base_x = tip_x - kArrowWidth / 2; 171 int left_base_x = tip_x - kArrowWidth / 2;
157 int left_base_y = y; 172 int left_base_y = y;
158 int tip_y = left_base_y + kArrowHeight; 173 int tip_y = left_base_y + kArrowHeight;
159 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); 174 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y));
160 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); 175 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y));
161 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), 176 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth),
162 SkIntToScalar(left_base_y)); 177 SkIntToScalar(left_base_y));
163 arrow_reference.SetPoint(tip_x, left_base_y - kArrowHeight); 178 arrow_reference.SetPoint(tip_x, left_base_y - kArrowHeight);
164 } else { 179 } else {
165 int tip_y = y - tray_arrow_offset_; 180 int tip_y;
166 tip_y = std::min(std::max(kArrowMinOffset, tip_y), 181 if (tray_arrow_offset_ ==
167 owner_->height() - kArrowMinOffset); 182 internal::TrayBubbleView::InitParams::kArrowDefaultOffset) {
183 tip_y = owner_->height() - kArrowMinOffset;
184 } else {
185 int pty = y - tray_arrow_offset_;
186 gfx::Point pt(0, pty);
187 views::View::ConvertPointToScreen(
188 anchor_->GetWidget()->GetRootView(), &pt);
189 views::View::ConvertPointFromScreen(
190 owner_->GetWidget()->GetRootView(), &pt);
191 tip_y = std::min(pt.y(), owner_->height() - kArrowMinOffset);
192 tip_y = std::max(tip_y, kArrowMinOffset);
193 }
168 int top_base_y = tip_y - kArrowWidth / 2; 194 int top_base_y = tip_y - kArrowWidth / 2;
169 int top_base_x, tip_x; 195 int top_base_x, tip_x;
170 if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) { 196 if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) {
171 top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset; 197 top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset;
172 tip_x = top_base_x - kArrowHeight; 198 tip_x = top_base_x - kArrowHeight;
173 arrow_reference.SetPoint(top_base_x + kArrowHeight, tip_y); 199 arrow_reference.SetPoint(top_base_x + kArrowHeight, tip_y);
174 } else { 200 } else {
175 DCHECK(arrow_location() == views::BubbleBorder::RIGHT_BOTTOM); 201 DCHECK(arrow_location() == views::BubbleBorder::RIGHT_BOTTOM);
176 top_base_x = inset.left() + owner_->width() - 202 top_base_x = inset.left() + owner_->width() -
177 kSystemTrayBubbleHorizontalInset; 203 kSystemTrayBubbleHorizontalInset;
178 tip_x = top_base_x + kArrowHeight; 204 tip_x = top_base_x + kArrowHeight;
179 arrow_reference.SetPoint(top_base_x - kArrowHeight, tip_y); 205 arrow_reference.SetPoint(top_base_x - kArrowHeight, tip_y);
180 } 206 }
181 path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y)); 207 path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y));
182 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); 208 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y));
183 path.lineTo(SkIntToScalar(top_base_x), 209 path.lineTo(SkIntToScalar(top_base_x),
184 SkIntToScalar(top_base_y + kArrowWidth)); 210 SkIntToScalar(top_base_y + kArrowWidth));
185 } 211 }
186 212
187 views::Background* background = FindAppropriateBackground(owner_,
188 arrow_reference);
189
190 SkPaint paint; 213 SkPaint paint;
191 paint.setStyle(SkPaint::kFill_Style); 214 paint.setStyle(SkPaint::kFill_Style);
192 paint.setColor(background ? background->get_color() : kBackgroundColor); 215 paint.setColor(background_color());
193 canvas->DrawPath(path, paint); 216 canvas->DrawPath(path, paint);
194 217
195 // Now draw the arrow border. 218 // Now draw the arrow border.
196 paint.setStyle(SkPaint::kStroke_Style); 219 paint.setStyle(SkPaint::kStroke_Style);
197 paint.setColor(kBorderDarkColor); 220 paint.setColor(kBorderDarkColor);
198 canvas->DrawPath(path, paint); 221 canvas->DrawPath(path, paint);
199 222
200 } 223 }
201 224
202 views::View* owner_; 225 views::View* owner_;
203 views::View* anchor_; 226 views::View* anchor_;
204 const int tray_arrow_offset_; 227 const int tray_arrow_offset_;
205 228
206 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); 229 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder);
207 }; 230 };
208 231
209 } // namespace 232 } // namespace
210 233
211 namespace internal { 234 namespace internal {
212 235
236 // static
237 const int TrayBubbleView::InitParams::kArrowDefaultOffset = -1;
238
239 TrayBubbleView::InitParams::InitParams(AnchorType anchor_type,
240 ShelfAlignment shelf_alignment)
241 : anchor_type(anchor_type),
242 shelf_alignment(shelf_alignment),
243 bubble_width(kTrayPopupWidth),
244 max_height(0),
245 can_activate(false),
246 arrow_offset(kArrowDefaultOffset),
247 arrow_color(kHeaderBackgroundColorDark) {
248 }
249
250 TrayBubbleView* TrayBubbleView::Create(views::View* anchor,
251 Host* host,
252 const InitParams& init_params) {
253 // Set arrow_location here so that it can be passed correctly to the
254 // BubbleView constructor.
255 views::BubbleBorder::ArrowLocation arrow_location;
256 if (init_params.anchor_type == ANCHOR_TYPE_TRAY) {
257 if (init_params.shelf_alignment == SHELF_ALIGNMENT_BOTTOM) {
258 arrow_location = base::i18n::IsRTL() ?
259 views::BubbleBorder::BOTTOM_LEFT : views::BubbleBorder::BOTTOM_RIGHT;
260 } else if (init_params.shelf_alignment == SHELF_ALIGNMENT_LEFT) {
261 arrow_location = views::BubbleBorder::LEFT_BOTTOM;
262 } else {
263 arrow_location = views::BubbleBorder::RIGHT_BOTTOM;
264 }
265 } else {
266 arrow_location = views::BubbleBorder::NONE;
267 }
268
269 return new TrayBubbleView(init_params, arrow_location, anchor, host);
270 }
271
213 TrayBubbleView::TrayBubbleView( 272 TrayBubbleView::TrayBubbleView(
273 const InitParams& init_params,
274 views::BubbleBorder::ArrowLocation arrow_location,
214 views::View* anchor, 275 views::View* anchor,
215 views::BubbleBorder::ArrowLocation arrow_location, 276 Host* host)
216 Host* host,
217 bool can_activate,
218 int bubble_width)
219 : views::BubbleDelegateView(anchor, arrow_location), 277 : views::BubbleDelegateView(anchor, arrow_location),
220 host_(host), 278 params_(init_params),
221 can_activate_(can_activate), 279 host_(host) {
222 max_height_(0),
223 bubble_width_(bubble_width) {
224 set_margins(gfx::Insets()); 280 set_margins(gfx::Insets());
225 set_parent_window(Shell::GetContainer( 281 set_parent_window(Shell::GetContainer(
226 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), 282 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
227 internal::kShellWindowId_SettingBubbleContainer)); 283 internal::kShellWindowId_SettingBubbleContainer));
228 set_notify_enter_exit_on_child(true); 284 set_notify_enter_exit_on_child(true);
229 SetPaintToLayer(true); 285 SetPaintToLayer(true);
230 SetFillsBoundsOpaquely(true); 286 SetFillsBoundsOpaquely(true);
231 } 287 }
232 288
233 TrayBubbleView::~TrayBubbleView() { 289 TrayBubbleView::~TrayBubbleView() {
234 // Inform host items (models) that their views are being destroyed. 290 // Inform host items (models) that their views are being destroyed.
235 if (host_) 291 if (host_)
236 host_->BubbleViewDestroyed(); 292 host_->BubbleViewDestroyed();
237 } 293 }
238 294
239 void TrayBubbleView::SetBubbleBorder(int arrow_offset) {
240 DCHECK(GetWidget());
241 TrayBubbleBorder* bubble_border = new TrayBubbleBorder(
242 this, anchor_view(), arrow_location(), arrow_offset);
243 GetBubbleFrameView()->SetBubbleBorder(bubble_border);
244 // Recalculate size with new border.
245 SizeToContents();
246 }
247
248 void TrayBubbleView::UpdateBubble() { 295 void TrayBubbleView::UpdateBubble() {
249 SizeToContents(); 296 SizeToContents();
250 GetWidget()->GetRootView()->SchedulePaint(); 297 GetWidget()->GetRootView()->SchedulePaint();
251 } 298 }
252 299
253 void TrayBubbleView::SetMaxHeight(int height) { 300 void TrayBubbleView::SetMaxHeight(int height) {
jennyz 2012/07/31 02:29:47 This function seems not called in the new code pat
stevenjb 2012/07/31 16:35:28 Still called in SystemTrayBubble::UpdateView()
254 max_height_ = height; 301 params_.max_height = height;
255 if (GetWidget()) 302 if (GetWidget())
256 SizeToContents(); 303 SizeToContents();
257 } 304 }
258 305
259 void TrayBubbleView::Init() { 306 void TrayBubbleView::Init() {
260 views::BoxLayout* layout = 307 views::BoxLayout* layout =
261 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); 308 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
262 layout->set_spread_blank_space(true); 309 layout->set_spread_blank_space(true);
263 SetLayoutManager(layout); 310 SetLayoutManager(layout);
264 set_background(NULL); 311 set_background(NULL);
265 } 312 }
266 313
267 gfx::Rect TrayBubbleView::GetAnchorRect() { 314 gfx::Rect TrayBubbleView::GetAnchorRect() {
268 gfx::Rect rect; 315 gfx::Rect rect;
269 if (host_) 316
270 rect = host_->GetAnchorRect(); 317 if (anchor_widget()->IsVisible()) {
318 rect = anchor_widget()->GetWindowBoundsInScreen();
319 if (params_.anchor_type == ANCHOR_TYPE_TRAY) {
320 if (params_.shelf_alignment == SHELF_ALIGNMENT_BOTTOM) {
321 bool rtl = base::i18n::IsRTL();
322 rect.Inset(
323 rtl ? kPaddingFromRightEdgeOfScreenBottomAlignment : 0,
324 0,
325 rtl ? 0 : kPaddingFromRightEdgeOfScreenBottomAlignment,
326 kPaddingFromBottomOfScreenBottomAlignment);
327 } else if (params_.shelf_alignment == SHELF_ALIGNMENT_LEFT) {
328 rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
329 kPaddingFromBottomOfScreenVerticalAlignment);
330 } else {
331 rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
332 0, 0, kPaddingFromBottomOfScreenVerticalAlignment);
333 }
334 } else if (params_.anchor_type == ANCHOR_TYPE_BUBBLE) {
335 // Invert the offsets to align with the bubble below.
336 if (params_.shelf_alignment == SHELF_ALIGNMENT_LEFT) {
337 rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
338 0, 0, kPaddingFromBottomOfScreenVerticalAlignment);
339 } else if (params_.shelf_alignment == SHELF_ALIGNMENT_RIGHT) {
340 rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
341 kPaddingFromBottomOfScreenVerticalAlignment);
342 }
343 }
344 }
345
271 // TODO(jennyz): May need to add left/right alignment in the following code. 346 // TODO(jennyz): May need to add left/right alignment in the following code.
272 if (rect.IsEmpty()) { 347 if (rect.IsEmpty()) {
273 rect = gfx::Screen::GetPrimaryDisplay().bounds(); 348 rect = gfx::Screen::GetPrimaryDisplay().bounds();
274 rect = gfx::Rect( 349 rect = gfx::Rect(
275 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : 350 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment :
276 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, 351 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment,
277 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, 352 rect.height() - kPaddingFromBottomOfScreenBottomAlignment,
278 0, 0); 353 0, 0);
279 } 354 }
280 return rect; 355 return rect;
281 } 356 }
282 357
283 gfx::Rect TrayBubbleView::GetBubbleBounds() { 358 gfx::Rect TrayBubbleView::GetBubbleBounds() {
284 // Same as BubbleDelegateView implementation, but don't try mirroring. 359 // Same as BubbleDelegateView implementation, but don't try mirroring.
285 return GetBubbleFrameView()->GetUpdatedWindowBounds( 360 return GetBubbleFrameView()->GetUpdatedWindowBounds(
286 GetAnchorRect(), GetPreferredSize(), false /*try_mirroring_arrow*/); 361 GetAnchorRect(), GetPreferredSize(), false /*try_mirroring_arrow*/);
287 } 362 }
288 363
289 bool TrayBubbleView::CanActivate() const { 364 bool TrayBubbleView::CanActivate() const {
290 return can_activate_; 365 return params_.can_activate;
366 }
367
368 // Overridden to create BubbleFrameView and set the border to TrayBubbleBorder
369 // (instead of creating a default BubbleBorder and replacing it).
370 views::NonClientFrameView* TrayBubbleView::CreateNonClientFrameView(
371 views::Widget* widget) {
372 TrayBubbleBorder* bubble_border = new TrayBubbleBorder(
373 this, anchor_view(),
374 arrow_location(), params_.arrow_offset, params_.arrow_color);
375 return new views::BubbleFrameView(margins(), bubble_border);
291 } 376 }
292 377
293 gfx::Size TrayBubbleView::GetPreferredSize() { 378 gfx::Size TrayBubbleView::GetPreferredSize() {
294 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); 379 gfx::Size size = views::BubbleDelegateView::GetPreferredSize();
295 int height = size.height(); 380 int height = size.height();
296 if (max_height_ != 0 && height > max_height_) 381 if (params_.max_height != 0 && height > params_.max_height)
297 height = max_height_; 382 height = params_.max_height;
298 return gfx::Size(bubble_width_, height); 383 return gfx::Size(params_.bubble_width, height);
299 } 384 }
300 385
301 void TrayBubbleView::OnMouseEntered(const views::MouseEvent& event) { 386 void TrayBubbleView::OnMouseEntered(const views::MouseEvent& event) {
302 if (host_) 387 if (host_)
303 host_->OnMouseEnteredView(); 388 host_->OnMouseEnteredView();
304 } 389 }
305 390
306 void TrayBubbleView::OnMouseExited(const views::MouseEvent& event) { 391 void TrayBubbleView::OnMouseExited(const views::MouseEvent& event) {
307 if (host_) 392 if (host_)
308 host_->OnMouseExitedView(); 393 host_->OnMouseExitedView();
309 } 394 }
310 395
311 void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { 396 void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) {
312 if (can_activate_) { 397 if (params_.can_activate) {
313 state->role = ui::AccessibilityTypes::ROLE_WINDOW; 398 state->role = ui::AccessibilityTypes::ROLE_WINDOW;
314 state->name = l10n_util::GetStringUTF16( 399 state->name = l10n_util::GetStringUTF16(
315 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); 400 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME);
316 } 401 }
317 } 402 }
318 403
319 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { 404 void TrayBubbleView::ChildPreferredSizeChanged(View* child) {
320 SizeToContents(); 405 SizeToContents();
321 } 406 }
322 407
(...skipping 10 matching lines...) Expand all
333 TrayBubbleView::Host::Host() 418 TrayBubbleView::Host::Host()
334 : widget_(NULL), 419 : widget_(NULL),
335 tray_view_(NULL) { 420 tray_view_(NULL) {
336 Shell::GetInstance()->AddEnvEventFilter(this); 421 Shell::GetInstance()->AddEnvEventFilter(this);
337 } 422 }
338 423
339 TrayBubbleView::Host::~Host() { 424 TrayBubbleView::Host::~Host() {
340 Shell::GetInstance()->RemoveEnvEventFilter(this); 425 Shell::GetInstance()->RemoveEnvEventFilter(this);
341 } 426 }
342 427
343 void TrayBubbleView::Host::InitializeHost(views::Widget* widget, 428 void TrayBubbleView::Host::InitializeAndShowBubble(views::Widget* widget,
344 views::View* tray_view) { 429 TrayBubbleView* bubble_view,
430 views::View* tray_view) {
345 widget_ = widget; 431 widget_ = widget;
346 tray_view_ = tray_view; 432 tray_view_ = tray_view;
433
434 // Must occur after call to BubbleDelegateView::CreateBubble().
435 bubble_view->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
436
437 // Setup animation.
438 ash::SetWindowVisibilityAnimationType(
439 widget->GetNativeWindow(),
440 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
441 ash::SetWindowVisibilityAnimationTransition(
442 widget->GetNativeWindow(),
443 ash::ANIMATE_BOTH);
444 ash::SetWindowVisibilityAnimationDuration(
445 widget->GetNativeWindow(),
446 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS));
447
448 bubble_view->Show();
449 bubble_view->UpdateBubble();
347 } 450 }
348 451
349 bool TrayBubbleView::Host::PreHandleKeyEvent(aura::Window* target, 452 bool TrayBubbleView::Host::PreHandleKeyEvent(aura::Window* target,
350 aura::KeyEvent* event) { 453 aura::KeyEvent* event) {
351 return false; 454 return false;
352 } 455 }
353 456
354 bool TrayBubbleView::Host::PreHandleMouseEvent(aura::Window* target, 457 bool TrayBubbleView::Host::PreHandleMouseEvent(aura::Window* target,
355 aura::MouseEvent* event) { 458 aura::MouseEvent* event) {
356 if (event->type() == ui::ET_MOUSE_PRESSED) 459 if (event->type() == ui::ET_MOUSE_PRESSED)
(...skipping 30 matching lines...) Expand all
387 return; 490 return;
388 } 491 }
389 // Handle clicking outside the bubble and tray. We don't block the event, so 492 // Handle clicking outside the bubble and tray. We don't block the event, so
390 // it will also be handled by whatever widget was clicked on. 493 // it will also be handled by whatever widget was clicked on.
391 OnClickedOutsideView(); 494 OnClickedOutsideView();
392 } 495 }
393 496
394 497
395 } // namespace internal 498 } // namespace internal
396 } // namespace ash 499 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698