summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-30 02:36:54 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-30 02:36:54 +0000
commiteabd506f273e5680225f0b0cabf6b2a162126cd4 (patch)
tree5cc9bddbda42f1473a39fa60712232cbd667b0ca /chrome
parent13324b2fe5b579fe0338ab30084b01e92e7523be (diff)
downloadchromium_src-eabd506f273e5680225f0b0cabf6b2a162126cd4.zip
chromium_src-eabd506f273e5680225f0b0cabf6b2a162126cd4.tar.gz
chromium_src-eabd506f273e5680225f0b0cabf6b2a162126cd4.tar.bz2
Fix various problems with constrained windows and/or custom frame windows:
* Wrong titlebar height * Titlebars not handling custom font size properly * Drawing errors in maximized mode * One-pixel overlap glitch on bottom corners of client edges * Borders not handling custom border sizes correctly * Unnecessarily small top resize area (unlike in the main window, there's no competition here between resizing and window dragging in the same small strip) * Wrong icon sizing (only a problem in theory, no one uses this code ATM) These files are now very much like simplified versions of the opaque_non_client_view.cc code (which was the goal); eventually all these should be refactorable. BUG=5054 Review URL: http://codereview.chromium.org/19484 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8947 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/views/constrained_window_impl.cc113
-rw-r--r--chrome/views/custom_frame_window.cc260
2 files changed, 266 insertions, 107 deletions
diff --git a/chrome/browser/views/constrained_window_impl.cc b/chrome/browser/views/constrained_window_impl.cc
index e42a72a..dac5356 100644
--- a/chrome/browser/views/constrained_window_impl.cc
+++ b/chrome/browser/views/constrained_window_impl.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/browser/tab_contents/web_contents_view.h"
#include "chrome/browser/toolbar_model.h"
+#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/web_app.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/chrome_constants.h"
@@ -216,10 +217,23 @@ class ConstrainedWindowNonClientView
virtual void ButtonPressed(views::BaseButton* sender);
private:
+ // Returns the thickness of the border that makes up the window frame edges.
+ // This does not include any client edge.
+ int FrameBorderThickness() const;
+
+ // Returns the thickness of the entire nonclient left, right, and bottom
+ // borders, including both the window frame and any client edge.
+ int NonClientBorderThickness() const;
+
// Returns the height of the entire nonclient top border, including the window
// frame, any title area, and any connected client edge.
int NonClientTopBorderHeight() const;
+ // Calculates multiple values related to title layout. Returns the height of
+ // the entire titlebar including any connected client edge.
+ int TitleCoordinates(int* title_top_spacing,
+ int* title_thickness) const;
+
// Paints different parts of the window to the incoming canvas.
void PaintFrameBorder(ChromeCanvas* canvas);
void PaintTitleBar(ChromeCanvas* canvas);
@@ -252,20 +266,31 @@ class ConstrainedWindowNonClientView
};
ChromeFont ConstrainedWindowNonClientView::title_font_;
-static const int kWindowLeftSpacing = 5;
-static const int kWindowControlsTopOffset = 1;
-static const int kWindowControlsRightOffset = 4;
-static const int kTitleTopOffset = 6;
-static const int kTitleBottomSpacing = 5;
-static const int kNoTitleTopSpacing = 8;
-static const int kResizeAreaSize = 5;
-static const int kResizeAreaNorthSize = 3;
-static const int kResizeAreaCornerSize = 16;
-static const int kWindowHorizontalBorderSize = 5;
-static const int kWindowVerticalBorderSize = 5;
-static const int kWindowIconSize = 16;
namespace {
+// The frame border is only visible in restored mode and is hardcoded to 4 px on
+// each side regardless of the system window border size.
+const int kFrameBorderThickness = 4;
+// Various edges of the frame border have a 1 px shadow along their edges; in a
+// few cases we shift elements based on this amount for visual appeal.
+const int kFrameShadowThickness = 1;
+// In the window corners, the resize areas don't actually expand bigger, but the
+// 16 px at the end of each edge triggers diagonal resizing.
+const int kResizeAreaCornerSize = 16;
+// The titlebar never shrinks to less than 20 px tall, including the height of
+// the frame border and client edge.
+const int kTitlebarMinimumHeight = 20;
+// The icon is inset 2 px from the left frame border.
+const int kIconLeftSpacing = 2;
+// The title text starts 2 px below the bottom of the top frame border.
+const int kTitleTopSpacing = 2;
+// There is a 5 px gap between the title text and the caption buttons.
+const int kTitleCaptionSpacing = 5;
+// The caption buttons are always drawn 1 px down from the visible top of the
+// window (the true top in restored mode, or the top of the screen in maximized
+// mode).
+const int kCaptionTopSpacing = 1;
+
const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0);
const SkColor kContentsBorderColor = SkColorSetRGB(219, 235, 255);
}
@@ -315,16 +340,18 @@ gfx::Rect ConstrainedWindowNonClientView::CalculateClientAreaBounds(
int width,
int height) const {
int top_height = NonClientTopBorderHeight();
- return gfx::Rect(kWindowHorizontalBorderSize, top_height,
- std::max(0, width - (2 * kWindowHorizontalBorderSize)),
- std::max(0, height - top_height - kWindowVerticalBorderSize));
+ int border_thickness = NonClientBorderThickness();
+ return gfx::Rect(border_thickness, top_height,
+ std::max(0, width - (2 * border_thickness)),
+ std::max(0, height - top_height - border_thickness));
}
gfx::Size ConstrainedWindowNonClientView::CalculateWindowSizeForClientSize(
int width,
int height) const {
- return gfx::Size(width + (2 * kWindowHorizontalBorderSize),
- height + NonClientTopBorderHeight() + kWindowVerticalBorderSize);
+ int border_thickness = NonClientBorderThickness();
+ return gfx::Size(width + (2 * border_thickness),
+ height + NonClientTopBorderHeight() + border_thickness);
}
CPoint ConstrainedWindowNonClientView::GetSystemMenuPoint() const {
@@ -344,8 +371,8 @@ int ConstrainedWindowNonClientView::NonClientHitTest(const gfx::Point& point) {
if (close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(point))
return HTCLOSE;
- int window_component = GetHTComponentForFrame(point, kResizeAreaNorthSize,
- kResizeAreaSize, kResizeAreaCornerSize,
+ int window_component = GetHTComponentForFrame(point, FrameBorderThickness(),
+ NonClientBorderThickness(), kResizeAreaCornerSize,
container_->window_delegate()->CanResize());
// Fall back to the caption if no other component matches.
return ((window_component == HTNOWHERE) && bounds().Contains(point)) ?
@@ -396,8 +423,9 @@ void ConstrainedWindowNonClientView::Layout() {
gfx::Size ConstrainedWindowNonClientView::GetPreferredSize() {
gfx::Size prefsize(container_->client_view()->GetPreferredSize());
- prefsize.Enlarge(2 * kWindowHorizontalBorderSize,
- NonClientTopBorderHeight() + kWindowVerticalBorderSize);
+ int border_thickness = NonClientBorderThickness();
+ prefsize.Enlarge(2 * border_thickness,
+ NonClientTopBorderHeight() + border_thickness);
return prefsize;
}
@@ -422,8 +450,31 @@ void ConstrainedWindowNonClientView::ButtonPressed(views::BaseButton* sender) {
////////////////////////////////////////////////////////////////////////////////
// ConstrainedWindowNonClientView, private:
+int ConstrainedWindowNonClientView::FrameBorderThickness() const {
+ return kFrameBorderThickness;
+}
+
+int ConstrainedWindowNonClientView::NonClientBorderThickness() const {
+ return FrameBorderThickness() + kClientEdgeThickness;
+}
+
int ConstrainedWindowNonClientView::NonClientTopBorderHeight() const {
- return kTitleTopOffset + title_font_.height() + kTitleBottomSpacing;
+ int title_top_spacing, title_thickness;
+ return TitleCoordinates(&title_top_spacing, &title_thickness);
+}
+
+int ConstrainedWindowNonClientView::TitleCoordinates(
+ int* title_top_spacing,
+ int* title_thickness) const {
+ int frame_thickness = FrameBorderThickness();
+ int min_titlebar_height = kTitlebarMinimumHeight + frame_thickness;
+ *title_top_spacing = frame_thickness + kTitleTopSpacing;
+ // The bottom spacing should be the same apparent height as the top spacing,
+ // plus have the client edge tacked on.
+ int title_bottom_spacing = *title_top_spacing + kClientEdgeThickness;
+ *title_thickness = std::max(title_font_.height(),
+ min_titlebar_height - *title_top_spacing - title_bottom_spacing);
+ return *title_top_spacing + *title_thickness + title_bottom_spacing;
}
void ConstrainedWindowNonClientView::PaintFrameBorder(ChromeCanvas* canvas) {
@@ -480,7 +531,7 @@ void ConstrainedWindowNonClientView::PaintClientEdge(ChromeCanvas* canvas) {
gfx::Rect client_edge_bounds(CalculateClientAreaBounds(width(), height()));
client_edge_bounds.Inset(-kClientEdgeThickness, -kClientEdgeThickness);
gfx::Rect frame_shadow_bounds(client_edge_bounds);
- frame_shadow_bounds.Inset(-1, -1);
+ frame_shadow_bounds.Inset(-kFrameShadowThickness, -kFrameShadowThickness);
canvas->FillRectInt(kContentsBorderShadow, frame_shadow_bounds.x(),
frame_shadow_bounds.y(), frame_shadow_bounds.width(),
@@ -494,18 +545,20 @@ void ConstrainedWindowNonClientView::PaintClientEdge(ChromeCanvas* canvas) {
void ConstrainedWindowNonClientView::LayoutWindowControls() {
gfx::Size close_button_size = close_button_->GetPreferredSize();
close_button_->SetBounds(
- width() - close_button_size.width() - kWindowControlsRightOffset,
- kWindowControlsTopOffset, close_button_size.width(),
+ width() - close_button_size.width() - FrameBorderThickness(),
+ kCaptionTopSpacing, close_button_size.width(),
close_button_size.height());
}
void ConstrainedWindowNonClientView::LayoutTitleBar() {
// Size the title.
- int title_x = kWindowLeftSpacing;
- int title_top_spacing = NonClientTopBorderHeight();
- title_bounds_.SetRect(title_x, kTitleTopOffset,
- close_button_->x() - kWindowLeftSpacing - title_x,
- title_font_.height());
+ int title_x = FrameBorderThickness() + kIconLeftSpacing;
+ int title_top_spacing, title_thickness;
+ TitleCoordinates(&title_top_spacing, &title_thickness);
+ title_bounds_.SetRect(title_x,
+ title_top_spacing + ((title_thickness - title_font_.height()) / 2),
+ std::max(0, close_button_->x() - kTitleCaptionSpacing - title_x),
+ title_font_.height());
}
void ConstrainedWindowNonClientView::LayoutClientView() {
diff --git a/chrome/views/custom_frame_window.cc b/chrome/views/custom_frame_window.cc
index 76735fd..a97b921 100644
--- a/chrome/views/custom_frame_window.cc
+++ b/chrome/views/custom_frame_window.cc
@@ -216,7 +216,6 @@ class InactiveWindowResources : public WindowResources {
SkBitmap* ActiveWindowResources::standard_frame_bitmaps_[];
SkBitmap* InactiveWindowResources::standard_frame_bitmaps_[];
-
///////////////////////////////////////////////////////////////////////////////
//
// DefaultNonClientView
@@ -251,18 +250,32 @@ class DefaultNonClientView : public NonClientView,
virtual void ButtonPressed(BaseButton* sender);
private:
- // Updates the system menu icon button.
- void SetWindowIcon(SkBitmap window_icon);
+ // Returns the thickness of the border that makes up the window frame edges.
+ // This does not include any client edge.
+ int FrameBorderThickness() const;
+
+ // Returns the thickness of the entire nonclient left, right, and bottom
+ // borders, including both the window frame and any client edge.
+ int NonClientBorderThickness() const;
// Returns the height of the entire nonclient top border, including the window
// frame, any title area, and any connected client edge.
int NonClientTopBorderHeight() const;
+ // A bottom border, and, in restored mode, a client edge are drawn at the
+ // bottom of the titlebar. This returns the total height drawn.
+ int BottomEdgeThicknessWithinNonClientHeight() const;
+
+ // Calculates multiple values related to title layout. Returns the height of
+ // the entire titlebar including any connected client edge.
+ int TitleCoordinates(int* title_top_spacing,
+ int* title_thickness) const;
+
// Paint various sub-components of this view.
void PaintRestoredFrameBorder(ChromeCanvas* canvas);
void PaintMaximizedFrameBorder(ChromeCanvas* canvas);
void PaintTitleBar(ChromeCanvas* canvas);
- void PaintClientEdge(ChromeCanvas* canvas);
+ void PaintRestoredClientEdge(ChromeCanvas* canvas);
// Layout various sub-components of this view.
void LayoutWindowControls();
@@ -307,22 +320,50 @@ class DefaultNonClientView : public NonClientView,
WindowResources* DefaultNonClientView::active_resources_ = NULL;
WindowResources* DefaultNonClientView::inactive_resources_ = NULL;
ChromeFont DefaultNonClientView::title_font_;
-static const int kWindowControlsTopOffset = 1;
-static const int kWindowControlsRightOffset = 5;
-static const int kWindowControlsTopZoomedOffset = 1;
-static const int kWindowControlsRightZoomedOffset = 5;
-static const int kWindowTopMarginZoomed = 1;
-static const int kWindowIconLeftOffset = 5;
-static const int kWindowIconTopOffset = 5;
-static const int kTitleTopOffset = 6;
-static const int kWindowIconTitleSpacing = 3;
-static const int kTitleBottomSpacing = 6;
-static const int kNoTitleTopSpacing = 8;
-static const int kResizeAreaSize = 5;
-static const int kResizeAreaNorthSize = 3;
-static const int kResizeAreaCornerSize = 16;
-static const int kWindowHorizontalBorderSize = 4;
-static const int kWindowVerticalBorderSize = 4;
+
+namespace {
+// The frame border is only visible in restored mode and is hardcoded to 4 px on
+// each side regardless of the system window border size.
+const int kFrameBorderThickness = 4;
+// Various edges of the frame border have a 1 px shadow along their edges; in a
+// few cases we shift elements based on this amount for visual appeal.
+const int kFrameShadowThickness = 1;
+// While resize areas on Windows are normally the same size as the window
+// borders, our top area is shrunk by 1 px to make it easier to move the window
+// around with our thinner top grabbable strip. (Incidentally, our side and
+// bottom resize areas don't match the frame border thickness either -- they
+// span the whole nonclient area, so there's no "dead zone" for the mouse.)
+const int kTopResizeAdjust = 1;
+// In the window corners, the resize areas don't actually expand bigger, but the
+// 16 px at the end of each edge triggers diagonal resizing.
+const int kResizeAreaCornerSize = 16;
+// The titlebar never shrinks to less than 18 px tall, plus the height of the
+// frame border and any bottom edge.
+const int kTitlebarMinimumHeight = 18;
+// The icon is inset 2 px from the left frame border.
+const int kIconLeftSpacing = 2;
+// The icon takes up 16/25th of the available titlebar height. (This is
+// expressed as two ints to avoid precision losses leading to off-by-one pixel
+// errors.)
+const int kIconHeightFractionNumerator = 16;
+const int kIconHeightFractionDenominator = 25;
+// The icon never shrinks below 16 px on a side.
+const int kIconMinimumSize = 16;
+// Because our frame border has a different "3D look" than Windows', with a less
+// cluttered top edge, we need to shift the icon up by 1 px in restored mode so
+// it looks more centered.
+const int kIconRestoredAdjust = 1;
+// There is a 4 px gap between the icon and the title text.
+const int kIconTitleSpacing = 4;
+// The title text starts 2 px below the bottom of the top frame border.
+const int kTitleTopSpacing = 2;
+// There is a 5 px gap between the title text and the caption buttons.
+const int kTitleCaptionSpacing = 5;
+// The caption buttons are always drawn 1 px down from the visible top of the
+// window (the true top in restored mode, or the top of the screen in maximized
+// mode).
+const int kCaptionTopSpacing = 1;
+}
///////////////////////////////////////////////////////////////////////////////
// DefaultNonClientView, public:
@@ -386,17 +427,18 @@ DefaultNonClientView::~DefaultNonClientView() {
gfx::Rect DefaultNonClientView::CalculateClientAreaBounds(int width,
int height) const {
int top_height = NonClientTopBorderHeight();
- int border_thickness = kWindowHorizontalBorderSize;
+ int border_thickness = NonClientBorderThickness();
return gfx::Rect(border_thickness, top_height,
- std::max(0, width - (2 * border_thickness)),
- std::max(0, height - top_height - kWindowVerticalBorderSize));
+ std::max(0, width - (2 * border_thickness)),
+ std::max(0, height - top_height - border_thickness));
}
gfx::Size DefaultNonClientView::CalculateWindowSizeForClientSize(
int width,
int height) const {
- return gfx::Size(width + (2 * kWindowHorizontalBorderSize),
- height + NonClientTopBorderHeight() + kWindowVerticalBorderSize);
+ int border_thickness = NonClientBorderThickness();
+ return gfx::Size(width + (2 * border_thickness),
+ height + NonClientTopBorderHeight() + border_thickness);
}
CPoint DefaultNonClientView::GetSystemMenuPoint() const {
@@ -431,8 +473,8 @@ int DefaultNonClientView::NonClientHitTest(const gfx::Point& point) {
point))
return HTSYSMENU;
- int window_component = GetHTComponentForFrame(point, kResizeAreaNorthSize,
- kResizeAreaSize, kResizeAreaCornerSize,
+ int window_component = GetHTComponentForFrame(point, FrameBorderThickness(),
+ NonClientBorderThickness(), kResizeAreaCornerSize,
container_->window_delegate()->CanResize());
// Fall back to the caption if no other component matches.
return ((window_component == HTNOWHERE) && bounds().Contains(point)) ?
@@ -482,7 +524,8 @@ void DefaultNonClientView::Paint(ChromeCanvas* canvas) {
else
PaintRestoredFrameBorder(canvas);
PaintTitleBar(canvas);
- PaintClientEdge(canvas);
+ if (!container_->IsMaximized())
+ PaintRestoredClientEdge(canvas);
}
void DefaultNonClientView::Layout() {
@@ -493,8 +536,9 @@ void DefaultNonClientView::Layout() {
gfx::Size DefaultNonClientView::GetPreferredSize() {
gfx::Size prefsize(container_->client_view()->GetPreferredSize());
- prefsize.Enlarge(2 * kWindowHorizontalBorderSize,
- NonClientTopBorderHeight() + kWindowVerticalBorderSize);
+ int border_thickness = NonClientBorderThickness();
+ prefsize.Enlarge(2 * border_thickness,
+ NonClientTopBorderHeight() + border_thickness);
return prefsize;
}
@@ -524,8 +568,50 @@ void DefaultNonClientView::ButtonPressed(BaseButton* sender) {
///////////////////////////////////////////////////////////////////////////////
// DefaultNonClientView, private:
+int DefaultNonClientView::FrameBorderThickness() const {
+ return container_->IsMaximized() ?
+ GetSystemMetrics(SM_CXSIZEFRAME) : kFrameBorderThickness;
+}
+
+int DefaultNonClientView::NonClientBorderThickness() const {
+ // In maximized mode, we don't show a client edge.
+ return FrameBorderThickness() +
+ (container_->IsMaximized() ? 0 : kClientEdgeThickness);
+}
+
int DefaultNonClientView::NonClientTopBorderHeight() const {
- return kTitleTopOffset + title_font_.height() + kTitleBottomSpacing;
+ int title_top_spacing, title_thickness;
+ return TitleCoordinates(&title_top_spacing, &title_thickness);
+}
+
+int DefaultNonClientView::BottomEdgeThicknessWithinNonClientHeight() const {
+ return kFrameShadowThickness +
+ (container_->IsMaximized() ? 0 : kClientEdgeThickness);
+}
+
+int DefaultNonClientView::TitleCoordinates(int* title_top_spacing,
+ int* title_thickness) const {
+ int frame_thickness = FrameBorderThickness();
+ int min_titlebar_height = kTitlebarMinimumHeight + frame_thickness;
+ *title_top_spacing = frame_thickness + kTitleTopSpacing;
+ // The bottom spacing should be the same apparent height as the top spacing.
+ // Because the actual top spacing height varies based on the system border
+ // thickness, we calculate this based on the restored top spacing and then
+ // adjust for maximized mode. We also don't include the frame shadow here,
+ // since while it's part of the bottom spacing it will be added in at the end.
+ int title_bottom_spacing =
+ kFrameBorderThickness + kTitleTopSpacing - kFrameShadowThickness;
+ if (container_->IsMaximized()) {
+ // When we maximize, the top border appears to be chopped off; shift the
+ // title down to stay centered within the remaining space.
+ int title_adjust = (kFrameBorderThickness / 2);
+ *title_top_spacing += title_adjust;
+ title_bottom_spacing -= title_adjust;
+ }
+ *title_thickness = std::max(title_font_.height(),
+ min_titlebar_height - *title_top_spacing - title_bottom_spacing);
+ return *title_top_spacing + *title_thickness + title_bottom_spacing +
+ BottomEdgeThicknessWithinNonClientHeight();
}
void DefaultNonClientView::PaintRestoredFrameBorder(ChromeCanvas* canvas) {
@@ -575,7 +661,15 @@ void DefaultNonClientView::PaintRestoredFrameBorder(ChromeCanvas* canvas) {
void DefaultNonClientView::PaintMaximizedFrameBorder(
ChromeCanvas* canvas) {
SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE);
- canvas->TileImageInt(*top_edge, 0, 0, width(), top_edge->height());
+ canvas->TileImageInt(*top_edge, 0, FrameBorderThickness(), width(),
+ top_edge->height());
+
+ // The bottom of the titlebar actually comes from the top of the Client Edge
+ // graphic, with the actual client edge clipped off the bottom.
+ SkBitmap* titlebar_bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP);
+ int edge_height = titlebar_bottom->height() - kClientEdgeThickness;
+ canvas->TileImageInt(*titlebar_bottom, 0,
+ container_->client_view()->y() - edge_height, width(), edge_height);
}
void DefaultNonClientView::PaintTitleBar(ChromeCanvas* canvas) {
@@ -585,7 +679,7 @@ void DefaultNonClientView::PaintTitleBar(ChromeCanvas* canvas) {
title_bounds_.width(), title_bounds_.height());
}
-void DefaultNonClientView::PaintClientEdge(ChromeCanvas* canvas) {
+void DefaultNonClientView::PaintRestoredClientEdge(ChromeCanvas* canvas) {
gfx::Rect client_area_bounds = container_->client_view()->bounds();
int client_area_top = client_area_bounds.y();
@@ -613,22 +707,23 @@ void DefaultNonClientView::PaintClientEdge(ChromeCanvas* canvas) {
canvas->DrawBitmapInt(*top_right, client_area_bounds.right(), top_edge_y);
// Right.
+ int client_area_bottom =
+ std::max(client_area_top, client_area_bounds.bottom());
+ int client_area_height = client_area_bottom - client_area_top;
canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top,
- right->width(), client_area_bounds.height());
+ right->width(), client_area_height);
// Bottom.
canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(),
- client_area_bounds.bottom());
- canvas->TileImageInt(*bottom, client_area_bounds.x(),
- client_area_bounds.bottom(),
+ client_area_bottom);
+ canvas->TileImageInt(*bottom, client_area_bounds.x(), client_area_bottom,
client_area_bounds.width(), bottom_right->height());
canvas->DrawBitmapInt(*bottom_left,
- client_area_bounds.x() - bottom_left->width(),
- client_area_bounds.bottom());
+ client_area_bounds.x() - bottom_left->width(), client_area_bottom);
// Left.
canvas->TileImageInt(*left, client_area_bounds.x() - left->width(),
- client_area_top, left->width(), client_area_bounds.height());
+ client_area_top, left->width(), client_area_height);
}
void DefaultNonClientView::LayoutWindowControls() {
@@ -636,14 +731,16 @@ void DefaultNonClientView::LayoutWindowControls() {
// Maximized buttons start at window top so that even if their images aren't
// drawn flush with the screen edge, they still obey Fitts' Law.
bool is_maximized = container_->IsMaximized();
- int caption_y = is_maximized ? 0 : kWindowControlsTopOffset;
- int top_extra_height = is_maximized ? kWindowControlsTopZoomedOffset : 0;
+ int frame_thickness = FrameBorderThickness();
+ int caption_y = is_maximized ? frame_thickness : kCaptionTopSpacing;
+ int top_extra_height = is_maximized ? kCaptionTopSpacing : 0;
// There should always be the same number of non-shadow pixels visible to the
// side of the caption buttons. In maximized mode we extend the rightmost
// button to the screen corner to obey Fitts' Law.
- int right_extra_width = is_maximized ? kWindowControlsRightZoomedOffset : 0;
+ int right_extra_width = is_maximized ?
+ (kFrameBorderThickness - kFrameShadowThickness) : 0;
int right_spacing = is_maximized ?
- kWindowControlsRightZoomedOffset : kWindowControlsRightOffset;
+ (GetSystemMetrics(SM_CXSIZEFRAME) + right_extra_width) : frame_thickness;
gfx::Size close_button_size = close_button_->GetPreferredSize();
close_button_->SetBounds(width() - close_button_size.width() - right_spacing,
caption_y,
@@ -698,41 +795,48 @@ void DefaultNonClientView::LayoutWindowControls() {
}
void DefaultNonClientView::LayoutTitleBar() {
- int top_offset = container_->IsMaximized() ? kWindowTopMarginZoomed : 0;
- WindowDelegate* d = container_->window_delegate();
-
- // Size the window icon, if visible.
- if (d->ShouldShowWindowIcon()) {
- system_menu_button_->SetVisible(true);
- gfx::Size ps = system_menu_button_->GetPreferredSize();
- system_menu_button_->SetBounds(
- kWindowIconLeftOffset, kWindowIconTopOffset + top_offset, ps.width(),
- ps.height());
- } else {
- // Put the menu in the right place at least even if it is hidden so we
- // can size the title based on its position.
- system_menu_button_->SetBounds(kWindowIconLeftOffset,
- kWindowIconTopOffset, 0, 0);
- }
+ // Always lay out the icon, even when it's not present, so we can lay out the
+ // window title based on its position.
+ int frame_thickness = FrameBorderThickness();
+ int icon_x = frame_thickness + kIconLeftSpacing;
+
+ // The usable height of the titlebar area is the total height minus the top
+ // resize border and any edge area we draw at its bottom.
+ int title_top_spacing, title_thickness;
+ int top_height = TitleCoordinates(&title_top_spacing, &title_thickness);
+ int available_height = top_height - frame_thickness -
+ BottomEdgeThicknessWithinNonClientHeight();
+
+ // The icon takes up a constant fraction of the available height, down to a
+ // minimum size, and is always an even number of pixels on a side (presumably
+ // to make scaled icons look better). It's centered within the usable height.
+ int icon_size = std::max((available_height * kIconHeightFractionNumerator /
+ kIconHeightFractionDenominator) / 2 * 2, kIconMinimumSize);
+ int icon_y = ((available_height - icon_size) / 2) + frame_thickness;
+
+ // Hack: Our frame border has a different "3D look" than Windows'. Theirs has
+ // a more complex gradient on the top that they push their icon/title below;
+ // then the maximized window cuts this off and the icon/title are centered in
+ // the remaining space. Because the apparent shape of our border is simpler,
+ // using the same positioning makes things look slightly uncentered with
+ // restored windows, so we come up to compensate.
+ if (!container_->IsMaximized())
+ icon_y -= kIconRestoredAdjust;
+
+ views::WindowDelegate* d = container_->window_delegate();
+ if (!d->ShouldShowWindowIcon())
+ icon_size = 0;
+ system_menu_button_->SetBounds(icon_x, icon_y, icon_size, icon_size);
// Size the title.
- gfx::Rect system_menu_bounds = system_menu_button_->bounds();
- int spacing = d->ShouldShowWindowIcon() ? kWindowIconTitleSpacing : 0;
- int title_right = should_show_minmax_buttons_ ?
- minimize_button_->x() : close_button_->x();
- int title_left = system_menu_bounds.right() + spacing;
- title_bounds_.SetRect(title_left, kTitleTopOffset + top_offset,
- std::max(0, static_cast<int>(title_right - system_menu_bounds.right())),
- title_font_.height());
-
- // Center the icon within the height of the title if the title is taller.
- int delta_y = title_bounds_.height() - system_menu_button_->height();
- if (delta_y > 0) {
- int new_y = title_bounds_.y() + static_cast<int>(delta_y / 2);
- system_menu_button_->SetBounds(system_menu_button_->x(), new_y,
- system_menu_button_->width(),
- system_menu_button_->height());
- }
+ int icon_right = icon_x + icon_size;
+ int title_x =
+ icon_right + (d->ShouldShowWindowIcon() ? kIconTitleSpacing : 0);
+ int title_right = (should_show_minmax_buttons_ ?
+ minimize_button_->x() : close_button_->x()) - kTitleCaptionSpacing;
+ title_bounds_.SetRect(title_x,
+ title_top_spacing + ((title_thickness - title_font_.height()) / 2),
+ std::max(0, title_right - title_x), title_font_.height());
}
void DefaultNonClientView::LayoutClientView() {
@@ -746,7 +850,9 @@ void DefaultNonClientView::InitClass() {
if (!initialized) {
active_resources_ = new ActiveWindowResources;
inactive_resources_ = new InactiveWindowResources;
+
title_font_ = win_util::GetWindowTitleFont();
+
initialized = true;
}
}