1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/overflow_bubble_view.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <algorithm>
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/root_window_controller.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_layout_manager.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_view.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shell.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shell_window_ids.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/events/event.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gfx/insets.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gfx/screen.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/bubble/bubble_frame_view.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/widget/widget.h"
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace ash {
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace internal {
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace {
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Max bubble size to screen size ratio.
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const float kMaxBubbleSizeToScreenRatio = 0.5f;
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Inner padding in pixels for shelf view inside bubble.
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kPadding = 2;
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Padding space in pixels between ShelfView's left/top edge to its contents.
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kShelfViewLeadingInset = 8;
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)OverflowBubbleView::OverflowBubbleView()
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : shelf_view_(NULL) {
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)OverflowBubbleView::~OverflowBubbleView() {
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OverflowBubbleView::InitOverflowBubble(views::View* anchor,
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            ShelfView* shelf_view) {
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // set_anchor_view needs to be called before GetShelfLayoutManagerForLauncher
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // can be called.
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SetAnchorView(anchor);
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  set_arrow(GetBubbleArrow());
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  set_background(NULL);
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  set_color(SkColorSetARGB(kLauncherBackgroundAlpha, 0, 0, 0));
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  set_margins(gfx::Insets(kPadding, kPadding, kPadding, kPadding));
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  set_move_with_anchor(true);
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Overflow bubble should not get focus. If it get focus when it is shown,
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // active state item is changed to running state.
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  set_use_focusless(true);
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Makes bubble view has a layer and clip its children layers.
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SetPaintToLayer(true);
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SetFillsBoundsOpaquely(false);
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  layer()->SetMasksToBounds(true);
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  shelf_view_ = shelf_view;
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AddChildView(shelf_view_);
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  set_parent_window(Shell::GetContainer(
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      internal::kShellWindowId_ShelfBubbleContainer));
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  views::BubbleDelegateView::CreateBubble(this);
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool OverflowBubbleView::IsHorizontalAlignment() const {
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ShelfLayoutManager* shelf_layout_manager = GetShelfLayoutManagerForLauncher();
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return shelf_layout_manager ?
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      shelf_layout_manager->IsHorizontalAlignment() :
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false;
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const gfx::Size OverflowBubbleView::GetContentsSize() const {
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return static_cast<views::View*>(shelf_view_)->GetPreferredSize();
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Gets arrow location based on shelf alignment.
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)views::BubbleBorder::Arrow OverflowBubbleView::GetBubbleArrow() const {
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ShelfLayoutManager* shelf_layout_manager = GetShelfLayoutManagerForLauncher();
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return shelf_layout_manager ?
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      shelf_layout_manager->SelectValueForShelfAlignment(
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          views::BubbleBorder::BOTTOM_LEFT,
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          views::BubbleBorder::LEFT_TOP,
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          views::BubbleBorder::RIGHT_TOP,
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          views::BubbleBorder::TOP_LEFT) :
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      views::BubbleBorder::NONE;
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OverflowBubbleView::ScrollByXOffset(int x_offset) {
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const gfx::Rect visible_bounds(GetContentsBounds());
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const gfx::Size contents_size(GetContentsSize());
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GE(contents_size.width(), visible_bounds.width());
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int x = std::min(contents_size.width() - visible_bounds.width(),
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   std::max(0, scroll_offset_.x() + x_offset));
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scroll_offset_.set_x(x);
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OverflowBubbleView::ScrollByYOffset(int y_offset) {
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const gfx::Rect visible_bounds(GetContentsBounds());
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const gfx::Size contents_size(GetContentsSize());
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GE(contents_size.width(), visible_bounds.width());
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int y = std::min(contents_size.height() - visible_bounds.height(),
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   std::max(0, scroll_offset_.y() + y_offset));
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scroll_offset_.set_y(y);
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)gfx::Size OverflowBubbleView::GetPreferredSize() {
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Size preferred_size = GetContentsSize();
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const gfx::Rect monitor_rect = Shell::GetScreen()->GetDisplayNearestPoint(
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetAnchorRect().CenterPoint()).work_area();
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!monitor_rect.IsEmpty()) {
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (IsHorizontalAlignment()) {
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      preferred_size.set_width(std::min(
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          preferred_size.width(),
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          static_cast<int>(monitor_rect.width() *
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           kMaxBubbleSizeToScreenRatio)));
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      preferred_size.set_height(std::min(
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          preferred_size.height(),
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          static_cast<int>(monitor_rect.height() *
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           kMaxBubbleSizeToScreenRatio)));
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return preferred_size;
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OverflowBubbleView::Layout() {
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  shelf_view_->SetBoundsRect(gfx::Rect(
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      gfx::PointAtOffsetFromOrigin(-scroll_offset_), GetContentsSize()));
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OverflowBubbleView::ChildPreferredSizeChanged(views::View* child) {
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // When contents size is changed, ContentsBounds should be updated before
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // calculating scroll offset.
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SizeToContents();
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Ensures |shelf_view_| is still visible.
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IsHorizontalAlignment())
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScrollByXOffset(0);
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScrollByYOffset(0);
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Layout();
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool OverflowBubbleView::OnMouseWheel(const ui::MouseWheelEvent& event) {
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The MouseWheelEvent was changed to support both X and Y offsets
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // recently, but the behavior of this function was retained to continue
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // using Y offsets only. Might be good to simply scroll in both
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // directions as in OverflowBubbleView::OnScrollEvent.
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IsHorizontalAlignment())
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScrollByXOffset(-event.y_offset());
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScrollByYOffset(-event.y_offset());
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Layout();
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ShelfLayoutManager*
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)OverflowBubbleView::GetShelfLayoutManagerForLauncher() const {
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return GetAnchorView() ?
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ShelfLayoutManager::ForLauncher(
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          GetAnchorView()->GetWidget()->GetNativeView()) :
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      NULL;
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OverflowBubbleView::OnScrollEvent(ui::ScrollEvent* event) {
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ScrollByXOffset(-event->x_offset());
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ScrollByYOffset(-event->y_offset());
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Layout();
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  event->SetHandled();
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)gfx::Rect OverflowBubbleView::GetBubbleBounds() {
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  views::BubbleBorder* border = GetBubbleFrameView()->bubble_border();
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Insets bubble_insets = border->GetInsets();
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int border_size =
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      views::BubbleBorder::is_arrow_on_horizontal(arrow()) ?
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bubble_insets.left() : bubble_insets.top();
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int arrow_offset = border_size + kPadding + kShelfViewLeadingInset +
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ShelfLayoutManager::GetPreferredShelfSize() / 2;
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const gfx::Size content_size = GetPreferredSize();
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  border->set_arrow_offset(arrow_offset);
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const gfx::Rect anchor_rect = GetAnchorRect();
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bubble_rect = GetBubbleFrameView()->GetUpdatedWindowBounds(
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      anchor_rect,
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      content_size,
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      false);
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect monitor_rect = Shell::GetScreen()->GetDisplayNearestPoint(
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      anchor_rect.CenterPoint()).work_area();
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int offset = 0;
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (views::BubbleBorder::is_arrow_on_horizontal(arrow())) {
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (bubble_rect.x() < monitor_rect.x())
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      offset = monitor_rect.x() - bubble_rect.x();
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    else if (bubble_rect.right() > monitor_rect.right())
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      offset = monitor_rect.right() - bubble_rect.right();
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bubble_rect.Offset(offset, 0);
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    border->set_arrow_offset(anchor_rect.CenterPoint().x() - bubble_rect.x());
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (bubble_rect.y() < monitor_rect.y())
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      offset = monitor_rect.y() - bubble_rect.y();
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    else if (bubble_rect.bottom() > monitor_rect.bottom())
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      offset =  monitor_rect.bottom() - bubble_rect.bottom();
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bubble_rect.Offset(0, offset);
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    border->set_arrow_offset(anchor_rect.CenterPoint().y() - bubble_rect.y());
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GetBubbleFrameView()->SchedulePaint();
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return bubble_rect;
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace internal
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace ash
230