| Index: ui/views/bubble/bubble_frame_view.cc
|
| diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
|
| index 9ae1f8d5862799a76d3239555054824cbd076af1..d164194262ee51554250609c209d1575d95634f2 100644
|
| --- a/ui/views/bubble/bubble_frame_view.cc
|
| +++ b/ui/views/bubble/bubble_frame_view.cc
|
| @@ -74,17 +74,22 @@ gfx::Size BubbleFrameView::GetPreferredSize() {
|
|
|
| gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect,
|
| gfx::Size client_size,
|
| - bool try_mirroring_arrow) {
|
| + bool adjust_if_offscreen) {
|
| // Give the contents a margin.
|
| client_size.Enlarge(content_margins_.width(), content_margins_.height());
|
|
|
| - if (try_mirroring_arrow) {
|
| - // Try to mirror the anchoring if the bubble does not fit on the screen.
|
| - MirrorArrowIfOffScreen(true, anchor_rect, client_size);
|
| - MirrorArrowIfOffScreen(false, anchor_rect, client_size);
|
| + const BubbleBorder::ArrowLocation arrow = bubble_border_->arrow_location();
|
| + if (adjust_if_offscreen && BubbleBorder::has_arrow(arrow)) {
|
| + if (!bubble_border_->is_arrow_at_center(arrow)) {
|
| + // Try to mirror the anchoring if the bubble does not fit on the screen.
|
| + MirrorArrowIfOffScreen(true, anchor_rect, client_size);
|
| + MirrorArrowIfOffScreen(false, anchor_rect, client_size);
|
| + } else {
|
| + OffsetArrowIfOffScreen(anchor_rect, client_size);
|
| + }
|
| }
|
|
|
| - // Calculate the bounds with the arrow in its updated location.
|
| + // Calculate the bounds with the arrow in its updated location and offset.
|
| return bubble_border_->GetBounds(anchor_rect, client_size);
|
| }
|
|
|
| @@ -124,4 +129,42 @@ void BubbleFrameView::MirrorArrowIfOffScreen(
|
| }
|
| }
|
|
|
| +void BubbleFrameView::OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect,
|
| + const gfx::Size& client_size) {
|
| + BubbleBorder::ArrowLocation arrow = bubble_border()->arrow_location();
|
| + DCHECK(BubbleBorder::is_arrow_at_center(arrow));
|
| +
|
| + // Get the desired bubble bounds without adjustment.
|
| + bubble_border_->set_arrow_offset(0);
|
| + gfx::Rect window_bounds(bubble_border_->GetBounds(anchor_rect, client_size));
|
| +
|
| + gfx::Rect monitor_rect(GetMonitorBounds(anchor_rect));
|
| + if (monitor_rect.IsEmpty() || monitor_rect.Contains(window_bounds))
|
| + return;
|
| +
|
| + // Calculate off-screen adjustment.
|
| + const bool is_horizontal = BubbleBorder::is_arrow_on_horizontal(arrow);
|
| + int offscreen_adjust = 0;
|
| + if (is_horizontal) {
|
| + if (window_bounds.x() < monitor_rect.x())
|
| + offscreen_adjust = monitor_rect.x() - window_bounds.x();
|
| + else if (window_bounds.right() > monitor_rect.right())
|
| + offscreen_adjust = monitor_rect.right() - window_bounds.right();
|
| + } else {
|
| + if (window_bounds.y() < monitor_rect.y())
|
| + offscreen_adjust = monitor_rect.y() - window_bounds.y();
|
| + else if (window_bounds.bottom() > monitor_rect.bottom())
|
| + offscreen_adjust = monitor_rect.bottom() - window_bounds.bottom();
|
| + }
|
| +
|
| + // For center arrows, arrows are moved in the opposite direction of
|
| + // |offscreen_adjust|, e.g. positive |offscreen_adjust| means bubble
|
| + // window needs to be moved to the right and that means we need to move arrow
|
| + // to the left, and that means negative offset.
|
| + bubble_border_->set_arrow_offset(
|
| + bubble_border_->GetArrowOffset(window_bounds.size()) - offscreen_adjust);
|
| + if (offscreen_adjust)
|
| + SchedulePaint();
|
| +}
|
| +
|
| } // namespace views
|
|
|