constrained_window_views.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/constrained_window_views.h" 6 7#include <algorithm> 8 9#include "base/command_line.h" 10#include "base/utf_string_conversions.h" 11#include "chrome/app/chrome_command_ids.h" 12#include "chrome/browser/platform_util.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/browser/themes/theme_properties.h" 15#include "chrome/browser/ui/toolbar/toolbar_model.h" 16#include "chrome/browser/ui/views/frame/browser_view.h" 17#include "chrome/browser/ui/views/theme_image_mapper.h" 18#include "chrome/browser/ui/web_contents_modal_dialog_host.h" 19#include "chrome/browser/ui/web_contents_modal_dialog_manager.h" 20#include "chrome/common/chrome_constants.h" 21#include "content/public/browser/navigation_controller.h" 22#include "content/public/browser/web_contents.h" 23#include "content/public/browser/web_contents_view.h" 24#include "grit/chromium_strings.h" 25#include "grit/generated_resources.h" 26#include "grit/theme_resources.h" 27#include "grit/ui_resources.h" 28#include "net/base/net_util.h" 29#include "ui/aura/client/aura_constants.h" 30#include "ui/base/hit_test.h" 31#include "ui/base/resource/resource_bundle.h" 32#include "ui/base/ui_base_switches.h" 33#include "ui/gfx/canvas.h" 34#include "ui/gfx/font.h" 35#include "ui/gfx/path.h" 36#include "ui/gfx/rect.h" 37#include "ui/gfx/screen.h" 38#include "ui/views/border.h" 39#include "ui/views/color_constants.h" 40#include "ui/views/controls/button/image_button.h" 41#include "ui/views/focus/focus_manager.h" 42#include "ui/views/views_delegate.h" 43#include "ui/views/widget/widget.h" 44#include "ui/views/widget/widget_observer.h" 45#include "ui/views/window/client_view.h" 46#include "ui/views/window/dialog_client_view.h" 47#include "ui/views/window/dialog_delegate.h" 48#include "ui/views/window/frame_background.h" 49#include "ui/views/window/non_client_view.h" 50#include "ui/views/window/window_resources.h" 51#include "ui/views/window/window_shape.h" 52 53#if defined(OS_WIN) && !defined(USE_AURA) 54#include "ui/base/win/shell.h" 55#include "ui/views/widget/native_widget_win.h" 56#endif 57 58#if defined(USE_AURA) 59#include "ui/aura/window.h" 60#include "ui/views/corewm/shadow_types.h" 61#include "ui/views/corewm/visibility_controller.h" 62#include "ui/views/corewm/window_animations.h" 63#include "ui/views/corewm/window_modality_controller.h" 64#endif 65 66#if defined(USE_ASH) 67#include "ash/ash_constants.h" 68#include "ash/shell.h" 69#include "ash/wm/custom_frame_view_ash.h" 70#endif 71 72using base::TimeDelta; 73 74namespace views { 75class ClientView; 76} 77 78namespace { 79// The name of a key to store on the window handle to associate 80// WebContentsModalDialogHostObserverViews with the Widget. 81const char* const kWebContentsModalDialogHostObserverViewsKey = 82 "__WEB_CONTENTS_MODAL_DIALOG_HOST_OBSERVER_VIEWS__"; 83 84// Applies positioning changes from the WebContentsModalDialogHost to the 85// Widget. 86class WebContentsModalDialogHostObserverViews 87 : public views::WidgetObserver, 88 public WebContentsModalDialogHostObserver { 89 public: 90 WebContentsModalDialogHostObserverViews( 91 WebContentsModalDialogHost* host, 92 views::Widget* target_widget, 93 const char *const native_window_property) 94 : host_(host), 95 target_widget_(target_widget), 96 native_window_property_(native_window_property) { 97 DCHECK(host_); 98 DCHECK(target_widget_); 99 host_->AddObserver(this); 100 target_widget_->AddObserver(this); 101 } 102 103 virtual ~WebContentsModalDialogHostObserverViews() { 104 host_->RemoveObserver(this); 105 target_widget_->RemoveObserver(this); 106 target_widget_->SetNativeWindowProperty(native_window_property_, 107 NULL); 108 } 109 110 // WidgetObserver overrides 111 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE { 112 delete this; 113 } 114 115 // WebContentsModalDialogHostObserver overrides 116 virtual void OnPositionRequiresUpdate() OVERRIDE { 117 gfx::Size size = target_widget_->GetWindowBoundsInScreen().size(); 118 gfx::Point position = host_->GetDialogPosition(size); 119 views::Border* border = 120 target_widget_->non_client_view()->frame_view()->border(); 121 // Border may be null during widget initialization. 122 if (border) { 123 // Align the first row of pixels inside the border. This is the apparent 124 // top of the dialog. 125 position.set_y(position.y() - border->GetInsets().top()); 126 } 127 target_widget_->SetBounds(gfx::Rect(position, size)); 128 } 129 130 private: 131 WebContentsModalDialogHost* host_; 132 views::Widget* target_widget_; 133 const char* const native_window_property_; 134 135 DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogHostObserverViews); 136}; 137 138} // namespace 139 140// An enumeration of image resources used by this window. 141enum { 142 FRAME_PART_IMAGE_FIRST = 0, // Must be first. 143 144 // Window Frame Border. 145 FRAME_BOTTOM_EDGE, 146 FRAME_BOTTOM_LEFT_CORNER, 147 FRAME_BOTTOM_RIGHT_CORNER, 148 FRAME_LEFT_EDGE, 149 FRAME_RIGHT_EDGE, 150 FRAME_TOP_EDGE, 151 FRAME_TOP_LEFT_CORNER, 152 FRAME_TOP_RIGHT_CORNER, 153 154 FRAME_PART_IMAGE_COUNT // Must be last. 155}; 156 157static const int kXPFramePartIDs[] = { 158 0, 159 IDR_WINDOW_BOTTOM_CENTER, IDR_WINDOW_BOTTOM_LEFT_CORNER, 160 IDR_WINDOW_BOTTOM_RIGHT_CORNER, IDR_WINDOW_LEFT_SIDE, 161 IDR_WINDOW_RIGHT_SIDE, IDR_WINDOW_TOP_CENTER, 162 IDR_WINDOW_TOP_LEFT_CORNER, IDR_WINDOW_TOP_RIGHT_CORNER, 163 0 }; 164static const int kVistaFramePartIDs[] = { 165 0, 166 IDR_CONSTRAINED_BOTTOM_CENTER_V, IDR_CONSTRAINED_BOTTOM_LEFT_CORNER_V, 167 IDR_CONSTRAINED_BOTTOM_RIGHT_CORNER_V, IDR_CONSTRAINED_LEFT_SIDE_V, 168 IDR_CONSTRAINED_RIGHT_SIDE_V, IDR_CONSTRAINED_TOP_CENTER_V, 169 IDR_CONSTRAINED_TOP_LEFT_CORNER_V, IDR_CONSTRAINED_TOP_RIGHT_CORNER_V, 170 0 }; 171 172class XPWindowResources : public views::WindowResources { 173 public: 174 XPWindowResources() { 175 InitClass(); 176 } 177 virtual ~XPWindowResources() {} 178 179 virtual gfx::ImageSkia* GetPartImage( 180 views::FramePartImage part_id) const OVERRIDE { 181 return images_[part_id]; 182 } 183 184 private: 185 static void InitClass() { 186 static bool initialized = false; 187 if (!initialized) { 188 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 189 for (int i = 0; i < FRAME_PART_IMAGE_COUNT; ++i) { 190 int id = kXPFramePartIDs[i]; 191 if (id != 0) 192 images_[i] = rb.GetImageSkiaNamed(id); 193 } 194 initialized = true; 195 } 196 } 197 198 static gfx::ImageSkia* images_[FRAME_PART_IMAGE_COUNT]; 199 200 DISALLOW_COPY_AND_ASSIGN(XPWindowResources); 201}; 202 203class VistaWindowResources : public views::WindowResources { 204 public: 205 VistaWindowResources() { 206 InitClass(); 207 } 208 virtual ~VistaWindowResources() {} 209 210 virtual gfx::ImageSkia* GetPartImage( 211 views::FramePartImage part_id) const OVERRIDE { 212 return images_[part_id]; 213 } 214 215 private: 216 static void InitClass() { 217 static bool initialized = false; 218 if (!initialized) { 219 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 220 for (int i = 0; i < FRAME_PART_IMAGE_COUNT; ++i) { 221 int id = kVistaFramePartIDs[i]; 222 if (id != 0) 223 images_[i] = rb.GetImageSkiaNamed(id); 224 } 225 initialized = true; 226 } 227 } 228 229 static gfx::ImageSkia* images_[FRAME_PART_IMAGE_COUNT]; 230 231 DISALLOW_COPY_AND_ASSIGN(VistaWindowResources); 232}; 233 234gfx::ImageSkia* XPWindowResources::images_[]; 235gfx::ImageSkia* VistaWindowResources::images_[]; 236 237class ConstrainedWindowFrameView : public views::NonClientFrameView, 238 public views::ButtonListener { 239 public: 240 ConstrainedWindowFrameView(views::Widget* container, 241 bool browser_is_off_the_record); 242 virtual ~ConstrainedWindowFrameView(); 243 244 virtual void UpdateWindowTitle() OVERRIDE; 245 246 // Overridden from views::NonClientFrameView: 247 virtual gfx::Rect GetBoundsForClientView() const OVERRIDE; 248 virtual gfx::Rect GetWindowBoundsForClientBounds( 249 const gfx::Rect& client_bounds) const OVERRIDE; 250 virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE; 251 virtual void GetWindowMask(const gfx::Size& size, 252 gfx::Path* window_mask) OVERRIDE; 253 virtual void ResetWindowControls() OVERRIDE {} 254 virtual void UpdateWindowIcon() OVERRIDE {} 255 256 // Overridden from views::View: 257 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 258 virtual void Layout() OVERRIDE; 259 virtual void OnThemeChanged() OVERRIDE; 260 261 // Overridden from views::ButtonListener: 262 virtual void ButtonPressed(views::Button* sender, 263 const ui::Event& event) OVERRIDE; 264 265 private: 266 // Returns the thickness of the entire nonclient left, right, and bottom 267 // borders, including both the window frame and any client edge. 268 int NonClientBorderThickness() const; 269 270 // Returns the height of the entire nonclient top border, including the window 271 // frame, any title area, and any connected client edge. 272 int NonClientTopBorderHeight() const; 273 274 // Returns the thickness of the nonclient portion of the 3D edge along the 275 // bottom of the titlebar. 276 int TitlebarBottomThickness() const; 277 278 // Returns what the size of the titlebar icon would be if there was one. 279 int IconSize() const; 280 281 // Returns what the titlebar icon's bounds would be if there was one. 282 gfx::Rect IconBounds() const; 283 284 // Paints different parts of the window to the incoming canvas. 285 void PaintFrameBorder(gfx::Canvas* canvas); 286 void PaintTitleBar(gfx::Canvas* canvas); 287 void PaintClientEdge(gfx::Canvas* canvas); 288 289 // Layout various sub-components of this view. 290 void LayoutWindowControls(); 291 void LayoutTitleBar(); 292 293 // Returns the bounds of the client area for the specified view size. 294 gfx::Rect CalculateClientAreaBounds(int width, int height) const; 295 296 SkColor GetTitleColor() const { 297 return browser_is_off_the_record_ 298#if defined(OS_WIN) && !defined(USE_AURA) 299 || !ui::win::IsAeroGlassEnabled() 300#endif 301 ? SK_ColorWHITE : SK_ColorBLACK; 302 } 303 304 // Loads the appropriate set of WindowResources for the frame view. 305 void InitWindowResources(); 306 307 views::Widget* container_; 308 309 bool browser_is_off_the_record_; 310 311 scoped_ptr<views::WindowResources> resources_; 312 313 gfx::Rect title_bounds_; 314 315 views::ImageButton* close_button_; 316 317 // The bounds of the ClientView. 318 gfx::Rect client_view_bounds_; 319 320 // Background painter for the frame. 321 scoped_ptr<views::FrameBackground> frame_background_; 322 323 static void InitClass(); 324 325 // The font to be used to render the titlebar text. 326 static const gfx::Font* title_font_; 327 328 DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowFrameView); 329}; 330 331const gfx::Font* ConstrainedWindowFrameView::title_font_ = NULL; 332 333namespace { 334// The frame border is only visible in restored mode and is hardcoded to 4 px on 335// each side regardless of the system window border size. 336const int kFrameBorderThickness = 4; 337// Various edges of the frame border have a 1 px shadow along their edges; in a 338// few cases we shift elements based on this amount for visual appeal. 339const int kFrameShadowThickness = 1; 340// In the window corners, the resize areas don't actually expand bigger, but the 341// 16 px at the end of each edge triggers diagonal resizing. 342const int kResizeAreaCornerSize = 16; 343// The titlebar never shrinks too short to show the caption button plus some 344// padding below it. 345const int kCaptionButtonHeightWithPadding = 19; 346// The titlebar has a 2 px 3D edge along the top and bottom. 347const int kTitlebarTopAndBottomEdgeThickness = 2; 348// The icon would never shrink below 16 px on a side, if there was one. 349const int kIconMinimumSize = 16; 350// The title text starts 2 px from the right edge of the left frame border. 351const int kTitleLeftSpacing = 2; 352// There is a 5 px gap between the title text and the caption buttons. 353const int kTitleCaptionSpacing = 5; 354 355const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); 356 357} // namespace 358 359ConstrainedWindowFrameView::ConstrainedWindowFrameView( 360 views::Widget* container, bool browser_is_off_the_record) 361 : NonClientFrameView(), 362 container_(container), 363 browser_is_off_the_record_(browser_is_off_the_record), 364 close_button_(new views::ImageButton(this)), 365 frame_background_(new views::FrameBackground()) { 366 InitClass(); 367 InitWindowResources(); 368 369 // Constrained windows always use the custom frame - they just have a 370 // different set of images. 371 container->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM); 372 373 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 374 close_button_->SetImage(views::CustomButton::STATE_NORMAL, 375 rb.GetImageSkiaNamed(IDR_CLOSE_SA)); 376 close_button_->SetImage(views::CustomButton::STATE_HOVERED, 377 rb.GetImageSkiaNamed(IDR_CLOSE_SA_H)); 378 close_button_->SetImage(views::CustomButton::STATE_PRESSED, 379 rb.GetImageSkiaNamed(IDR_CLOSE_SA_P)); 380 close_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, 381 views::ImageButton::ALIGN_MIDDLE); 382 AddChildView(close_button_); 383} 384 385ConstrainedWindowFrameView::~ConstrainedWindowFrameView() { 386} 387 388void ConstrainedWindowFrameView::UpdateWindowTitle() { 389 SchedulePaintInRect(title_bounds_); 390} 391 392gfx::Rect ConstrainedWindowFrameView::GetBoundsForClientView() const { 393 return client_view_bounds_; 394} 395 396gfx::Rect ConstrainedWindowFrameView::GetWindowBoundsForClientBounds( 397 const gfx::Rect& client_bounds) const { 398 int top_height = NonClientTopBorderHeight(); 399 int border_thickness = NonClientBorderThickness(); 400 return gfx::Rect(std::max(0, client_bounds.x() - border_thickness), 401 std::max(0, client_bounds.y() - top_height), 402 client_bounds.width() + (2 * border_thickness), 403 client_bounds.height() + top_height + border_thickness); 404} 405 406int ConstrainedWindowFrameView::NonClientHitTest(const gfx::Point& point) { 407 if (!bounds().Contains(point)) 408 return HTNOWHERE; 409 410 int frame_component = 411 container_->client_view()->NonClientHitTest(point); 412 413 // See if we're in the sysmenu region. (We check the ClientView first to be 414 // consistent with OpaqueBrowserFrameView; it's not really necessary here.) 415 gfx::Rect sysmenu_rect(IconBounds()); 416 sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect)); 417 if (sysmenu_rect.Contains(point)) 418 return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU; 419 420 if (frame_component != HTNOWHERE) 421 return frame_component; 422 423 // Then see if the point is within any of the window controls. 424 if (close_button_->GetMirroredBounds().Contains(point)) 425 return HTCLOSE; 426 427 int window_component = GetHTComponentForFrame(point, kFrameBorderThickness, 428 NonClientBorderThickness(), kResizeAreaCornerSize, kResizeAreaCornerSize, 429 container_->widget_delegate()->CanResize()); 430 // Fall back to the caption if no other component matches. 431 return (window_component == HTNOWHERE) ? HTCAPTION : window_component; 432} 433 434void ConstrainedWindowFrameView::GetWindowMask(const gfx::Size& size, 435 gfx::Path* window_mask) { 436 DCHECK(window_mask); 437 views::GetDefaultWindowMask(size, window_mask); 438} 439 440void ConstrainedWindowFrameView::OnPaint(gfx::Canvas* canvas) { 441 PaintFrameBorder(canvas); 442 PaintTitleBar(canvas); 443 PaintClientEdge(canvas); 444} 445 446void ConstrainedWindowFrameView::Layout() { 447 LayoutWindowControls(); 448 LayoutTitleBar(); 449 client_view_bounds_ = CalculateClientAreaBounds(width(), height()); 450} 451 452void ConstrainedWindowFrameView::OnThemeChanged() { 453 InitWindowResources(); 454} 455 456void ConstrainedWindowFrameView::ButtonPressed( 457 views::Button* sender, const ui::Event& event) { 458 if (sender == close_button_) 459 container_->Close(); 460} 461 462int ConstrainedWindowFrameView::NonClientBorderThickness() const { 463 return kFrameBorderThickness + kClientEdgeThickness; 464} 465 466int ConstrainedWindowFrameView::NonClientTopBorderHeight() const { 467 return std::max(kFrameBorderThickness + IconSize(), 468 kFrameShadowThickness + kCaptionButtonHeightWithPadding) + 469 TitlebarBottomThickness(); 470} 471 472int ConstrainedWindowFrameView::TitlebarBottomThickness() const { 473 return kTitlebarTopAndBottomEdgeThickness + kClientEdgeThickness; 474} 475 476int ConstrainedWindowFrameView::IconSize() const { 477#if defined(OS_WIN) 478 // This metric scales up if either the titlebar height or the titlebar font 479 // size are increased. 480 return GetSystemMetrics(SM_CYSMICON); 481#else 482 return std::max(title_font_->GetHeight(), kIconMinimumSize); 483#endif 484} 485 486gfx::Rect ConstrainedWindowFrameView::IconBounds() const { 487 int size = IconSize(); 488 // Our frame border has a different "3D look" than Windows'. Theirs has a 489 // more complex gradient on the top that they push their icon/title below; 490 // then the maximized window cuts this off and the icon/title are centered 491 // in the remaining space. Because the apparent shape of our border is 492 // simpler, using the same positioning makes things look slightly uncentered 493 // with restored windows, so instead of calculating the remaining space from 494 // below the frame border, we calculate from below the 3D edge. 495 int unavailable_px_at_top = kTitlebarTopAndBottomEdgeThickness; 496 // When the icon is shorter than the minimum space we reserve for the caption 497 // button, we vertically center it. We want to bias rounding to put extra 498 // space above the icon, since the 3D edge + client edge below looks (to the 499 // eye) more like additional space than does the 3D edge above; hence the +1. 500 int y = unavailable_px_at_top + (NonClientTopBorderHeight() - 501 unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2; 502 return gfx::Rect(kFrameBorderThickness + kTitleLeftSpacing, y, size, size); 503} 504 505void ConstrainedWindowFrameView::PaintFrameBorder(gfx::Canvas* canvas) { 506 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 507 frame_background_->set_frame_color(ThemeProperties::GetDefaultColor( 508 ThemeProperties::COLOR_FRAME)); 509 chrome::HostDesktopType desktop_type = 510 chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); 511 gfx::ImageSkia* theme_frame = rb.GetImageSkiaNamed( 512 chrome::MapThemeImage(desktop_type, IDR_THEME_FRAME)); 513 frame_background_->set_theme_image(theme_frame); 514 frame_background_->set_theme_overlay_image(NULL); 515 frame_background_->set_top_area_height(theme_frame->height()); 516 517 frame_background_->SetCornerImages( 518 resources_->GetPartImage(FRAME_TOP_LEFT_CORNER), 519 resources_->GetPartImage(FRAME_TOP_RIGHT_CORNER), 520 resources_->GetPartImage(FRAME_BOTTOM_LEFT_CORNER), 521 resources_->GetPartImage(FRAME_BOTTOM_RIGHT_CORNER)); 522 frame_background_->SetSideImages( 523 resources_->GetPartImage(FRAME_LEFT_EDGE), 524 resources_->GetPartImage(FRAME_TOP_EDGE), 525 resources_->GetPartImage(FRAME_RIGHT_EDGE), 526 resources_->GetPartImage(FRAME_BOTTOM_EDGE)); 527 frame_background_->PaintRestored(canvas, this); 528} 529 530void ConstrainedWindowFrameView::PaintTitleBar(gfx::Canvas* canvas) { 531 canvas->DrawStringInt( 532 container_->widget_delegate()->GetWindowTitle(), 533 *title_font_, GetTitleColor(), GetMirroredXForRect(title_bounds_), 534 title_bounds_.y(), title_bounds_.width(), title_bounds_.height()); 535} 536 537void ConstrainedWindowFrameView::PaintClientEdge(gfx::Canvas* canvas) { 538 gfx::Rect client_edge_bounds(CalculateClientAreaBounds(width(), height())); 539 client_edge_bounds.Inset(-kClientEdgeThickness, -kClientEdgeThickness); 540 gfx::Rect frame_shadow_bounds(client_edge_bounds); 541 frame_shadow_bounds.Inset(-kFrameShadowThickness, -kFrameShadowThickness); 542 543 canvas->FillRect(frame_shadow_bounds, kContentsBorderShadow); 544 canvas->FillRect(client_edge_bounds, views::kClientEdgeColor); 545} 546 547void ConstrainedWindowFrameView::LayoutWindowControls() { 548 gfx::Size close_button_size = close_button_->GetPreferredSize(); 549 close_button_->SetBounds( 550 width() - kFrameBorderThickness - close_button_size.width(), 551 kFrameShadowThickness, close_button_size.width(), 552 close_button_size.height()); 553} 554 555void ConstrainedWindowFrameView::LayoutTitleBar() { 556 // The window title is based on the calculated icon position, even though' 557 // there is no icon in constrained windows. 558 gfx::Rect icon_bounds(IconBounds()); 559 int title_x = icon_bounds.x(); 560 int title_height = title_font_->GetHeight(); 561 // We bias the title position so that when the difference between the icon and 562 // title heights is odd, the extra pixel of the title is above the vertical 563 // midline rather than below. This compensates for how the icon is already 564 // biased downwards (see IconBounds()) and helps prevent descenders on the 565 // title from overlapping the 3D edge at the bottom of the titlebar. 566 title_bounds_.SetRect(title_x, 567 icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2), 568 std::max(0, close_button_->x() - kTitleCaptionSpacing - title_x), 569 title_height); 570} 571 572gfx::Rect ConstrainedWindowFrameView::CalculateClientAreaBounds( 573 int width, 574 int height) const { 575 int top_height = NonClientTopBorderHeight(); 576 int border_thickness = NonClientBorderThickness(); 577 return gfx::Rect(border_thickness, top_height, 578 std::max(0, width - (2 * border_thickness)), 579 std::max(0, height - top_height - border_thickness)); 580} 581 582void ConstrainedWindowFrameView::InitWindowResources() { 583#if defined(OS_WIN) && !defined(USE_AURA) 584 resources_.reset(ui::win::IsAeroGlassEnabled() ? 585 static_cast<views::WindowResources*>(new VistaWindowResources) : 586 new XPWindowResources); 587#else 588 // TODO(oshima): Use aura frame decoration. 589 resources_.reset(new XPWindowResources); 590#endif 591} 592 593// static 594void ConstrainedWindowFrameView::InitClass() { 595 static bool initialized = false; 596 if (!initialized) { 597#if defined(OS_WIN) && !defined(USE_AURA) 598 title_font_ = new gfx::Font(views::NativeWidgetWin::GetWindowTitleFont()); 599#else 600 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 601 title_font_ = &rb.GetFont(ui::ResourceBundle::MediumFont); 602#endif 603 initialized = true; 604 } 605} 606 607#if defined(USE_ASH) 608// Ash has its own window frames, but we need the special close semantics for 609// constrained windows. 610class ConstrainedWindowFrameViewAsh : public ash::CustomFrameViewAsh { 611 public: 612 explicit ConstrainedWindowFrameViewAsh() 613 : ash::CustomFrameViewAsh(), 614 container_(NULL) { 615 } 616 617 void Init(views::Widget* container) { 618 container_ = container; 619 ash::CustomFrameViewAsh::Init(container); 620 // Always use "active" look. 621 SetInactiveRenderingDisabled(true); 622 } 623 624 // views::ButtonListener overrides: 625 virtual void ButtonPressed(views::Button* sender, 626 const ui::Event& event) OVERRIDE { 627 if (sender == close_button()) 628 container_->Close(); 629 } 630 631 private: 632 views::Widget* container_; // not owned 633 DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowFrameViewAsh); 634}; 635#endif // defined(USE_ASH) 636 637views::Widget* CreateWebContentsModalDialogViews( 638 views::WidgetDelegate* widget_delegate, 639 gfx::NativeView parent, 640 WebContentsModalDialogHost* dialog_host) { 641 views::Widget* dialog = new views::Widget; 642 643 views::Widget::InitParams params; 644 params.delegate = widget_delegate; 645 params.child = true; 646 WebContentsModalDialogHostObserver* dialog_host_observer = NULL; 647 if (views::DialogDelegate::UseNewStyle()) { 648 params.parent = dialog_host->GetHostView(); 649 params.remove_standard_frame = true; 650 dialog_host_observer = 651 new WebContentsModalDialogHostObserverViews( 652 dialog_host, 653 dialog, 654 kWebContentsModalDialogHostObserverViewsKey); 655#if defined(USE_AURA) 656 params.transparent = true; 657#endif 658 } else { 659 params.parent = parent; 660 } 661 662 dialog->Init(params); 663 664#if defined(USE_AURA) 665 if (views::DialogDelegate::UseNewStyle()) { 666 // TODO(msw): Add a matching shadow type and remove the bubble frame border? 667 views::corewm::SetShadowType(dialog->GetNativeWindow(), 668 views::corewm::SHADOW_TYPE_NONE); 669 } 670#endif 671 672 if (dialog_host_observer) { 673 dialog_host_observer->OnPositionRequiresUpdate(); 674 dialog->SetNativeWindowProperty(kWebContentsModalDialogHostObserverViewsKey, 675 dialog_host_observer); 676 } 677 678 return dialog; 679} 680 681views::NonClientFrameView* CreateConstrainedStyleNonClientFrameView( 682 views::Widget* widget, 683 content::BrowserContext* browser_context) { 684 if (views::DialogDelegate::UseNewStyle()) { 685#if defined(USE_AURA) 686 const bool force_opaque_border = false; 687#else 688 const bool force_opaque_border = true; 689#endif 690 return views::DialogDelegate::CreateNewStyleFrameView(widget, 691 force_opaque_border); 692 } 693#if defined(USE_ASH) 694 ConstrainedWindowFrameViewAsh* frame = new ConstrainedWindowFrameViewAsh; 695 frame->Init(widget); 696 return frame; 697#endif 698 return new ConstrainedWindowFrameView(widget, 699 browser_context->IsOffTheRecord()); 700} 701