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

Side by Side Diff: ui/views/bubble/bubble_delegate.cc

Issue 73533002: Remove the Views bubble double widget hack. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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 | « ui/views/bubble/bubble_delegate.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/bubble/bubble_delegate.h" 5 #include "ui/views/bubble/bubble_delegate.h"
6 6
7 #include "ui/gfx/animation/slide_animation.h" 7 #include "ui/gfx/animation/slide_animation.h"
8 #include "ui/gfx/color_utils.h" 8 #include "ui/gfx/color_utils.h"
9 #include "ui/gfx/rect.h" 9 #include "ui/gfx/rect.h"
10 #include "ui/native_theme/native_theme.h" 10 #include "ui/native_theme/native_theme.h"
(...skipping 21 matching lines...) Expand all
32 Widget* bubble_widget = new Widget(); 32 Widget* bubble_widget = new Widget();
33 Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE); 33 Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE);
34 bubble_params.delegate = bubble; 34 bubble_params.delegate = bubble;
35 bubble_params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW; 35 bubble_params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
36 bubble_params.accept_events = bubble->accept_events(); 36 bubble_params.accept_events = bubble->accept_events();
37 if (bubble->parent_window()) 37 if (bubble->parent_window())
38 bubble_params.parent = bubble->parent_window(); 38 bubble_params.parent = bubble->parent_window();
39 else if (bubble->anchor_widget()) 39 else if (bubble->anchor_widget())
40 bubble_params.parent = bubble->anchor_widget()->GetNativeView(); 40 bubble_params.parent = bubble->anchor_widget()->GetNativeView();
41 bubble_params.can_activate = bubble->CanActivate(); 41 bubble_params.can_activate = bubble->CanActivate();
42 #if defined(OS_WIN) && !defined(USE_AURA)
43 bubble_params.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS;
44 bubble_params.opacity = Widget::InitParams::OPAQUE_WINDOW;
45 #endif
46 bubble->OnBeforeBubbleWidgetInit(&bubble_params, bubble_widget); 42 bubble->OnBeforeBubbleWidgetInit(&bubble_params, bubble_widget);
47 bubble_widget->Init(bubble_params); 43 bubble_widget->Init(bubble_params);
48 return bubble_widget; 44 return bubble_widget;
49 } 45 }
50 46
51 } // namespace 47 } // namespace
52 48
53 #if defined(OS_WIN) && !defined(USE_AURA)
54 // Windows uses two widgets and some extra complexity to host partially
55 // transparent native controls and use per-pixel HWND alpha on the border.
56 // TODO(msw): Clean these up when Windows native controls are no longer needed.
57 class BubbleBorderDelegate : public WidgetDelegate,
58 public WidgetObserver {
59 public:
60 BubbleBorderDelegate(BubbleDelegateView* bubble, Widget* widget)
61 : bubble_(bubble),
62 widget_(widget) {
63 bubble_->GetWidget()->AddObserver(this);
64 }
65
66 virtual ~BubbleBorderDelegate() {
67 DetachFromBubble();
68 }
69
70 // WidgetDelegate overrides:
71 virtual bool CanActivate() const OVERRIDE { return false; }
72 virtual string16 GetWindowTitle() const OVERRIDE {
73 return bubble_->GetWindowTitle();
74 }
75 virtual bool ShouldShowCloseButton() const OVERRIDE {
76 return bubble_->ShouldShowCloseButton();
77 }
78 virtual void DeleteDelegate() OVERRIDE { delete this; }
79 virtual Widget* GetWidget() OVERRIDE { return widget_; }
80 virtual const Widget* GetWidget() const OVERRIDE { return widget_; }
81 virtual NonClientFrameView* CreateNonClientFrameView(
82 Widget* widget) OVERRIDE {
83 return bubble_->CreateNonClientFrameView(widget);
84 }
85
86 // WidgetObserver overrides:
87 virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
88 DetachFromBubble();
89 widget_->Close();
90 }
91
92 private:
93 // Removes state installed on |bubble_|, including references |bubble_| has to
94 // us.
95 void DetachFromBubble() {
96 if (!bubble_)
97 return;
98 if (bubble_->GetWidget())
99 bubble_->GetWidget()->RemoveObserver(this);
100 bubble_->border_widget_ = NULL;
101 bubble_ = NULL;
102 }
103
104 BubbleDelegateView* bubble_;
105 Widget* widget_;
106
107 DISALLOW_COPY_AND_ASSIGN(BubbleBorderDelegate);
108 };
109
110 namespace {
111
112 // Create a widget to host the bubble's border.
113 Widget* CreateBorderWidget(BubbleDelegateView* bubble) {
114 Widget* border_widget = new Widget();
115 Widget::InitParams border_params(Widget::InitParams::TYPE_BUBBLE);
116 border_params.delegate = new BubbleBorderDelegate(bubble, border_widget);
117 border_params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
118 border_params.parent = bubble->GetWidget()->GetNativeView();
119 border_params.can_activate = false;
120 border_params.accept_events = bubble->border_accepts_events();
121 border_widget->Init(border_params);
122 border_widget->set_focus_on_creation(false);
123 return border_widget;
124 }
125
126 } // namespace
127
128 #endif
129
130 BubbleDelegateView::BubbleDelegateView() 49 BubbleDelegateView::BubbleDelegateView()
131 : close_on_esc_(true), 50 : close_on_esc_(true),
132 close_on_deactivate_(true), 51 close_on_deactivate_(true),
133 anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()), 52 anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()),
134 anchor_widget_(NULL), 53 anchor_widget_(NULL),
135 move_with_anchor_(false), 54 move_with_anchor_(false),
136 arrow_(BubbleBorder::TOP_LEFT), 55 arrow_(BubbleBorder::TOP_LEFT),
137 shadow_(BubbleBorder::SMALL_SHADOW), 56 shadow_(BubbleBorder::SMALL_SHADOW),
138 color_explicitly_set_(false), 57 color_explicitly_set_(false),
139 margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin), 58 margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin),
140 original_opacity_(255), 59 original_opacity_(255),
141 border_widget_(NULL),
142 use_focusless_(false), 60 use_focusless_(false),
143 accept_events_(true), 61 accept_events_(true),
144 border_accepts_events_(true), 62 border_accepts_events_(true),
145 adjust_if_offscreen_(true), 63 adjust_if_offscreen_(true),
146 parent_window_(NULL) { 64 parent_window_(NULL) {
147 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); 65 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
148 UpdateColorsFromTheme(GetNativeTheme()); 66 UpdateColorsFromTheme(GetNativeTheme());
149 } 67 }
150 68
151 BubbleDelegateView::BubbleDelegateView( 69 BubbleDelegateView::BubbleDelegateView(
152 View* anchor_view, 70 View* anchor_view,
153 BubbleBorder::Arrow arrow) 71 BubbleBorder::Arrow arrow)
154 : close_on_esc_(true), 72 : close_on_esc_(true),
155 close_on_deactivate_(true), 73 close_on_deactivate_(true),
156 anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()), 74 anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()),
157 anchor_widget_(NULL), 75 anchor_widget_(NULL),
158 move_with_anchor_(false), 76 move_with_anchor_(false),
159 arrow_(arrow), 77 arrow_(arrow),
160 shadow_(BubbleBorder::SMALL_SHADOW), 78 shadow_(BubbleBorder::SMALL_SHADOW),
161 color_explicitly_set_(false), 79 color_explicitly_set_(false),
162 margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin), 80 margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin),
163 original_opacity_(255), 81 original_opacity_(255),
164 border_widget_(NULL),
165 use_focusless_(false), 82 use_focusless_(false),
166 accept_events_(true), 83 accept_events_(true),
167 border_accepts_events_(true), 84 border_accepts_events_(true),
168 adjust_if_offscreen_(true), 85 adjust_if_offscreen_(true),
169 parent_window_(NULL) { 86 parent_window_(NULL) {
170 SetAnchorView(anchor_view); 87 SetAnchorView(anchor_view);
171 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); 88 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
172 UpdateColorsFromTheme(GetNativeTheme()); 89 UpdateColorsFromTheme(GetNativeTheme());
173 } 90 }
174 91
175 BubbleDelegateView::~BubbleDelegateView() { 92 BubbleDelegateView::~BubbleDelegateView() {
176 SetAnchorView(NULL); 93 SetAnchorView(NULL);
177 } 94 }
178 95
179 // static 96 // static
180 Widget* BubbleDelegateView::CreateBubble(BubbleDelegateView* bubble_delegate) { 97 Widget* BubbleDelegateView::CreateBubble(BubbleDelegateView* bubble_delegate) {
181 bubble_delegate->Init(); 98 bubble_delegate->Init();
182 // Get the latest anchor widget from the anchor view at bubble creation time. 99 // Get the latest anchor widget from the anchor view at bubble creation time.
183 bubble_delegate->SetAnchorView(bubble_delegate->GetAnchorView()); 100 bubble_delegate->SetAnchorView(bubble_delegate->GetAnchorView());
184 Widget* bubble_widget = CreateBubbleWidget(bubble_delegate); 101 Widget* bubble_widget = CreateBubbleWidget(bubble_delegate);
185 102
186 #if defined(OS_WIN) 103 #if defined(OS_WIN) && defined(USE_AURA)
187 #if defined(USE_AURA)
188 // If glass is enabled, the bubble is allowed to extend outside the bounds of 104 // If glass is enabled, the bubble is allowed to extend outside the bounds of
189 // the parent frame and let DWM handle compositing. If not, then we don't 105 // the parent frame and let DWM handle compositing. If not, then we don't
190 // want to allow the bubble to extend the frame because it will be clipped. 106 // want to allow the bubble to extend the frame because it will be clipped.
191 bubble_delegate->set_adjust_if_offscreen(ui::win::IsAeroGlassEnabled()); 107 bubble_delegate->set_adjust_if_offscreen(ui::win::IsAeroGlassEnabled());
192 #else
193 // First set the contents view to initialize view bounds for widget sizing.
194 bubble_widget->SetContentsView(bubble_delegate->GetContentsView());
195 bubble_delegate->border_widget_ = CreateBorderWidget(bubble_delegate);
196 #endif
197 #endif 108 #endif
198 109
199 bubble_delegate->SizeToContents(); 110 bubble_delegate->SizeToContents();
200 bubble_widget->AddObserver(bubble_delegate); 111 bubble_widget->AddObserver(bubble_delegate);
201 return bubble_widget; 112 return bubble_widget;
202 } 113 }
203 114
204 BubbleDelegateView* BubbleDelegateView::AsBubbleDelegate() { 115 BubbleDelegateView* BubbleDelegateView::AsBubbleDelegate() {
205 return this; 116 return this;
206 } 117 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 if (fade_in) 197 if (fade_in)
287 GetWidget()->Show(); 198 GetWidget()->Show();
288 else 199 else
289 GetWidget()->Close(); 200 GetWidget()->Close();
290 #else 201 #else
291 fade_animation_.reset(new gfx::SlideAnimation(this)); 202 fade_animation_.reset(new gfx::SlideAnimation(this));
292 fade_animation_->SetSlideDuration(GetFadeDuration()); 203 fade_animation_->SetSlideDuration(GetFadeDuration());
293 fade_animation_->Reset(fade_in ? 0.0 : 1.0); 204 fade_animation_->Reset(fade_in ? 0.0 : 1.0);
294 if (fade_in) { 205 if (fade_in) {
295 original_opacity_ = 0; 206 original_opacity_ = 0;
296 if (border_widget_)
297 border_widget_->SetOpacity(original_opacity_);
298 GetWidget()->SetOpacity(original_opacity_); 207 GetWidget()->SetOpacity(original_opacity_);
299 GetWidget()->Show(); 208 GetWidget()->Show();
300 fade_animation_->Show(); 209 fade_animation_->Show();
301 } else { 210 } else {
302 original_opacity_ = 255; 211 original_opacity_ = 255;
303 fade_animation_->Hide(); 212 fade_animation_->Hide();
304 } 213 }
305 #endif 214 #endif
306 } 215 }
307 216
308 void BubbleDelegateView::ResetFade() { 217 void BubbleDelegateView::ResetFade() {
309 fade_animation_.reset(); 218 fade_animation_.reset();
310 if (border_widget_)
311 border_widget_->SetOpacity(original_opacity_);
312 GetWidget()->SetOpacity(original_opacity_); 219 GetWidget()->SetOpacity(original_opacity_);
313 } 220 }
314 221
315 void BubbleDelegateView::SetAlignment(BubbleBorder::BubbleAlignment alignment) { 222 void BubbleDelegateView::SetAlignment(BubbleBorder::BubbleAlignment alignment) {
316 GetBubbleFrameView()->bubble_border()->set_alignment(alignment); 223 GetBubbleFrameView()->bubble_border()->set_alignment(alignment);
317 SizeToContents(); 224 SizeToContents();
318 } 225 }
319 226
320 void BubbleDelegateView::SetArrowPaintType( 227 void BubbleDelegateView::SetArrowPaintType(
321 BubbleBorder::ArrowPaintType paint_type) { 228 BubbleBorder::ArrowPaintType paint_type) {
(...skipping 25 matching lines...) Expand all
347 bool closed = fade_animation_->GetCurrentValue() == 0; 254 bool closed = fade_animation_->GetCurrentValue() == 0;
348 fade_animation_->Reset(); 255 fade_animation_->Reset();
349 if (closed) 256 if (closed)
350 GetWidget()->Close(); 257 GetWidget()->Close();
351 } 258 }
352 259
353 void BubbleDelegateView::AnimationProgressed(const gfx::Animation* animation) { 260 void BubbleDelegateView::AnimationProgressed(const gfx::Animation* animation) {
354 if (animation != fade_animation_.get()) 261 if (animation != fade_animation_.get())
355 return; 262 return;
356 DCHECK(fade_animation_->is_animating()); 263 DCHECK(fade_animation_->is_animating());
357 unsigned char opacity = fade_animation_->GetCurrentValue() * 255; 264 GetWidget()->SetOpacity(fade_animation_->GetCurrentValue() * 255);
358 #if defined(OS_WIN) && !defined(USE_AURA)
359 // Explicitly set the content Widget's layered style and set transparency via
360 // SetLayeredWindowAttributes. This is done because initializing the Widget as
361 // transparent and setting opacity via UpdateLayeredWindow doesn't support
362 // hosting child native Windows controls.
363 const HWND hwnd = GetWidget()->GetNativeView();
364 const DWORD style = GetWindowLong(hwnd, GWL_EXSTYLE);
365 if ((opacity == 255) == !!(style & WS_EX_LAYERED))
366 SetWindowLong(hwnd, GWL_EXSTYLE, style ^ WS_EX_LAYERED);
367 SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA);
368 // Update the border widget's opacity.
369 border_widget_->SetOpacity(opacity);
370 #endif
371 GetWidget()->SetOpacity(opacity);
372 } 265 }
373 266
374 void BubbleDelegateView::Init() {} 267 void BubbleDelegateView::Init() {}
375 268
376 bool BubbleDelegateView::ShouldFlipArrowForRtl() const { 269 bool BubbleDelegateView::ShouldFlipArrowForRtl() const {
377 return true; 270 return true;
378 } 271 }
379 272
380 void BubbleDelegateView::SetAnchorView(View* anchor_view) { 273 void BubbleDelegateView::SetAnchorView(View* anchor_view) {
381 // When the anchor view gets set the associated anchor widget might 274 // When the anchor view gets set the associated anchor widget might
(...skipping 13 matching lines...) Expand all
395 // Remove the old storage item and set the new (if there is one). 288 // Remove the old storage item and set the new (if there is one).
396 ViewStorage* view_storage = ViewStorage::GetInstance(); 289 ViewStorage* view_storage = ViewStorage::GetInstance();
397 if (view_storage->RetrieveView(anchor_view_storage_id_)) 290 if (view_storage->RetrieveView(anchor_view_storage_id_))
398 view_storage->RemoveView(anchor_view_storage_id_); 291 view_storage->RemoveView(anchor_view_storage_id_);
399 292
400 if (anchor_view) 293 if (anchor_view)
401 view_storage->StoreView(anchor_view_storage_id_, anchor_view); 294 view_storage->StoreView(anchor_view_storage_id_, anchor_view);
402 } 295 }
403 296
404 void BubbleDelegateView::SizeToContents() { 297 void BubbleDelegateView::SizeToContents() {
405 #if defined(OS_WIN) && !defined(USE_AURA)
406 border_widget_->SetBounds(GetBubbleBounds());
407 GetWidget()->SetBounds(GetBubbleClientBounds());
408
409 // Update the local client bounds clipped out by the border widget background.
410 // Used to correctly display overlapping semi-transparent widgets on Windows.
411 GetBubbleFrameView()->bubble_border()->set_client_bounds(
412 GetBubbleFrameView()->GetBoundsForClientView());
413 #else
414 GetWidget()->SetBounds(GetBubbleBounds()); 298 GetWidget()->SetBounds(GetBubbleBounds());
415 #endif
416 } 299 }
417 300
418 BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const { 301 BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const {
419 const Widget* widget = border_widget_ ? border_widget_ : GetWidget(); 302 const NonClientView* view =
420 const NonClientView* view = widget ? widget->non_client_view() : NULL; 303 GetWidget() ? GetWidget()->non_client_view() : NULL;
421 return view ? static_cast<BubbleFrameView*>(view->frame_view()) : NULL; 304 return view ? static_cast<BubbleFrameView*>(view->frame_view()) : NULL;
422 } 305 }
423 306
424 gfx::Rect BubbleDelegateView::GetBubbleBounds() { 307 gfx::Rect BubbleDelegateView::GetBubbleBounds() {
425 // The argument rect has its origin at the bubble's arrow anchor point; 308 // The argument rect has its origin at the bubble's arrow anchor point;
426 // its size is the preferred size of the bubble's client view (this view). 309 // its size is the preferred size of the bubble's client view (this view).
427 return GetBubbleFrameView()->GetUpdatedWindowBounds(GetAnchorRect(), 310 return GetBubbleFrameView()->GetUpdatedWindowBounds(GetAnchorRect(),
428 GetPreferredSize(), adjust_if_offscreen_); 311 GetPreferredSize(), adjust_if_offscreen_);
429 } 312 }
430 313
431 int BubbleDelegateView::GetFadeDuration() { 314 int BubbleDelegateView::GetFadeDuration() {
432 return kHideFadeDurationMS; 315 return kHideFadeDurationMS;
433 } 316 }
434 317
435 void BubbleDelegateView::UpdateColorsFromTheme(const ui::NativeTheme* theme) { 318 void BubbleDelegateView::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
436 if (!color_explicitly_set_) { 319 if (!color_explicitly_set_) {
437 color_ = GetNativeTheme()->GetSystemColor( 320 color_ = GetNativeTheme()->GetSystemColor(
438 ui::NativeTheme::kColorId_WindowBackground); 321 ui::NativeTheme::kColorId_WindowBackground);
439 } 322 }
440 set_background(Background::CreateSolidBackground(color())); 323 set_background(Background::CreateSolidBackground(color()));
441 BubbleFrameView* frame_view = GetBubbleFrameView(); 324 BubbleFrameView* frame_view = GetBubbleFrameView();
442 if (frame_view) 325 if (frame_view)
443 frame_view->bubble_border()->set_background_color(color()); 326 frame_view->bubble_border()->set_background_color(color());
444 } 327 }
445 328
446 #if defined(OS_WIN) && !defined(USE_AURA) 329 void BubbleDelegateView::HandleVisibilityChanged(Widget* widget, bool visible) {
447 gfx::Rect BubbleDelegateView::GetBubbleClientBounds() const { 330 if (widget == GetWidget() && visible && anchor_widget() &&
448 gfx::Rect client_bounds(GetBubbleFrameView()->GetBoundsForClientView()); 331 anchor_widget()->GetTopLevelWidget()) {
449 client_bounds.Offset( 332 anchor_widget()->GetTopLevelWidget()->DisableInactiveRendering();
450 border_widget_->GetWindowBoundsInScreen().OffsetFromOrigin());
451 return client_bounds;
452 }
453 #endif
454
455 void BubbleDelegateView::HandleVisibilityChanged(Widget* widget,
456 bool visible) {
457 if (widget != GetWidget())
458 return;
459
460 if (visible) {
461 if (border_widget_)
462 border_widget_->ShowInactive();
463 if (anchor_widget() && anchor_widget()->GetTopLevelWidget())
464 anchor_widget()->GetTopLevelWidget()->DisableInactiveRendering();
465 } else {
466 if (border_widget_)
467 border_widget_->Hide();
468 } 333 }
469 } 334 }
470 335
471 } // namespace views 336 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/bubble/bubble_delegate.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698