• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
XPWindowResources()82   XPWindowResources() {
83     InitClass();
84   }
~XPWindowResources()85   virtual ~XPWindowResources() {}
86 
GetPartBitmap(views::FramePartBitmap part_id) const87   virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part_id) const {
88     return bitmaps_[part_id];
89   }
90 
91  private:
InitClass()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:
VistaWindowResources()112   VistaWindowResources() {
113     InitClass();
114   }
~VistaWindowResources()115   virtual ~VistaWindowResources() {}
116 
GetPartBitmap(views::FramePartBitmap part_id) const117   virtual SkBitmap* GetPartBitmap(views::FramePartBitmap part_id) const {
118     return bitmaps_[part_id];
119   }
120 
121  private:
InitClass()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;
ResetWindowControls()164   virtual void ResetWindowControls() OVERRIDE {}
UpdateWindowIcon()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 
GetTitleColor() const207   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 
ConstrainedWindowFrameView(ConstrainedWindowViews * container)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 
~ConstrainedWindowFrameView()287 ConstrainedWindowFrameView::~ConstrainedWindowFrameView() {
288 }
289 
UpdateWindowTitle()290 void ConstrainedWindowFrameView::UpdateWindowTitle() {
291   SchedulePaintInRect(title_bounds_);
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 // ConstrainedWindowFrameView, views::NonClientFrameView implementation:
296 
GetBoundsForClientView() const297 gfx::Rect ConstrainedWindowFrameView::GetBoundsForClientView() const {
298   return client_view_bounds_;
299 }
300 
AlwaysUseCustomFrame() const301 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 
GetWindowBoundsForClientBounds(const gfx::Rect & client_bounds) const307 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 
NonClientHitTest(const gfx::Point & point)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 
GetWindowMask(const gfx::Size & size,gfx::Path * window_mask)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 
EnableClose(bool enable)351 void ConstrainedWindowFrameView::EnableClose(bool enable) {
352   close_button_->SetEnabled(enable);
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 // ConstrainedWindowFrameView, views::View implementation:
357 
OnPaint(gfx::Canvas * canvas)358 void ConstrainedWindowFrameView::OnPaint(gfx::Canvas* canvas) {
359   PaintFrameBorder(canvas);
360   PaintTitleBar(canvas);
361   PaintClientEdge(canvas);
362 }
363 
Layout()364 void ConstrainedWindowFrameView::Layout() {
365   LayoutWindowControls();
366   LayoutTitleBar();
367   client_view_bounds_ = CalculateClientAreaBounds(width(), height());
368 }
369 
OnThemeChanged()370 void ConstrainedWindowFrameView::OnThemeChanged() {
371   InitWindowResources();
372 }
373 
374 ////////////////////////////////////////////////////////////////////////////////
375 // ConstrainedWindowFrameView, views::ButtonListener implementation:
376 
ButtonPressed(views::Button * sender,const views::Event & event)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 
NonClientBorderThickness() const386 int ConstrainedWindowFrameView::NonClientBorderThickness() const {
387   return kFrameBorderThickness + kClientEdgeThickness;
388 }
389 
NonClientTopBorderHeight() const390 int ConstrainedWindowFrameView::NonClientTopBorderHeight() const {
391   return std::max(kFrameBorderThickness + IconSize(),
392                   kFrameShadowThickness + kCaptionButtonHeightWithPadding) +
393       TitlebarBottomThickness();
394 }
395 
TitlebarBottomThickness() const396 int ConstrainedWindowFrameView::TitlebarBottomThickness() const {
397   return kTitlebarTopAndBottomEdgeThickness + kClientEdgeThickness;
398 }
399 
IconSize() const400 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 
IconBounds() const410 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 
PaintFrameBorder(gfx::Canvas * canvas)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 
PaintTitleBar(gfx::Canvas * canvas)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 
PaintClientEdge(gfx::Canvas * canvas)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 
LayoutWindowControls()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 
LayoutTitleBar()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 
CalculateClientAreaBounds(int width,int height) const540 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 
InitWindowResources()550 void ConstrainedWindowFrameView::InitWindowResources() {
551   resources_.reset(views::WidgetWin::IsAeroGlassEnabled() ?
552     static_cast<views::WindowResources*>(new VistaWindowResources) :
553     new XPWindowResources);
554 }
555 
556 // static
InitClass()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 
ConstrainedWindowViews(TabContents * owner,views::WindowDelegate * window_delegate)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 
~ConstrainedWindowViews()582 ConstrainedWindowViews::~ConstrainedWindowViews() {
583 }
584 
GetWindow()585 views::Window* ConstrainedWindowViews::GetWindow() {
586   return native_constrained_window_->AsNativeWindow()->GetWindow();
587 }
588 
589 ////////////////////////////////////////////////////////////////////////////////
590 // ConstrainedWindowViews, ConstrainedWindow implementation:
591 
ShowConstrainedWindow()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 
CloseConstrainedWindow()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 
FocusConstrainedWindow()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 
OnNativeConstrainedWindowDestroyed()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 
OnNativeConstrainedWindowMouseActivate()630 void ConstrainedWindowViews::OnNativeConstrainedWindowMouseActivate() {
631   GetWindow()->Activate();
632 }
633 
CreateFrameViewForWindow()634 views::NonClientFrameView* ConstrainedWindowViews::CreateFrameViewForWindow() {
635   return new ConstrainedWindowFrameView(this);
636 }
637 
638 ////////////////////////////////////////////////////////////////////////////////
639 // ConstrainedWindow, public:
640 
641 // static
CreateConstrainedDialog(TabContents * parent,views::WindowDelegate * window_delegate)642 ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog(
643     TabContents* parent,
644     views::WindowDelegate* window_delegate) {
645   return new ConstrainedWindowViews(parent, window_delegate);
646 }
647