OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/browser/views/info_bubble.h" | 5 #include "chrome/browser/views/info_bubble.h" |
6 | 6 |
7 #include "app/gfx/canvas.h" | 7 #include "app/gfx/canvas.h" |
8 #include "app/gfx/path.h" | 8 #include "app/gfx/path.h" |
9 #include "app/resource_bundle.h" | 9 #include "app/resource_bundle.h" |
10 #include "chrome/browser/browser_window.h" | 10 #include "chrome/browser/browser_window.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 set_window_style(WS_POPUP | WS_CLIPCHILDREN); | 122 set_window_style(WS_POPUP | WS_CLIPCHILDREN); |
123 set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); | 123 set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); |
124 // Because we're going to change the alpha value of the layered window we | 124 // Because we're going to change the alpha value of the layered window we |
125 // don't want to use the offscreen buffer provided by WidgetWin. | 125 // don't want to use the offscreen buffer provided by WidgetWin. |
126 SetUseLayeredBuffer(false); | 126 SetUseLayeredBuffer(false); |
127 set_initial_class_style( | 127 set_initial_class_style( |
128 (win_util::GetWinVersion() < win_util::WINVERSION_XP) ? | 128 (win_util::GetWinVersion() < win_util::WINVERSION_XP) ? |
129 0 : CS_DROPSHADOW); | 129 0 : CS_DROPSHADOW); |
130 #endif | 130 #endif |
131 content_view_ = CreateContentView(content); | 131 content_view_ = CreateContentView(content); |
132 gfx::Rect bounds = | |
133 content_view_->CalculateWindowBoundsAndAjust(position_relative_to); | |
134 | 132 |
135 #if defined(OS_WIN) | 133 #if defined(OS_WIN) |
136 WidgetWin::Init(parent->GetNativeWindow(), bounds); | 134 WidgetWin::Init(parent->GetNativeWindow(), gfx::Rect()); |
137 #else | 135 #else |
138 WidgetGtk::Init(GTK_WIDGET(parent->GetNativeWindow()), bounds); | 136 WidgetGtk::Init(GTK_WIDGET(parent->GetNativeWindow()), gfx::Rect()); |
139 #endif | 137 #endif |
| 138 |
140 SetContentsView(content_view_); | 139 SetContentsView(content_view_); |
141 // The preferred size may differ when parented. Ask for the bounds again | 140 // The preferred size may differ when parented. Ask for the bounds again |
142 // and if they differ reset the bounds. | 141 // and if they differ reset the bounds. |
143 gfx::Rect parented_bounds = | 142 gfx::Rect parented_bounds = |
144 content_view_->CalculateWindowBoundsAndAjust(position_relative_to); | 143 content_view_->CalculateWindowBoundsAndAjust(position_relative_to); |
145 | 144 |
146 if (bounds != parented_bounds) { | 145 // TODO(beng): This should be done in a cleaner and cross-platform way. |
147 #if defined(OS_WIN) | 146 #if defined(OS_WIN) |
148 SetWindowPos(NULL, parented_bounds.x(), parented_bounds.y(), | 147 SetWindowPos(NULL, parented_bounds.x(), parented_bounds.y(), |
149 parented_bounds.width(), parented_bounds.height(), | 148 parented_bounds.width(), parented_bounds.height(), |
150 SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOZORDER); | 149 SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOZORDER); |
151 // Invoke ChangeSize, otherwise layered window isn't updated correctly. | 150 // Invoke ChangeSize, otherwise layered window isn't updated correctly. |
152 ChangeSize(0, CSize(parented_bounds.width(), parented_bounds.height())); | 151 ChangeSize(0, CSize(parented_bounds.width(), parented_bounds.height())); |
| 152 #else |
| 153 SetBounds(parented_bounds); |
153 #endif | 154 #endif |
154 } | |
155 | 155 |
156 #if defined(OS_WIN) | 156 #if defined(OS_WIN) |
157 // Register the Escape accelerator for closing. | 157 // Register the Escape accelerator for closing. |
158 GetFocusManager()->RegisterAccelerator(views::Accelerator(VK_ESCAPE, false, | 158 GetFocusManager()->RegisterAccelerator(views::Accelerator(VK_ESCAPE, false, |
159 false, false), | 159 false, false), |
160 this); | 160 this); |
161 // Set initial alpha value of the layered window. | 161 // Set initial alpha value of the layered window. |
162 SetLayeredWindowAttributes(GetNativeView(), | 162 SetLayeredWindowAttributes(GetNativeView(), |
163 RGB(0xFF, 0xFF, 0xFF), | 163 RGB(0xFF, 0xFF, 0xFF), |
164 kMinimumAlpha, | 164 kMinimumAlpha, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 // The popup should close when it is deactivated. | 206 // The popup should close when it is deactivated. |
207 if (action == WA_INACTIVE && !closed_) { | 207 if (action == WA_INACTIVE && !closed_) { |
208 Close(); | 208 Close(); |
209 } else if (action == WA_ACTIVE) { | 209 } else if (action == WA_ACTIVE) { |
210 DCHECK(GetRootView()->GetChildViewCount() > 0); | 210 DCHECK(GetRootView()->GetChildViewCount() > 0); |
211 GetRootView()->GetChildViewAt(0)->RequestFocus(); | 211 GetRootView()->GetChildViewAt(0)->RequestFocus(); |
212 } | 212 } |
213 } | 213 } |
214 | 214 |
215 void InfoBubble::OnSize(UINT param, const CSize& size) { | 215 void InfoBubble::OnSize(UINT param, const CSize& size) { |
| 216 // See OnSizeAllocate for the Linux version. |
216 gfx::Path path; | 217 gfx::Path path; |
217 content_view_->GetMask(gfx::Size(size.cx, size.cy), &path); | 218 content_view_->GetMask(gfx::Size(size.cx, size.cy), &path); |
218 SetWindowRgn(path.CreateHRGN(), TRUE); | 219 SetWindowRgn(path.CreateHRGN(), TRUE); |
219 WidgetWin::OnSize(param, size); | 220 WidgetWin::OnSize(param, size); |
220 } | 221 } |
221 #endif | 222 #endif |
222 | 223 |
223 InfoBubble::ContentView* InfoBubble::CreateContentView(View* content) { | 224 InfoBubble::ContentView* InfoBubble::CreateContentView(View* content) { |
224 return new ContentView(content, this); | 225 return new ContentView(content, this); |
225 } | 226 } |
226 | 227 |
227 void InfoBubble::Close(bool closed_by_escape) { | 228 void InfoBubble::Close(bool closed_by_escape) { |
228 if (closed_) | 229 if (closed_) |
229 return; | 230 return; |
230 | 231 |
231 // We don't fade out because it looks terrible. | 232 // We don't fade out because it looks terrible. |
232 if (delegate_) | 233 if (delegate_) |
233 delegate_->InfoBubbleClosing(this, closed_by_escape); | 234 delegate_->InfoBubbleClosing(this, closed_by_escape); |
234 closed_ = true; | 235 closed_ = true; |
235 #if defined(OS_WIN) | 236 #if defined(OS_WIN) |
236 WidgetWin::Close(); | 237 WidgetWin::Close(); |
237 #else | 238 #else |
238 WidgetGtk::Close(); | 239 WidgetGtk::Close(); |
239 #endif | 240 #endif |
240 } | 241 } |
241 | 242 |
| 243 #if defined(OS_LINUX) |
| 244 void InfoBubble::OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) { |
| 245 gfx::Path path; |
| 246 content_view_->GetMask(gfx::Size(allocation->width, allocation->height), |
| 247 &path); |
| 248 SetShape(path); |
| 249 WidgetGtk::OnSizeAllocate(widget, allocation); |
| 250 } |
| 251 #endif |
| 252 |
242 // ContentView ---------------------------------------------------------------- | 253 // ContentView ---------------------------------------------------------------- |
243 | 254 |
244 InfoBubble::ContentView::ContentView(views::View* content, InfoBubble* host) | 255 InfoBubble::ContentView::ContentView(views::View* content, InfoBubble* host) |
245 : host_(host) { | 256 : content_(content), |
| 257 host_(host) { |
246 if (UILayoutIsRightToLeft()) { | 258 if (UILayoutIsRightToLeft()) { |
247 arrow_edge_ = TOP_RIGHT; | 259 arrow_edge_ = TOP_RIGHT; |
248 } else { | 260 } else { |
249 arrow_edge_ = TOP_LEFT; | 261 arrow_edge_ = TOP_LEFT; |
250 } | 262 } |
251 AddChildView(content); | |
252 } | 263 } |
253 | 264 |
254 gfx::Rect InfoBubble::ContentView::CalculateWindowBoundsAndAjust( | 265 gfx::Rect InfoBubble::ContentView::CalculateWindowBoundsAndAjust( |
255 const gfx::Rect& position_relative_to) { | 266 const gfx::Rect& position_relative_to) { |
256 scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider( | 267 scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider( |
257 WindowSizer::CreateDefaultMonitorInfoProvider()); | 268 WindowSizer::CreateDefaultMonitorInfoProvider()); |
258 gfx::Rect monitor_bounds( | 269 gfx::Rect monitor_bounds( |
259 monitor_provider->GetMonitorWorkAreaMatching(position_relative_to)); | 270 monitor_provider->GetMonitorWorkAreaMatching(position_relative_to)); |
260 // Calculate the bounds using TOP_LEFT (the default). | 271 // Calculate the bounds using TOP_LEFT (the default). |
261 gfx::Rect window_bounds = CalculateWindowBounds(position_relative_to); | 272 gfx::Rect window_bounds = CalculateWindowBounds(position_relative_to); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 canvas->FillRectInt(kBorderColor1, arrow_x + (kArrowSize - i), y, 1, 1); | 443 canvas->FillRectInt(kBorderColor1, arrow_x + (kArrowSize - i), y, 1, 1); |
433 if (i != 0) { | 444 if (i != 0) { |
434 canvas->FillRectInt(kBorderColor2, arrow_x - (kArrowSize - i) - 1, y, 1, | 445 canvas->FillRectInt(kBorderColor2, arrow_x - (kArrowSize - i) - 1, y, 1, |
435 1); | 446 1); |
436 canvas->FillRectInt(kBorderColor2, arrow_x + (kArrowSize - i) + 1, y, 1, | 447 canvas->FillRectInt(kBorderColor2, arrow_x + (kArrowSize - i) + 1, y, 1, |
437 1); | 448 1); |
438 } | 449 } |
439 } | 450 } |
440 } | 451 } |
441 | 452 |
| 453 void InfoBubble::ContentView::ViewHierarchyChanged(bool is_add, |
| 454 View* parent, |
| 455 View* child) { |
| 456 if (is_add && child == this) |
| 457 AddChildView(content_); |
| 458 } |
| 459 |
442 gfx::Rect InfoBubble::ContentView::CalculateWindowBounds( | 460 gfx::Rect InfoBubble::ContentView::CalculateWindowBounds( |
443 const gfx::Rect& position_relative_to) { | 461 const gfx::Rect& position_relative_to) { |
444 gfx::Size pref = GetPreferredSize(); | 462 gfx::Size pref = GetPreferredSize(); |
445 int x = position_relative_to.x() + position_relative_to.width() / 2; | 463 int x = position_relative_to.x() + position_relative_to.width() / 2; |
446 int y; | 464 int y; |
447 if (IsLeft()) | 465 if (IsLeft()) |
448 x -= kArrowXOffset; | 466 x -= kArrowXOffset; |
449 else | 467 else |
450 x = x + kArrowXOffset - pref.width(); | 468 x = x + kArrowXOffset - pref.width(); |
451 if (IsTop()) { | 469 if (IsTop()) { |
452 y = position_relative_to.bottom() + kArrowToContentPadding; | 470 y = position_relative_to.bottom() + kArrowToContentPadding; |
453 } else { | 471 } else { |
454 y = position_relative_to.y() - kArrowToContentPadding - pref.height(); | 472 y = position_relative_to.y() - kArrowToContentPadding - pref.height(); |
455 } | 473 } |
456 return gfx::Rect(x, y, pref.width(), pref.height()); | 474 return gfx::Rect(x, y, pref.width(), pref.height()); |
457 } | 475 } |
OLD | NEW |