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/constrained_window_views.h" 6 7 #include <algorithm> 8 9 #include "chrome/app/chrome_command_ids.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/ui/toolbar/toolbar_model.h" 12 #include "chrome/browser/ui/views/frame/browser_view.h" 13 #include "chrome/browser/ui/window_sizer.h" 14 #include "chrome/common/chrome_constants.h" 15 #include "content/browser/tab_contents/tab_contents.h" 16 #include "content/browser/tab_contents/tab_contents_view.h" 17 #include "content/common/notification_service.h" 18 #include "grit/app_resources.h" 19 #include "grit/chromium_strings.h" 20 #include "grit/generated_resources.h" 21 #include "grit/theme_resources.h" 22 #include "net/base/net_util.h" 23 #include "ui/base/resource/resource_bundle.h" 24 #include "ui/gfx/canvas.h" 25 #include "ui/gfx/font.h" 26 #include "ui/gfx/path.h" 27 #include "ui/gfx/rect.h" 28 #include "views/controls/button/image_button.h" 29 #include "views/focus/focus_manager.h" 30 #include "views/window/client_view.h" 31 #include "views/window/native_window.h" 32 #include "views/window/non_client_view.h" 33 #include "views/window/window_resources.h" 34 #include "views/window/window_shape.h" 35 #include "views/window/window.h" 36 37 #if defined(OS_WIN) 38 #include "views/widget/widget_win.h" 39 #include "views/window/window_win.h" 40 #endif 41 42 using base::TimeDelta; 43 44 namespace views { 45 class ClientView; 46 } 47 48 // An enumeration of bitmap resources used by this window. 49 enum { 50 FRAME_PART_BITMAP_FIRST = 0, // Must be first. 51 52 // Window Frame Border. 53 FRAME_BOTTOM_EDGE, 54 FRAME_BOTTOM_LEFT_CORNER, 55 FRAME_BOTTOM_RIGHT_CORNER, 56 FRAME_LEFT_EDGE, 57 FRAME_RIGHT_EDGE, 58 FRAME_TOP_EDGE, 59 FRAME_TOP_LEFT_CORNER, 60 FRAME_TOP_RIGHT_CORNER, 61 62 FRAME_PART_BITMAP_COUNT // Must be last. 63 }; 64 65 static const int kXPFramePartIDs[] = { 66 0, 67 IDR_WINDOW_BOTTOM_CENTER, IDR_WINDOW_BOTTOM_LEFT_CORNER, 68 IDR_WINDOW_BOTTOM_RIGHT_CORNER, IDR_WINDOW_LEFT_SIDE, 69 IDR_WINDOW_RIGHT_SIDE, IDR_WINDOW_TOP_CENTER, 70 IDR_WINDOW_TOP_LEFT_CORNER, IDR_WINDOW_TOP_RIGHT_CORNER, 71 0 }; 72 static const int kVistaFramePartIDs[] = { 73 0, 74 IDR_CONSTRAINED_BOTTOM_CENTER_V, IDR_CONSTRAINED_BOTTOM_LEFT_CORNER_V, 75 IDR_CONSTRAINED_BOTTOM_RIGHT_CORNER_V, IDR_CONSTRAINED_LEFT_SIDE_V, 76 IDR_CONSTRAINED_RIGHT_SIDE_V, IDR_CONSTRAINED_TOP_CENTER_V, 77 IDR_CONSTRAINED_TOP_LEFT_CORNER_V, IDR_CONSTRAINED_TOP_RIGHT_CORNER_V, 78 0 }; 79 80 class XPWindowResources : public views::WindowResources { 81 public: 82 XPWindowResources() { 83 InitClass(); 84 } 85 virtual ~XPWindowResources() {} 86 87 virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part_id) const { 88 return bitmaps_[part_id]; 89 } 90 91 private: 92 static void InitClass() { 93 static bool initialized = false; 94 if (!initialized) { 95 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 96 for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) { 97 int id = kXPFramePartIDs[i]; 98 if (id != 0) 99 bitmaps_[i] = rb.GetBitmapNamed(id); 100 } 101 initialized = true; 102 } 103 } 104 105 static SkBitmap* bitmaps_[FRAME_PART_BITMAP_COUNT]; 106 107 DISALLOW_COPY_AND_ASSIGN(XPWindowResources); 108 }; 109 110 class VistaWindowResources : public views::WindowResources { 111 public: 112 VistaWindowResources() { 113 InitClass(); 114 } 115 virtual ~VistaWindowResources() {} 116 117 virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part_id) const { 118 return bitmaps_[part_id]; 119 } 120 121 private: 122 static void InitClass() { 123 static bool initialized = false; 124 if (!initialized) { 125 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 126 for (int i = 0; i < FRAME_PART_BITMAP_COUNT; ++i) { 127 int id = kVistaFramePartIDs[i]; 128 if (id != 0) 129 bitmaps_[i] = rb.GetBitmapNamed(id); 130 } 131 initialized = true; 132 } 133 } 134 135 static SkBitmap* bitmaps_[FRAME_PART_BITMAP_COUNT]; 136 137 DISALLOW_COPY_AND_ASSIGN(VistaWindowResources); 138 }; 139 140 SkBitmap* XPWindowResources::bitmaps_[]; 141 SkBitmap* VistaWindowResources::bitmaps_[]; 142 143 //////////////////////////////////////////////////////////////////////////////// 144 // ConstrainedWindowFrameView 145 146 class ConstrainedWindowFrameView 147 : public views::NonClientFrameView, 148 public views::ButtonListener { 149 public: 150 explicit ConstrainedWindowFrameView(ConstrainedWindowViews* container); 151 virtual ~ConstrainedWindowFrameView(); 152 153 void UpdateWindowTitle(); 154 155 // Overridden from views::NonClientFrameView: 156 virtual gfx::Rect GetBoundsForClientView() const OVERRIDE; 157 virtual bool AlwaysUseCustomFrame() const OVERRIDE; 158 virtual gfx::Rect GetWindowBoundsForClientBounds( 159 const gfx::Rect& client_bounds) const OVERRIDE; 160 virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE; 161 virtual void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) 162 OVERRIDE; 163 virtual void EnableClose(bool enable) OVERRIDE; 164 virtual void ResetWindowControls() OVERRIDE {} 165 virtual void UpdateWindowIcon() OVERRIDE {} 166 167 // Overridden from views::View: 168 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 169 virtual void Layout() OVERRIDE; 170 virtual void OnThemeChanged() OVERRIDE; 171 172 // Overridden from views::ButtonListener: 173 virtual void ButtonPressed(views::Button* sender, const views::Event& event) 174 OVERRIDE; 175 176 private: 177 // Returns the thickness of the entire nonclient left, right, and bottom 178 // borders, including both the window frame and any client edge. 179 int NonClientBorderThickness() const; 180 181 // Returns the height of the entire nonclient top border, including the window 182 // frame, any title area, and any connected client edge. 183 int NonClientTopBorderHeight() const; 184 185 // Returns the thickness of the nonclient portion of the 3D edge along the 186 // bottom of the titlebar. 187 int TitlebarBottomThickness() const; 188 189 // Returns what the size of the titlebar icon would be if there was one. 190 int IconSize() const; 191 192 // Returns what the titlebar icon's bounds would be if there was one. 193 gfx::Rect IconBounds() const; 194 195 // Paints different parts of the window to the incoming canvas. 196 void PaintFrameBorder(gfx::Canvas* canvas); 197 void PaintTitleBar(gfx::Canvas* canvas); 198 void PaintClientEdge(gfx::Canvas* canvas); 199 200 // Layout various sub-components of this view. 201 void LayoutWindowControls(); 202 void LayoutTitleBar(); 203 204 // Returns the bounds of the client area for the specified view size. 205 gfx::Rect CalculateClientAreaBounds(int width, int height) const; 206 207 SkColor GetTitleColor() const { 208 return container_->owner()->profile()->IsOffTheRecord() 209 #if defined(OS_WIN) 210 || !views::WidgetWin::IsAeroGlassEnabled() 211 #endif 212 ? SK_ColorWHITE : SK_ColorBLACK; 213 } 214 215 // Loads the appropriate set of WindowResources for the frame view. 216 void InitWindowResources(); 217 218 ConstrainedWindowViews* container_; 219 220 scoped_ptr<views::WindowResources> resources_; 221 222 gfx::Rect title_bounds_; 223 224 views::ImageButton* close_button_; 225 226 // The bounds of the ClientView. 227 gfx::Rect client_view_bounds_; 228 229 static void InitClass(); 230 231 // The font to be used to render the titlebar text. 232 static gfx::Font* title_font_; 233 234 DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowFrameView); 235 }; 236 237 gfx::Font* ConstrainedWindowFrameView::title_font_ = NULL; 238 239 namespace { 240 // The frame border is only visible in restored mode and is hardcoded to 4 px on 241 // each side regardless of the system window border size. 242 const int kFrameBorderThickness = 4; 243 // Various edges of the frame border have a 1 px shadow along their edges; in a 244 // few cases we shift elements based on this amount for visual appeal. 245 const int kFrameShadowThickness = 1; 246 // In the window corners, the resize areas don't actually expand bigger, but the 247 // 16 px at the end of each edge triggers diagonal resizing. 248 const int kResizeAreaCornerSize = 16; 249 // The titlebar never shrinks too short to show the caption button plus some 250 // padding below it. 251 const int kCaptionButtonHeightWithPadding = 19; 252 // The titlebar has a 2 px 3D edge along the top and bottom. 253 const int kTitlebarTopAndBottomEdgeThickness = 2; 254 // The icon would never shrink below 16 px on a side, if there was one. 255 const int kIconMinimumSize = 16; 256 // The title text starts 2 px from the right edge of the left frame border. 257 const int kTitleLeftSpacing = 2; 258 // There is a 5 px gap between the title text and the caption buttons. 259 const int kTitleCaptionSpacing = 5; 260 261 const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); 262 } 263 264 //////////////////////////////////////////////////////////////////////////////// 265 // ConstrainedWindowFrameView, public: 266 267 ConstrainedWindowFrameView::ConstrainedWindowFrameView( 268 ConstrainedWindowViews* container) 269 : NonClientFrameView(), 270 container_(container), 271 close_button_(new views::ImageButton(this)) { 272 InitClass(); 273 InitWindowResources(); 274 275 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 276 close_button_->SetImage(views::CustomButton::BS_NORMAL, 277 rb.GetBitmapNamed(IDR_CLOSE_SA)); 278 close_button_->SetImage(views::CustomButton::BS_HOT, 279 rb.GetBitmapNamed(IDR_CLOSE_SA_H)); 280 close_button_->SetImage(views::CustomButton::BS_PUSHED, 281 rb.GetBitmapNamed(IDR_CLOSE_SA_P)); 282 close_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, 283 views::ImageButton::ALIGN_MIDDLE); 284 AddChildView(close_button_); 285 } 286 287 ConstrainedWindowFrameView::~ConstrainedWindowFrameView() { 288 } 289 290 void ConstrainedWindowFrameView::UpdateWindowTitle() { 291 SchedulePaintInRect(title_bounds_); 292 } 293 294 //////////////////////////////////////////////////////////////////////////////// 295 // ConstrainedWindowFrameView, views::NonClientFrameView implementation: 296 297 gfx::Rect ConstrainedWindowFrameView::GetBoundsForClientView() const { 298 return client_view_bounds_; 299 } 300 301 bool ConstrainedWindowFrameView::AlwaysUseCustomFrame() const { 302 // Constrained windows always use the custom frame - they just have a 303 // different set of bitmaps. 304 return true; 305 } 306 307 gfx::Rect ConstrainedWindowFrameView::GetWindowBoundsForClientBounds( 308 const gfx::Rect& client_bounds) const { 309 int top_height = NonClientTopBorderHeight(); 310 int border_thickness = NonClientBorderThickness(); 311 return gfx::Rect(std::max(0, client_bounds.x() - border_thickness), 312 std::max(0, client_bounds.y() - top_height), 313 client_bounds.width() + (2 * border_thickness), 314 client_bounds.height() + top_height + border_thickness); 315 } 316 317 int ConstrainedWindowFrameView::NonClientHitTest(const gfx::Point& point) { 318 if (!bounds().Contains(point)) 319 return HTNOWHERE; 320 321 int frame_component = 322 container_->GetWindow()->client_view()->NonClientHitTest(point); 323 324 // See if we're in the sysmenu region. (We check the ClientView first to be 325 // consistent with OpaqueBrowserFrameView; it's not really necessary here.) 326 gfx::Rect sysmenu_rect(IconBounds()); 327 sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect)); 328 if (sysmenu_rect.Contains(point)) 329 return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU; 330 331 if (frame_component != HTNOWHERE) 332 return frame_component; 333 334 // Then see if the point is within any of the window controls. 335 if (close_button_->GetMirroredBounds().Contains(point)) 336 return HTCLOSE; 337 338 int window_component = GetHTComponentForFrame(point, kFrameBorderThickness, 339 NonClientBorderThickness(), kResizeAreaCornerSize, kResizeAreaCornerSize, 340 container_->GetWindow()->window_delegate()->CanResize()); 341 // Fall back to the caption if no other component matches. 342 return (window_component == HTNOWHERE) ? HTCAPTION : window_component; 343 } 344 345 void ConstrainedWindowFrameView::GetWindowMask(const gfx::Size& size, 346 gfx::Path* window_mask) { 347 DCHECK(window_mask); 348 views::GetDefaultWindowMask(size, window_mask); 349 } 350 351 void ConstrainedWindowFrameView::EnableClose(bool enable) { 352 close_button_->SetEnabled(enable); 353 } 354 355 //////////////////////////////////////////////////////////////////////////////// 356 // ConstrainedWindowFrameView, views::View implementation: 357 358 void ConstrainedWindowFrameView::OnPaint(gfx::Canvas* canvas) { 359 PaintFrameBorder(canvas); 360 PaintTitleBar(canvas); 361 PaintClientEdge(canvas); 362 } 363 364 void ConstrainedWindowFrameView::Layout() { 365 LayoutWindowControls(); 366 LayoutTitleBar(); 367 client_view_bounds_ = CalculateClientAreaBounds(width(), height()); 368 } 369 370 void ConstrainedWindowFrameView::OnThemeChanged() { 371 InitWindowResources(); 372 } 373 374 //////////////////////////////////////////////////////////////////////////////// 375 // ConstrainedWindowFrameView, views::ButtonListener implementation: 376 377 void ConstrainedWindowFrameView::ButtonPressed( 378 views::Button* sender, const views::Event& event) { 379 if (sender == close_button_) 380 container_->CloseConstrainedWindow(); 381 } 382 383 //////////////////////////////////////////////////////////////////////////////// 384 // ConstrainedWindowFrameView, private: 385 386 int ConstrainedWindowFrameView::NonClientBorderThickness() const { 387 return kFrameBorderThickness + kClientEdgeThickness; 388 } 389 390 int ConstrainedWindowFrameView::NonClientTopBorderHeight() const { 391 return std::max(kFrameBorderThickness + IconSize(), 392 kFrameShadowThickness + kCaptionButtonHeightWithPadding) + 393 TitlebarBottomThickness(); 394 } 395 396 int ConstrainedWindowFrameView::TitlebarBottomThickness() const { 397 return kTitlebarTopAndBottomEdgeThickness + kClientEdgeThickness; 398 } 399 400 int ConstrainedWindowFrameView::IconSize() const { 401 #if defined(OS_WIN) 402 // This metric scales up if either the titlebar height or the titlebar font 403 // size are increased. 404 return GetSystemMetrics(SM_CYSMICON); 405 #else 406 return std::max(title_font_->height(), kIconMinimumSize); 407 #endif 408 } 409 410 gfx::Rect ConstrainedWindowFrameView::IconBounds() const { 411 int size = IconSize(); 412 // Our frame border has a different "3D look" than Windows'. Theirs has a 413 // more complex gradient on the top that they push their icon/title below; 414 // then the maximized window cuts this off and the icon/title are centered 415 // in the remaining space. Because the apparent shape of our border is 416 // simpler, using the same positioning makes things look slightly uncentered 417 // with restored windows, so instead of calculating the remaining space from 418 // below the frame border, we calculate from below the 3D edge. 419 int unavailable_px_at_top = kTitlebarTopAndBottomEdgeThickness; 420 // When the icon is shorter than the minimum space we reserve for the caption 421 // button, we vertically center it. We want to bias rounding to put extra 422 // space above the icon, since the 3D edge + client edge below looks (to the 423 // eye) more like additional space than does the 3D edge above; hence the +1. 424 int y = unavailable_px_at_top + (NonClientTopBorderHeight() - 425 unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2; 426 return gfx::Rect(kFrameBorderThickness + kTitleLeftSpacing, y, size, size); 427 } 428 429 void ConstrainedWindowFrameView::PaintFrameBorder(gfx::Canvas* canvas) { 430 SkBitmap* top_left_corner = resources_->GetPartBitmap(FRAME_TOP_LEFT_CORNER); 431 SkBitmap* top_right_corner = 432 resources_->GetPartBitmap(FRAME_TOP_RIGHT_CORNER); 433 SkBitmap* top_edge = resources_->GetPartBitmap(FRAME_TOP_EDGE); 434 SkBitmap* right_edge = resources_->GetPartBitmap(FRAME_RIGHT_EDGE); 435 SkBitmap* left_edge = resources_->GetPartBitmap(FRAME_LEFT_EDGE); 436 SkBitmap* bottom_left_corner = 437 resources_->GetPartBitmap(FRAME_BOTTOM_LEFT_CORNER); 438 SkBitmap* bottom_right_corner = 439 resources_->GetPartBitmap(FRAME_BOTTOM_RIGHT_CORNER); 440 SkBitmap* bottom_edge = resources_->GetPartBitmap(FRAME_BOTTOM_EDGE); 441 442 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 443 SkBitmap* theme_frame = rb.GetBitmapNamed(IDR_THEME_FRAME); 444 SkColor frame_color = ResourceBundle::frame_color; 445 446 // Fill with the frame color first so we have a constant background for 447 // areas not covered by the theme image. 448 canvas->FillRectInt(frame_color, 0, 0, width(), theme_frame->height()); 449 // Now fill down the sides. 450 canvas->FillRectInt(frame_color, 0, theme_frame->height(), left_edge->width(), 451 height() - theme_frame->height()); 452 canvas->FillRectInt(frame_color, width() - right_edge->width(), 453 theme_frame->height(), right_edge->width(), 454 height() - theme_frame->height()); 455 // Now fill the bottom area. 456 canvas->FillRectInt(frame_color, 457 left_edge->width(), height() - bottom_edge->height(), 458 width() - left_edge->width() - right_edge->width(), 459 bottom_edge->height()); 460 461 // Draw the theme frame. 462 canvas->TileImageInt(*theme_frame, 0, 0, width(), theme_frame->height()); 463 464 // Top. 465 canvas->DrawBitmapInt(*top_left_corner, 0, 0); 466 canvas->TileImageInt(*top_edge, top_left_corner->width(), 0, 467 width() - top_right_corner->width(), top_edge->height()); 468 canvas->DrawBitmapInt(*top_right_corner, 469 width() - top_right_corner->width(), 0); 470 471 // Right. 472 canvas->TileImageInt(*right_edge, width() - right_edge->width(), 473 top_right_corner->height(), right_edge->width(), 474 height() - top_right_corner->height() - bottom_right_corner->height()); 475 476 // Bottom. 477 canvas->DrawBitmapInt(*bottom_right_corner, 478 width() - bottom_right_corner->width(), 479 height() - bottom_right_corner->height()); 480 canvas->TileImageInt(*bottom_edge, bottom_left_corner->width(), 481 height() - bottom_edge->height(), 482 width() - bottom_left_corner->width() - bottom_right_corner->width(), 483 bottom_edge->height()); 484 canvas->DrawBitmapInt(*bottom_left_corner, 0, 485 height() - bottom_left_corner->height()); 486 487 // Left. 488 canvas->TileImageInt(*left_edge, 0, top_left_corner->height(), 489 left_edge->width(), 490 height() - top_left_corner->height() - bottom_left_corner->height()); 491 } 492 493 void ConstrainedWindowFrameView::PaintTitleBar(gfx::Canvas* canvas) { 494 canvas->DrawStringInt( 495 container_->GetWindow()->window_delegate()->GetWindowTitle(), 496 *title_font_, GetTitleColor(), GetMirroredXForRect(title_bounds_), 497 title_bounds_.y(), title_bounds_.width(), title_bounds_.height()); 498 } 499 500 void ConstrainedWindowFrameView::PaintClientEdge(gfx::Canvas* canvas) { 501 gfx::Rect client_edge_bounds(CalculateClientAreaBounds(width(), height())); 502 client_edge_bounds.Inset(-kClientEdgeThickness, -kClientEdgeThickness); 503 gfx::Rect frame_shadow_bounds(client_edge_bounds); 504 frame_shadow_bounds.Inset(-kFrameShadowThickness, -kFrameShadowThickness); 505 506 canvas->FillRectInt(kContentsBorderShadow, frame_shadow_bounds.x(), 507 frame_shadow_bounds.y(), frame_shadow_bounds.width(), 508 frame_shadow_bounds.height()); 509 510 canvas->FillRectInt(ResourceBundle::toolbar_color, client_edge_bounds.x(), 511 client_edge_bounds.y(), client_edge_bounds.width(), 512 client_edge_bounds.height()); 513 } 514 515 void ConstrainedWindowFrameView::LayoutWindowControls() { 516 gfx::Size close_button_size = close_button_->GetPreferredSize(); 517 close_button_->SetBounds( 518 width() - kFrameBorderThickness - close_button_size.width(), 519 kFrameShadowThickness, close_button_size.width(), 520 close_button_size.height()); 521 } 522 523 void ConstrainedWindowFrameView::LayoutTitleBar() { 524 // The window title is based on the calculated icon position, even though' 525 // there is no icon in constrained windows. 526 gfx::Rect icon_bounds(IconBounds()); 527 int title_x = icon_bounds.x(); 528 int title_height = title_font_->GetHeight(); 529 // We bias the title position so that when the difference between the icon and 530 // title heights is odd, the extra pixel of the title is above the vertical 531 // midline rather than below. This compensates for how the icon is already 532 // biased downwards (see IconBounds()) and helps prevent descenders on the 533 // title from overlapping the 3D edge at the bottom of the titlebar. 534 title_bounds_.SetRect(title_x, 535 icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2), 536 std::max(0, close_button_->x() - kTitleCaptionSpacing - title_x), 537 title_height); 538 } 539 540 gfx::Rect ConstrainedWindowFrameView::CalculateClientAreaBounds( 541 int width, 542 int height) const { 543 int top_height = NonClientTopBorderHeight(); 544 int border_thickness = NonClientBorderThickness(); 545 return gfx::Rect(border_thickness, top_height, 546 std::max(0, width - (2 * border_thickness)), 547 std::max(0, height - top_height - border_thickness)); 548 } 549 550 void ConstrainedWindowFrameView::InitWindowResources() { 551 resources_.reset(views::WidgetWin::IsAeroGlassEnabled() ? 552 static_cast<views::WindowResources*>(new VistaWindowResources) : 553 new XPWindowResources); 554 } 555 556 // static 557 void ConstrainedWindowFrameView::InitClass() { 558 static bool initialized = false; 559 if (!initialized) { 560 #if defined(OS_WIN) 561 title_font_ = new gfx::Font(views::WindowWin::GetWindowTitleFont()); 562 #endif 563 initialized = true; 564 } 565 } 566 567 //////////////////////////////////////////////////////////////////////////////// 568 // ConstrainedWindowViews, public: 569 570 ConstrainedWindowViews::ConstrainedWindowViews( 571 TabContents* owner, 572 views::WindowDelegate* window_delegate) 573 : owner_(owner), 574 ALLOW_THIS_IN_INITIALIZER_LIST(native_constrained_window_( 575 NativeConstrainedWindow::CreateNativeConstrainedWindow( 576 this, window_delegate))) { 577 GetWindow()->non_client_view()->SetFrameView(CreateFrameViewForWindow()); 578 native_constrained_window_->InitNativeConstrainedWindow( 579 owner->GetNativeView()); 580 } 581 582 ConstrainedWindowViews::~ConstrainedWindowViews() { 583 } 584 585 views::Window* ConstrainedWindowViews::GetWindow() { 586 return native_constrained_window_->AsNativeWindow()->GetWindow(); 587 } 588 589 //////////////////////////////////////////////////////////////////////////////// 590 // ConstrainedWindowViews, ConstrainedWindow implementation: 591 592 void ConstrainedWindowViews::ShowConstrainedWindow() { 593 // We marked the view as hidden during construction. Mark it as 594 // visible now so FocusManager will let us receive focus. 595 GetWindow()->non_client_view()->SetVisible(true); 596 if (owner_->delegate()) 597 owner_->delegate()->WillShowConstrainedWindow(owner_); 598 GetWindow()->Activate(); 599 FocusConstrainedWindow(); 600 } 601 602 void ConstrainedWindowViews::CloseConstrainedWindow() { 603 // Broadcast to all observers of NOTIFY_CWINDOW_CLOSED. 604 // One example of such an observer is AutomationCWindowTracker in the 605 // automation component. 606 NotificationService::current()->Notify(NotificationType::CWINDOW_CLOSED, 607 Source<ConstrainedWindow>(this), 608 NotificationService::NoDetails()); 609 GetWindow()->CloseWindow(); 610 } 611 612 void ConstrainedWindowViews::FocusConstrainedWindow() { 613 if ((!owner_->delegate() || 614 owner_->delegate()->ShouldFocusConstrainedWindow()) && 615 GetWindow()->window_delegate() && 616 GetWindow()->window_delegate()->GetInitiallyFocusedView()) { 617 GetWindow()->window_delegate()->GetInitiallyFocusedView()->RequestFocus(); 618 } 619 } 620 621 //////////////////////////////////////////////////////////////////////////////// 622 // ConstrainedWindowViews, NativeConstrainedWindowDelegate implementation: 623 624 void ConstrainedWindowViews::OnNativeConstrainedWindowDestroyed() { 625 // Tell our constraining TabContents that we've gone so it can update its 626 // list. 627 owner_->WillClose(this); 628 } 629 630 void ConstrainedWindowViews::OnNativeConstrainedWindowMouseActivate() { 631 GetWindow()->Activate(); 632 } 633 634 views::NonClientFrameView* ConstrainedWindowViews::CreateFrameViewForWindow() { 635 return new ConstrainedWindowFrameView(this); 636 } 637 638 //////////////////////////////////////////////////////////////////////////////// 639 // ConstrainedWindow, public: 640 641 // static 642 ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog( 643 TabContents* parent, 644 views::WindowDelegate* window_delegate) { 645 return new ConstrainedWindowViews(parent, window_delegate); 646 } 647