• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/ui/views/browser_bubble.h"
6 
7 #include "chrome/browser/ui/views/frame/browser_view.h"
8 #if defined(OS_WIN)
9 #include "chrome/browser/external_tab_container_win.h"
10 #endif
11 #include "views/widget/root_view.h"
12 #include "views/window/window.h"
13 
14 namespace {
15 
GetBubbleHostFromFrame(views::Widget * frame)16 BrowserBubbleHost* GetBubbleHostFromFrame(views::Widget* frame) {
17   if (!frame)
18     return NULL;
19 
20   BrowserBubbleHost* bubble_host = NULL;
21   views::Window* window = frame->GetWindow();
22   if (window) {
23     bubble_host = BrowserView::GetBrowserViewForNativeWindow(
24         window->GetNativeWindow());
25     DCHECK(bubble_host);
26   }
27 
28   return bubble_host;
29 }
30 
31 }  // namespace
32 
BrowserBubble(views::View * view,views::Widget * frame,const gfx::Rect & relative_to,BubbleBorder::ArrowLocation arrow_location)33 BrowserBubble::BrowserBubble(views::View* view,
34                              views::Widget* frame,
35                              const gfx::Rect& relative_to,
36                              BubbleBorder::ArrowLocation arrow_location)
37     : frame_(frame),
38       view_(view),
39       relative_to_(relative_to),
40       arrow_location_(arrow_location),
41       visible_(false),
42       delegate_(NULL),
43       attached_(false),
44       bubble_host_(GetBubbleHostFromFrame(frame)) {
45   // Keep relative_to_ in frame-relative coordinates to aid in drag
46   // positioning.
47   gfx::Point origin = relative_to_.origin();
48   views::View::ConvertPointToView(NULL, frame_->GetRootView(), &origin);
49   relative_to_.set_origin(origin);
50 
51   InitPopup();
52 }
53 
~BrowserBubble()54 BrowserBubble::~BrowserBubble() {
55   DCHECK(!attached_);
56   popup_->Close();
57 
58   // Don't call DetachFromBrowser from here.  It needs to talk to the
59   // BrowserView to deregister itself, and if BrowserBubble is owned
60   // by a child of BrowserView, then it's possible that this stack frame
61   // is a descendant of BrowserView's destructor, which leads to problems.
62   // In that case, Detach doesn't need to get called anyway since BrowserView
63   // will do the necessary cleanup.
64 }
65 
DetachFromBrowser()66 void BrowserBubble::DetachFromBrowser() {
67   DCHECK(attached_);
68   if (!attached_)
69     return;
70   attached_ = false;
71 
72   if (bubble_host_)
73     bubble_host_->DetachBrowserBubble(this);
74 }
75 
AttachToBrowser()76 void BrowserBubble::AttachToBrowser() {
77   DCHECK(!attached_);
78   if (attached_)
79     return;
80 
81   if (bubble_host_)
82     bubble_host_->AttachBrowserBubble(this);
83 
84   attached_ = true;
85 }
86 
BrowserWindowMoved()87 void BrowserBubble::BrowserWindowMoved() {
88   if (delegate_)
89     delegate_->BubbleBrowserWindowMoved(this);
90   else
91     Hide();
92   if (visible_)
93     Reposition();
94 }
95 
BrowserWindowClosing()96 void BrowserBubble::BrowserWindowClosing() {
97   if (delegate_)
98     delegate_->BubbleBrowserWindowClosing(this);
99   else
100     Hide();
101 }
102 
SetBounds(int x,int y,int w,int h)103 void BrowserBubble::SetBounds(int x, int y, int w, int h) {
104   // If the UI layout is RTL, we don't need to mirror coordinates, since
105   // View logic will do that for us.
106   bounds_.SetRect(x, y, w, h);
107   Reposition();
108 }
109 
MoveTo(int x,int y)110 void BrowserBubble::MoveTo(int x, int y) {
111   SetBounds(x, y, bounds_.width(), bounds_.height());
112 }
113 
Reposition()114 void BrowserBubble::Reposition() {
115   gfx::Point top_left;
116   views::View::ConvertPointToScreen(frame_->GetRootView(), &top_left);
117   MovePopup(top_left.x() + bounds_.x(),
118             top_left.y() + bounds_.y(),
119             bounds_.width(),
120             bounds_.height());
121 }
122 
GetAbsoluteRelativeTo()123 gfx::Rect BrowserBubble::GetAbsoluteRelativeTo() {
124   // |relative_to_| is in browser-relative coordinates, so convert it to
125   // screen coordinates for use in placing the popup widgets.
126   gfx::Rect relative_rect = relative_to_;
127   gfx::Point relative_origin = relative_rect.origin();
128   views::View::ConvertPointToScreen(frame_->GetRootView(), &relative_origin);
129   relative_rect.set_origin(relative_origin);
130 
131   return relative_rect;
132 }
133 
SetAbsoluteBounds(const gfx::Rect & window_bounds)134 void BrowserBubble::SetAbsoluteBounds(const gfx::Rect& window_bounds) {
135   // Convert screen coordinates to frame relative.
136   gfx::Point relative_origin = window_bounds.origin();
137   views::View::ConvertPointToView(NULL, frame_->GetRootView(),
138                                   &relative_origin);
139   SetBounds(relative_origin.x(), relative_origin.y(),
140             window_bounds.width(), window_bounds.height());
141 }
142