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