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

Side by Side Diff: chrome/browser/ui/views/bubble/bubble.cc

Issue 8761012: Remove the old views bubble code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync. Created 9 years 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/views/bubble/bubble.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/bubble/bubble.h"
6
7 #include <vector>
8
9 #include "chrome/browser/ui/views/bubble/border_contents.h"
10 #include "chrome/common/chrome_notification_types.h"
11 #include "ui/base/animation/slide_animation.h"
12 #include "ui/base/keycodes/keyboard_codes.h"
13 #include "ui/gfx/color_utils.h"
14 #include "ui/views/layout/fill_layout.h"
15 #include "ui/views/widget/widget.h"
16 #include "ui/views/window/client_view.h"
17
18 #if defined(OS_CHROMEOS) && defined(TOOLKIT_USES_GTK)
19 #include "chrome/browser/chromeos/legacy_window_manager/wm_ipc.h"
20 #include "third_party/cros_system_api/window_manager/chromeos_wm_ipc_enums.h"
21 #endif
22
23 #if defined(OS_WIN) && !defined(USE_AURA)
24 #include "chrome/browser/ui/views/bubble/border_widget_win.h"
25 #endif
26
27 using std::vector;
28
29 // How long the fade should last for.
30 static const int kHideFadeDurationMS = 200;
31
32 // Background color of the bubble.
33 #if defined(OS_WIN) && !defined(USE_AURA)
34 const SkColor Bubble::kBackgroundColor =
35 color_utils::GetSysSkColor(COLOR_WINDOW);
36 #else
37 // TODO(beng): source from theme provider.
38 const SkColor Bubble::kBackgroundColor = SK_ColorWHITE;
39 #endif
40
41 // BubbleDelegate ---------------------------------------------------------
42
43 string16 BubbleDelegate::GetAccessibleName() {
44 return string16();
45 }
46
47 // Bubble -----------------------------------------------------------------
48
49 // static
50 Bubble* Bubble::Show(views::Widget* parent,
51 const gfx::Rect& position_relative_to,
52 views::BubbleBorder::ArrowLocation arrow_location,
53 views::BubbleBorder::BubbleAlignment alignment,
54 views::View* contents,
55 BubbleDelegate* delegate) {
56 Bubble* bubble = new Bubble;
57 bubble->InitBubble(parent, position_relative_to, arrow_location, alignment,
58 contents, delegate);
59
60 // Register the Escape accelerator for closing.
61 bubble->RegisterEscapeAccelerator();
62
63 if (delegate)
64 delegate->BubbleShown();
65
66 return bubble;
67 }
68
69 #if defined(OS_CHROMEOS)
70 // static
71 Bubble* Bubble::ShowFocusless(
72 views::Widget* parent,
73 const gfx::Rect& position_relative_to,
74 views::BubbleBorder::ArrowLocation arrow_location,
75 views::BubbleBorder::BubbleAlignment alignment,
76 views::View* contents,
77 BubbleDelegate* delegate,
78 bool show_while_screen_is_locked) {
79 Bubble* bubble = new Bubble(views::Widget::InitParams::TYPE_POPUP,
80 show_while_screen_is_locked);
81 bubble->InitBubble(parent, position_relative_to, arrow_location, alignment,
82 contents, delegate);
83 return bubble;
84 }
85 #endif
86
87 void Bubble::Close() {
88 if (show_status_ != kOpen)
89 return;
90
91 show_status_ = kClosing;
92
93 if (fade_away_on_close_)
94 FadeOut();
95 else
96 DoClose(false);
97 }
98
99 void Bubble::AnimationEnded(const ui::Animation* animation) {
100 if (static_cast<int>(animation_->GetCurrentValue()) == 0) {
101 // When fading out we just need to close the bubble at the end
102 DoClose(false);
103 } else {
104 #if defined(OS_WIN) && !defined(USE_AURA)
105 // When fading in we need to remove the layered window style flag, since
106 // that style prevents some bubble content from working properly.
107 SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) & ~WS_EX_LAYERED);
108 #endif
109 }
110 }
111
112 void Bubble::AnimationProgressed(const ui::Animation* animation) {
113 // Set the opacity for the main contents window.
114 unsigned char opacity = static_cast<unsigned char>(
115 animation_->GetCurrentValue() * 255);
116 #if defined(OS_WIN) && !defined(USE_AURA)
117 SetLayeredWindowAttributes(GetNativeView(), 0,
118 static_cast<byte>(opacity), LWA_ALPHA);
119 contents_->SchedulePaint();
120
121 // Also fade in/out the bubble border window.
122 border_->SetOpacity(opacity);
123 border_->border_contents()->SchedulePaint();
124 #else
125 SetOpacity(opacity);
126 border_contents_->SchedulePaint();
127 #endif
128 }
129
130 Bubble::Bubble()
131 :
132 #if defined(USE_AURA)
133 views::NativeWidgetAura(new views::Widget),
134 #elif defined(OS_WIN)
135 views::NativeWidgetWin(new views::Widget),
136 #elif defined(TOOLKIT_USES_GTK)
137 views::NativeWidgetGtk(new views::Widget),
138 #endif
139 #if defined(OS_WIN) && !defined(USE_AURA)
140 border_(NULL),
141 #else
142 border_contents_(NULL),
143 #endif
144 delegate_(NULL),
145 show_status_(kOpen),
146 fade_away_on_close_(false),
147 close_on_deactivate_(true),
148 #if defined(TOOLKIT_USES_GTK)
149 type_(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS),
150 #endif
151 #if defined(OS_CHROMEOS)
152 show_while_screen_is_locked_(false),
153 #endif
154 arrow_location_(views::BubbleBorder::NONE),
155 contents_(NULL),
156 accelerator_registered_(false) {
157 }
158
159 #if defined(OS_CHROMEOS)
160 Bubble::Bubble(views::Widget::InitParams::Type type,
161 bool show_while_screen_is_locked)
162 #if defined(USE_AURA)
163 : views::NativeWidgetAura(new views::Widget),
164 #else
165 : views::NativeWidgetGtk(new views::Widget),
166 #endif
167 border_contents_(NULL),
168 delegate_(NULL),
169 show_status_(kOpen),
170 fade_away_on_close_(false),
171 #if defined(TOOLKIT_USES_GTK)
172 type_(type),
173 #endif
174 show_while_screen_is_locked_(show_while_screen_is_locked),
175 arrow_location_(views::BubbleBorder::NONE),
176 contents_(NULL),
177 accelerator_registered_(false) {
178 }
179 #endif
180
181 Bubble::~Bubble() {
182 }
183
184 void Bubble::InitBubble(views::Widget* parent,
185 const gfx::Rect& position_relative_to,
186 views::BubbleBorder::ArrowLocation arrow_location,
187 views::BubbleBorder::BubbleAlignment alignment,
188 views::View* contents,
189 BubbleDelegate* delegate) {
190 delegate_ = delegate;
191 position_relative_to_ = position_relative_to;
192 arrow_location_ = arrow_location;
193 contents_ = contents;
194 const bool fade_in = delegate_ && delegate_->FadeInOnShow();
195
196 // Create the main window.
197 #if defined(USE_AURA)
198 views::Widget* parent_window = parent->GetTopLevelWidget();
199 if (parent_window)
200 parent_window->DisableInactiveRendering();
201 views::Widget::InitParams params;
202 params.transparent = true;
203 params.parent_widget = parent;
204 params.native_widget = this;
205 GetWidget()->Init(params);
206 if (fade_in)
207 SetOpacity(0);
208 #elif defined(OS_WIN)
209 views::Widget* parent_window = parent->GetTopLevelWidget();
210 if (parent_window)
211 parent_window->DisableInactiveRendering();
212 set_window_style(WS_POPUP | WS_CLIPCHILDREN);
213 int extended_style = WS_EX_TOOLWINDOW;
214 // During FadeIn we need to turn on the layered window style to deal with
215 // transparency. This flag needs to be reset after fading in is complete.
216 if (fade_in)
217 extended_style |= WS_EX_LAYERED;
218 set_window_ex_style(extended_style);
219
220 DCHECK(!border_);
221 border_ = new BorderWidgetWin();
222
223 border_->InitBorderWidgetWin(CreateBorderContents(), parent->GetNativeView());
224 border_->border_contents()->SetBackgroundColor(kBackgroundColor);
225 border_->border_contents()->SetAlignment(alignment);
226
227 // We make the BorderWidgetWin the owner of the Bubble HWND, so that the
228 // latter is displayed on top of the former.
229 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
230 params.parent = border_->GetNativeView();
231 params.native_widget = this;
232 GetWidget()->Init(params);
233
234 if (fade_in) {
235 border_->SetOpacity(0);
236 GetWidget()->SetOpacity(0);
237 }
238 SetWindowText(GetNativeView(), delegate_->GetAccessibleName().c_str());
239 #elif defined(TOOLKIT_USES_GTK)
240 views::Widget::InitParams params(type_);
241 params.transparent = true;
242 params.parent_widget = parent;
243 params.native_widget = this;
244 GetWidget()->Init(params);
245 if (fade_in)
246 SetOpacity(0);
247 #if defined(OS_CHROMEOS) && defined(TOOLKIT_USES_GTK)
248 {
249 vector<int> params;
250 params.push_back(show_while_screen_is_locked_ ? 1 : 0);
251 chromeos::WmIpc::instance()->SetWindowType(
252 GetNativeView(),
253 chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
254 &params);
255 }
256 #endif
257 #endif
258
259 // Create a View to hold the contents of the main window.
260 views::View* contents_view = new views::View;
261 // We add |contents_view| to ourselves before the AddChildView() call below so
262 // that when |contents| gets added, it will already have a widget, and thus
263 // any NativeButtons it creates in ViewHierarchyChanged() will be functional
264 // (e.g. calling SetChecked() on checkboxes is safe).
265 GetWidget()->SetContentsView(contents_view);
266 // Adding |contents| as a child has to be done before we call
267 // contents->GetPreferredSize() below, since some supplied views don't
268 // actually initialize themselves until they're added to a hierarchy.
269 contents_view->AddChildView(contents);
270
271 // Calculate and set the bounds for all windows and views.
272 gfx::Rect window_bounds;
273
274 #if defined(OS_WIN) && !defined(USE_AURA)
275 // Initialize and position the border window.
276 window_bounds = border_->SizeAndGetBounds(position_relative_to,
277 arrow_location,
278 contents->GetPreferredSize());
279
280 // Make |contents| take up the entire contents view.
281 contents_view->SetLayoutManager(new views::FillLayout);
282
283 // Paint the background color behind the contents.
284 contents_view->set_background(
285 views::Background::CreateSolidBackground(kBackgroundColor));
286 #else
287 // Create a view to paint the border and background.
288 border_contents_ = CreateBorderContents();
289 border_contents_->Init();
290 border_contents_->SetBackgroundColor(kBackgroundColor);
291 border_contents_->SetAlignment(alignment);
292 gfx::Rect contents_bounds;
293 border_contents_->SizeAndGetBounds(position_relative_to,
294 arrow_location, false, contents->GetPreferredSize(),
295 &contents_bounds, &window_bounds);
296 // This new view must be added before |contents| so it will paint under it.
297 contents_view->AddChildViewAt(border_contents_, 0);
298
299 // |contents_view| has no layout manager, so we have to explicitly position
300 // its children.
301 border_contents_->SetBoundsRect(
302 gfx::Rect(gfx::Point(), window_bounds.size()));
303 contents->SetBoundsRect(contents_bounds);
304 #endif
305 GetWidget()->SetBounds(window_bounds);
306
307 // Show the window.
308 #if defined(USE_AURA)
309 GetWidget()->Show();
310 #elif defined(OS_WIN)
311 border_->ShowWindow(SW_SHOW);
312 ShowWindow(SW_SHOW);
313 #elif defined(TOOLKIT_USES_GTK)
314 GetWidget()->Show();
315 #endif
316
317 if (fade_in)
318 FadeIn();
319 }
320
321 void Bubble::RegisterEscapeAccelerator() {
322 GetWidget()->GetFocusManager()->RegisterAccelerator(
323 ui::Accelerator(ui::VKEY_ESCAPE, false, false, false), this);
324 accelerator_registered_ = true;
325 }
326
327 void Bubble::UnregisterEscapeAccelerator() {
328 DCHECK(accelerator_registered_);
329 GetWidget()->GetFocusManager()->UnregisterAccelerator(
330 ui::Accelerator(ui::VKEY_ESCAPE, false, false, false), this);
331 accelerator_registered_ = false;
332 }
333
334 BorderContents* Bubble::CreateBorderContents() {
335 return new BorderContents();
336 }
337
338 void Bubble::SizeToContents() {
339 gfx::Rect window_bounds;
340
341 #if defined(OS_WIN) && !defined(USE_AURA)
342 // Initialize and position the border window.
343 window_bounds = border_->SizeAndGetBounds(position_relative_to_,
344 arrow_location_,
345 contents_->GetPreferredSize());
346 #else
347 gfx::Rect contents_bounds;
348 border_contents_->SizeAndGetBounds(position_relative_to_,
349 arrow_location_, false, contents_->GetPreferredSize(),
350 &contents_bounds, &window_bounds);
351 // |contents_view| has no layout manager, so we have to explicitly position
352 // its children.
353 border_contents_->SetBoundsRect(
354 gfx::Rect(gfx::Point(), window_bounds.size()));
355 contents_->SetBoundsRect(contents_bounds);
356 #endif
357 GetWidget()->SetBounds(window_bounds);
358 }
359
360 #if defined(USE_AURA)
361 void Bubble::OnLostActive() {
362 GetWidget()->Close();
363 }
364 #elif defined(OS_WIN)
365 void Bubble::OnActivate(UINT action, BOOL minimized, HWND window) {
366 // The popup should close when it is deactivated.
367 if (action == WA_INACTIVE) {
368 if (close_on_deactivate_)
369 GetWidget()->Close();
370 } else if (action == WA_ACTIVE) {
371 DCHECK(GetWidget()->GetRootView()->has_children());
372 GetWidget()->GetRootView()->child_at(0)->RequestFocus();
373 }
374 }
375 #elif defined(TOOLKIT_USES_GTK)
376 void Bubble::OnActiveChanged() {
377 if (!GetWidget()->IsActive())
378 GetWidget()->Close();
379 }
380 #endif
381
382 void Bubble::DoClose(bool closed_by_escape) {
383 if (show_status_ == kClosed)
384 return;
385
386 if (accelerator_registered_)
387 UnregisterEscapeAccelerator();
388 if (delegate_)
389 delegate_->BubbleClosing(this, closed_by_escape);
390 FOR_EACH_OBSERVER(Observer, observer_list_, OnBubbleClosing());
391 show_status_ = kClosed;
392 #if defined(OS_WIN) && !defined(USE_AURA)
393 border_->Close();
394 #endif
395 #if defined(USE_AURA)
396 NativeWidgetAura::Close();
397 #elif defined(OS_WIN)
398 NativeWidgetWin::Close();
399 #elif defined(TOOLKIT_USES_GTK)
400 NativeWidgetGtk::Close();
401 #endif
402 }
403
404 void Bubble::FadeIn() {
405 Fade(true); // |fade_in|.
406 }
407
408 void Bubble::FadeOut() {
409 #if defined(OS_WIN) && !defined(USE_AURA)
410 // The contents window cannot have the layered flag on by default, since its
411 // content doesn't always work inside a layered window, but when animating it
412 // is ok to set that style on the window for the purpose of fading it out.
413 SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) | WS_EX_LAYERED);
414 // This must be the very next call, otherwise we can get flicker on close.
415 SetLayeredWindowAttributes(GetNativeView(), 0,
416 static_cast<byte>(255), LWA_ALPHA);
417 #elif defined(USE_AURA)
418 NOTIMPLEMENTED();
419 #endif
420
421 Fade(false); // |fade_in|.
422 }
423
424 void Bubble::Fade(bool fade_in) {
425 animation_.reset(new ui::SlideAnimation(this));
426 animation_->SetSlideDuration(kHideFadeDurationMS);
427 animation_->SetTweenType(ui::Tween::LINEAR);
428
429 animation_->Reset(fade_in ? 0.0 : 1.0);
430 if (fade_in)
431 animation_->Show();
432 else
433 animation_->Hide();
434 }
435
436 bool Bubble::AcceleratorPressed(const ui::Accelerator& accelerator) {
437 if (!delegate_ || delegate_->CloseOnEscape()) {
438 DoClose(true);
439 return true;
440 }
441 return false;
442 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/bubble/bubble.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698