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 <vector>
8
9 #include "chrome/browser/ui/views/bubble/border_contents.h"
10 #include "chrome/browser/ui/views/frame/browser_view.h"
11 #include "views/widget/root_view.h"
12 #include "views/widget/widget_gtk.h"
13
14 #if defined(OS_CHROMEOS)
15 #include "chrome/browser/chromeos/wm_ipc.h"
16 #include "third_party/cros/chromeos_wm_ipc_enums.h"
17 #endif
18
19 using std::vector;
20
21 namespace {
22
23 class BubbleWidget : public views::WidgetGtk {
24 public:
BubbleWidget(BrowserBubble * bubble)25 explicit BubbleWidget(BrowserBubble* bubble)
26 : views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW),
27 bubble_(bubble),
28 border_contents_(new BorderContents) {
29 border_contents_->Init();
30 }
31
ShowAndActivate(bool activate)32 void ShowAndActivate(bool activate) {
33 // TODO: honor activate.
34 views::WidgetGtk::Show();
35 }
36
Close()37 virtual void Close() {
38 if (!bubble_)
39 return; // We have already been closed.
40 if (IsActive()) {
41 BrowserBubble::Delegate* delegate = bubble_->delegate();
42 if (delegate)
43 delegate->BubbleLostFocus(bubble_, false);
44 }
45 views::WidgetGtk::Close();
46 bubble_ = NULL;
47 }
48
Hide()49 virtual void Hide() {
50 if (IsActive()&& bubble_) {
51 BrowserBubble::Delegate* delegate = bubble_->delegate();
52 if (delegate)
53 delegate->BubbleLostFocus(bubble_, false);
54 }
55 views::WidgetGtk::Hide();
56 }
57
IsActiveChanged()58 virtual void IsActiveChanged() {
59 if (IsActive() || !bubble_)
60 return;
61 BrowserBubble::Delegate* delegate = bubble_->delegate();
62 if (!delegate) {
63 bubble_->DetachFromBrowser();
64 delete bubble_;
65 return;
66 }
67
68 // TODO(jcampan): http://crbugs.com/29131 Check if the window we are losing
69 // focus to is a child window and pass that to the call
70 // below.
71 delegate->BubbleLostFocus(bubble_, false);
72 }
73
OnFocusIn(GtkWidget * widget,GdkEventFocus * event)74 virtual gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event) {
75 if (bubble_ && bubble_->delegate())
76 bubble_->delegate()->BubbleGotFocus(bubble_);
77 return views::WidgetGtk::OnFocusIn(widget, event);
78 }
79
border_contents()80 BorderContents* border_contents() {
81 return border_contents_;
82 }
83
84 private:
85 BrowserBubble* bubble_;
86 BorderContents* border_contents_; // Owned by root view of this widget.
87
88 DISALLOW_COPY_AND_ASSIGN(BubbleWidget);
89 };
90
91 } // namespace
92
InitPopup()93 void BrowserBubble::InitPopup() {
94 // TODO(port)
95 BubbleWidget* pop = new BubbleWidget(this);
96 pop->MakeTransparent();
97 pop->make_transient_to_parent();
98 pop->Init(frame_->GetNativeView(), gfx::Rect());
99 #if defined(OS_CHROMEOS)
100 {
101 vector<int> params;
102 params.push_back(0); // don't show while screen is locked
103 chromeos::WmIpc::instance()->SetWindowType(
104 pop->GetNativeView(),
105 chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
106 ¶ms);
107 }
108 #endif
109
110 views::View* contents_view = new views::View;
111
112 // We add |contents_view| to ourselves before the AddChildView() call below so
113 // that when |contents| gets added, it will already have a widget, and thus
114 // any NativeButtons it creates in ViewHierarchyChanged() will be functional
115 // (e.g. calling SetChecked() on checkboxes is safe).
116 pop->SetContentsView(contents_view);
117
118 // Added border_contents before |view_| so it will paint under it.
119 contents_view->AddChildView(pop->border_contents());
120 contents_view->AddChildView(view_);
121
122 popup_ = pop;
123
124 ResizeToView();
125 Reposition();
126 AttachToBrowser();
127 }
128
MovePopup(int x,int y,int w,int h)129 void BrowserBubble::MovePopup(int x, int y, int w, int h) {
130 views::WidgetGtk* pop = static_cast<views::WidgetGtk*>(popup_);
131 pop->SetBounds(gfx::Rect(x, y, w, h));
132 }
133
Show(bool activate)134 void BrowserBubble::Show(bool activate) {
135 if (visible_)
136 return;
137 static_cast<BubbleWidget*>(popup_)->ShowAndActivate(activate);
138 visible_ = true;
139 }
140
Hide()141 void BrowserBubble::Hide() {
142 if (!visible_)
143 return;
144 views::WidgetGtk* pop = static_cast<views::WidgetGtk*>(popup_);
145 pop->Hide();
146 visible_ = false;
147 }
148
ResizeToView()149 void BrowserBubble::ResizeToView() {
150 BorderContents* border_contents =
151 static_cast<BubbleWidget*>(popup_)->border_contents();
152
153 // Calculate and set the bounds for all windows and views.
154 gfx::Rect window_bounds;
155 gfx::Rect contents_bounds;
156 border_contents->SizeAndGetBounds(GetAbsoluteRelativeTo(),
157 arrow_location_, false, view_->size(),
158 &contents_bounds, &window_bounds);
159
160 border_contents->SetBoundsRect(gfx::Rect(gfx::Point(), window_bounds.size()));
161 view_->SetBoundsRect(contents_bounds);
162
163 SetAbsoluteBounds(window_bounds);
164 }
165