Home | History | Annotate | Download | only in views
      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