diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/views/constrained_window_impl.cc | 285 | ||||
-rw-r--r-- | chrome/views/custom_frame_window.cc | 281 |
2 files changed, 237 insertions, 329 deletions
diff --git a/chrome/browser/views/constrained_window_impl.cc b/chrome/browser/views/constrained_window_impl.cc index 1bc3157..e42a72a 100644 --- a/chrome/browser/views/constrained_window_impl.cc +++ b/chrome/browser/views/constrained_window_impl.cc @@ -46,40 +46,48 @@ class ClientView; enum { FRAME_PART_BITMAP_FIRST = 0, // Must be first. - FRAME_BOTTOM_CENTER, + // Window Controls. + FRAME_CLOSE_BUTTON_ICON, + FRAME_CLOSE_BUTTON_ICON_H, + FRAME_CLOSE_BUTTON_ICON_P, + + // Window Frame Border. + FRAME_BOTTOM_EDGE, FRAME_BOTTOM_LEFT_CORNER, FRAME_BOTTOM_RIGHT_CORNER, - FRAME_LEFT_SIDE, - FRAME_RIGHT_SIDE, - FRAME_TOP_CENTER, + FRAME_LEFT_EDGE, + FRAME_RIGHT_EDGE, + FRAME_TOP_EDGE, FRAME_TOP_LEFT_CORNER, FRAME_TOP_RIGHT_CORNER, - FRAME_CLOSE_BUTTON_ICON, - FRAME_CLOSE_BUTTON_ICON_H, - FRAME_CLOSE_BUTTON_ICON_P, - FRAME_PART_BITMAP_COUNT // Must be last. }; static const int kXPFramePartIDs[] = { - 0, IDR_CONSTRAINED_BOTTOM_CENTER, IDR_CONSTRAINED_BOTTOM_LEFT_CORNER, + 0, + IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, + IDR_CONSTRAINED_BOTTOM_CENTER, IDR_CONSTRAINED_BOTTOM_LEFT_CORNER, IDR_CONSTRAINED_BOTTOM_RIGHT_CORNER, IDR_CONSTRAINED_LEFT_SIDE, IDR_CONSTRAINED_RIGHT_SIDE, IDR_CONSTRAINED_TOP_CENTER, IDR_CONSTRAINED_TOP_LEFT_CORNER, IDR_CONSTRAINED_TOP_RIGHT_CORNER, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, 0 }; + 0 }; static const int kVistaFramePartIDs[] = { - 0, IDR_CONSTRAINED_BOTTOM_CENTER_V, IDR_CONSTRAINED_BOTTOM_LEFT_CORNER_V, + 0, + IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, + IDR_CONSTRAINED_BOTTOM_CENTER_V, IDR_CONSTRAINED_BOTTOM_LEFT_CORNER_V, IDR_CONSTRAINED_BOTTOM_RIGHT_CORNER_V, IDR_CONSTRAINED_LEFT_SIDE_V, IDR_CONSTRAINED_RIGHT_SIDE_V, IDR_CONSTRAINED_TOP_CENTER_V, IDR_CONSTRAINED_TOP_LEFT_CORNER_V, IDR_CONSTRAINED_TOP_RIGHT_CORNER_V, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, 0 }; + 0 }; static const int kOTRFramePartIDs[] = { - 0, IDR_WINDOW_BOTTOM_CENTER_OTR, IDR_WINDOW_BOTTOM_LEFT_CORNER_OTR, + 0, + IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, + IDR_WINDOW_BOTTOM_CENTER_OTR, IDR_WINDOW_BOTTOM_LEFT_CORNER_OTR, IDR_WINDOW_BOTTOM_RIGHT_CORNER_OTR, IDR_WINDOW_LEFT_SIDE_OTR, IDR_WINDOW_RIGHT_SIDE_OTR, IDR_WINDOW_TOP_CENTER_OTR, IDR_WINDOW_TOP_LEFT_CORNER_OTR, IDR_WINDOW_TOP_RIGHT_CORNER_OTR, - IDR_CLOSE_SA, IDR_CLOSE_SA_H, IDR_CLOSE_SA_P, 0 }; + 0 }; class XPWindowResources : public views::WindowResources { public: @@ -186,19 +194,8 @@ class ConstrainedWindowNonClientView TabContents* owner); virtual ~ConstrainedWindowNonClientView(); - // Calculates the pixel height of the titlebar - int CalculateTitlebarHeight() const; - - // Calculates the pixel height of all pieces of a window that are - // not part of the webcontent display area. - gfx::Rect CalculateWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const; void UpdateWindowTitle(); - void set_window_delegate(views::WindowDelegate* window_delegate) { - window_delegate_ = window_delegate; - } - // Overridden from views::NonClientView: virtual gfx::Rect CalculateClientAreaBounds(int width, int height) const; virtual gfx::Size CalculateWindowSizeForClientSize(int width, @@ -207,7 +204,7 @@ class ConstrainedWindowNonClientView virtual int NonClientHitTest(const gfx::Point& point); virtual void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask); virtual void EnableClose(bool enable); - virtual void ResetWindowControls(); + virtual void ResetWindowControls() { } // Overridden from views::View: virtual void Paint(ChromeCanvas* canvas); @@ -218,27 +215,31 @@ class ConstrainedWindowNonClientView // Overridden from views::BaseButton::ButtonListener: virtual void ButtonPressed(views::BaseButton* sender); + private: + // Returns the height of the entire nonclient top border, including the window + // frame, any title area, and any connected client edge. + int NonClientTopBorderHeight() const; + // Paints different parts of the window to the incoming canvas. void PaintFrameBorder(ChromeCanvas* canvas); void PaintTitleBar(ChromeCanvas* canvas); - void PaintWindowTitle(ChromeCanvas* canvas); + void PaintClientEdge(ChromeCanvas* canvas); + + // Layout various sub-components of this view. + void LayoutWindowControls(); + void LayoutTitleBar(); + void LayoutClientView(); SkColor GetTitleColor() const { - if (container_->owner()->profile()->IsOffTheRecord() || - !win_util::ShouldUseVistaFrame()) { - return SK_ColorWHITE; - } - return SK_ColorBLACK; + return (container_->owner()->profile()->IsOffTheRecord() || + !win_util::ShouldUseVistaFrame()) ? SK_ColorWHITE : SK_ColorBLACK; } ConstrainedWindowImpl* container_; - views::WindowDelegate* window_delegate_; scoped_ptr<views::WindowResources> resources_; gfx::Rect title_bounds_; - gfx::Rect icon_bounds_; - gfx::Rect client_bounds_; views::Button* close_button_; @@ -264,8 +265,10 @@ static const int kWindowHorizontalBorderSize = 5; static const int kWindowVerticalBorderSize = 5; static const int kWindowIconSize = 16; -static const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); -static const SkColor kContentsBorderColor = SkColorSetRGB(219, 235, 255); +namespace { +const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); +const SkColor kContentsBorderColor = SkColorSetRGB(219, 235, 255); +} //////////////////////////////////////////////////////////////////////////////// // ConstrainedWindowNonClientView, public: @@ -274,7 +277,6 @@ ConstrainedWindowNonClientView::ConstrainedWindowNonClientView( ConstrainedWindowImpl* container, TabContents* owner) : NonClientView(), container_(container), - window_delegate_(NULL), close_button_(new views::Button) { InitClass(); if (owner->profile()->IsOffTheRecord()) { @@ -302,31 +304,6 @@ ConstrainedWindowNonClientView::ConstrainedWindowNonClientView( ConstrainedWindowNonClientView::~ConstrainedWindowNonClientView() { } -int ConstrainedWindowNonClientView::CalculateTitlebarHeight() const { - int height; - if (window_delegate_ && window_delegate_->ShouldShowWindowTitle()) { - height = kTitleTopOffset + title_font_.height() + kTitleBottomSpacing; - } else { - height = kNoTitleTopSpacing; - } - - return height; -} - -gfx::Rect ConstrainedWindowNonClientView::CalculateWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const { - int non_client_height = CalculateTitlebarHeight(); - gfx::Rect window_bounds = client_bounds; - window_bounds.set_width( - window_bounds.width() + 2 * kWindowHorizontalBorderSize); - window_bounds.set_height( - window_bounds.height() + non_client_height + kWindowVerticalBorderSize); - window_bounds.set_x( - std::max(0, window_bounds.x() - kWindowHorizontalBorderSize)); - window_bounds.set_y(std::max(0, window_bounds.y() - non_client_height)); - return window_bounds; -} - void ConstrainedWindowNonClientView::UpdateWindowTitle() { SchedulePaint(title_bounds_, false); } @@ -337,52 +314,42 @@ void ConstrainedWindowNonClientView::UpdateWindowTitle() { gfx::Rect ConstrainedWindowNonClientView::CalculateClientAreaBounds( int width, int height) const { - int non_client_height = CalculateTitlebarHeight(); - return gfx::Rect(kWindowHorizontalBorderSize, non_client_height, + int top_height = NonClientTopBorderHeight(); + return gfx::Rect(kWindowHorizontalBorderSize, top_height, std::max(0, width - (2 * kWindowHorizontalBorderSize)), - std::max(0, height - non_client_height - kWindowVerticalBorderSize)); + std::max(0, height - top_height - kWindowVerticalBorderSize)); } gfx::Size ConstrainedWindowNonClientView::CalculateWindowSizeForClientSize( int width, int height) const { - // This is only used for truly constrained windows, which does not include - // popups generated from a user gesture since those are detached immediately. - gfx::Rect window_bounds = - CalculateWindowBoundsForClientBounds(gfx::Rect(0, 0, width, height)); - return window_bounds.size(); + return gfx::Size(width + (2 * kWindowHorizontalBorderSize), + height + NonClientTopBorderHeight() + kWindowVerticalBorderSize); } CPoint ConstrainedWindowNonClientView::GetSystemMenuPoint() const { - CPoint system_menu_point(icon_bounds_.x(), icon_bounds_.bottom()); - MapWindowPoints(container_->GetHWND(), HWND_DESKTOP, &system_menu_point, 1); - return system_menu_point; + // Doesn't matter what we return, since this is only used when the user clicks + // a window icon, and we never have an icon. + return CPoint(); } int ConstrainedWindowNonClientView::NonClientHitTest(const gfx::Point& point) { // First see if it's within the grow box area, since that overlaps the client // bounds. - int component = container_->client_view()->NonClientHitTest(point); - if (component != HTNOWHERE) - return component; + int frame_component = container_->client_view()->NonClientHitTest(point); + if (frame_component != HTNOWHERE) + return frame_component; // Then see if the point is within any of the window controls. - gfx::Rect button_bounds = - close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION); - if (button_bounds.Contains(point)) + if (close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(point)) return HTCLOSE; - if (icon_bounds_.Contains(point)) - return HTSYSMENU; - - component = GetHTComponentForFrame(point, kResizeAreaNorthSize, - kResizeAreaSize, kResizeAreaCornerSize, window_delegate_->CanResize()); - if (component == HTNOWHERE) { - // Finally fall back to the caption. - if (bounds().Contains(point)) - component = HTCAPTION; - // Otherwise, the point is outside the window's bounds. - } - return component; + + int window_component = GetHTComponentForFrame(point, kResizeAreaNorthSize, + kResizeAreaSize, kResizeAreaCornerSize, + container_->window_delegate()->CanResize()); + // Fall back to the caption if no other component matches. + return ((window_component == HTNOWHERE) && bounds().Contains(point)) ? + HTCAPTION : window_component; } void ConstrainedWindowNonClientView::GetWindowMask(const gfx::Size& size, @@ -412,63 +379,35 @@ void ConstrainedWindowNonClientView::EnableClose(bool enable) { close_button_->SetEnabled(enable); } -void ConstrainedWindowNonClientView::ResetWindowControls() { - // We have no window controls to reset. -} - //////////////////////////////////////////////////////////////////////////////// // ConstrainedWindowNonClientView, views::View implementation: void ConstrainedWindowNonClientView::Paint(ChromeCanvas* canvas) { PaintFrameBorder(canvas); PaintTitleBar(canvas); + PaintClientEdge(canvas); } void ConstrainedWindowNonClientView::Layout() { - gfx::Size ps; - - ps = close_button_->GetPreferredSize(); - close_button_->SetBounds(width() - ps.width() - kWindowControlsRightOffset, - kWindowControlsTopOffset, ps.width(), ps.height()); - - int titlebar_height = CalculateTitlebarHeight(); - if (window_delegate_) { - if (window_delegate_->ShouldShowWindowTitle()) { - int spacing = kWindowLeftSpacing; - int title_right = close_button_->x() - spacing; - int title_left = icon_bounds_.right() + spacing; - title_bounds_.SetRect(title_left, kTitleTopOffset, - title_right - title_left, title_font_.height()); - - // Center the icon within the vertical bounds of the title if the title - // is taller. - int delta_y = title_bounds_.height() - icon_bounds_.height(); - if (delta_y > 0) - icon_bounds_.set_y(title_bounds_.y() + static_cast<int>(delta_y / 2)); - } - } - - client_bounds_ = CalculateClientAreaBounds(width(), height()); - container_->client_view()->SetBounds(client_bounds_); + LayoutWindowControls(); + LayoutTitleBar(); + LayoutClientView(); } gfx::Size ConstrainedWindowNonClientView::GetPreferredSize() { - gfx::Size prefsize = container_->client_view()->GetPreferredSize(); + gfx::Size prefsize(container_->client_view()->GetPreferredSize()); prefsize.Enlarge(2 * kWindowHorizontalBorderSize, - CalculateTitlebarHeight() + - kWindowVerticalBorderSize); + NonClientTopBorderHeight() + kWindowVerticalBorderSize); return prefsize; } void ConstrainedWindowNonClientView::ViewHierarchyChanged(bool is_add, View *parent, View *child) { - if (is_add && GetWidget()) { - // Add our Client View as we are added to the Container so that if we are - // subsequently resized all the parent-child relationships are established. - if (is_add && GetWidget() && child == this) - AddChildView(container_->client_view()); - } + // Add our Client View as we are added to the Container so that if we are + // subsequently resized all the parent-child relationships are established. + if (is_add && GetWidget() && child == this) + AddChildView(container_->client_view()); } //////////////////////////////////////////////////////////////////////////////// @@ -483,31 +422,34 @@ void ConstrainedWindowNonClientView::ButtonPressed(views::BaseButton* sender) { //////////////////////////////////////////////////////////////////////////////// // ConstrainedWindowNonClientView, private: +int ConstrainedWindowNonClientView::NonClientTopBorderHeight() const { + return kTitleTopOffset + title_font_.height() + kTitleBottomSpacing; +} + void ConstrainedWindowNonClientView::PaintFrameBorder(ChromeCanvas* canvas) { SkBitmap* top_left_corner = resources_->GetPartBitmap(FRAME_TOP_LEFT_CORNER); SkBitmap* top_right_corner = resources_->GetPartBitmap(FRAME_TOP_RIGHT_CORNER); - SkBitmap* top_edge = resources_->GetPartBitmap(FRAME_TOP_CENTER); - SkBitmap* right_edge = resources_->GetPartBitmap(FRAME_RIGHT_SIDE); - SkBitmap* left_edge = resources_->GetPartBitmap(FRAME_LEFT_SIDE); + SkBitmap* top_edge = resources_->GetPartBitmap(FRAME_TOP_EDGE); + SkBitmap* right_edge = resources_->GetPartBitmap(FRAME_RIGHT_EDGE); + SkBitmap* left_edge = resources_->GetPartBitmap(FRAME_LEFT_EDGE); SkBitmap* bottom_left_corner = resources_->GetPartBitmap(FRAME_BOTTOM_LEFT_CORNER); SkBitmap* bottom_right_corner = resources_->GetPartBitmap(FRAME_BOTTOM_RIGHT_CORNER); - SkBitmap* bottom_edge = resources_->GetPartBitmap(FRAME_BOTTOM_CENTER); + SkBitmap* bottom_edge = resources_->GetPartBitmap(FRAME_BOTTOM_EDGE); // Top. canvas->DrawBitmapInt(*top_left_corner, 0, 0); canvas->TileImageInt(*top_edge, top_left_corner->width(), 0, width() - top_right_corner->width(), top_edge->height()); - canvas->DrawBitmapInt( - *top_right_corner, width() - top_right_corner->width(), 0); + canvas->DrawBitmapInt(*top_right_corner, + width() - top_right_corner->width(), 0); // Right. - int top_stack_height = top_right_corner->height(); canvas->TileImageInt(*right_edge, width() - right_edge->width(), - top_stack_height, right_edge->width(), - height() - top_stack_height - + top_right_corner->height(), right_edge->width(), + height() - top_right_corner->height() - bottom_right_corner->height()); // Bottom. @@ -523,38 +465,52 @@ void ConstrainedWindowNonClientView::PaintFrameBorder(ChromeCanvas* canvas) { height() - bottom_left_corner->height()); // Left. - top_stack_height = top_left_corner->height(); - canvas->TileImageInt(*left_edge, 0, top_stack_height, left_edge->width(), - height() - top_stack_height - - bottom_left_corner->height()); + canvas->TileImageInt(*left_edge, 0, top_left_corner->height(), + left_edge->width(), + height() - top_left_corner->height() - bottom_left_corner->height()); +} + +void ConstrainedWindowNonClientView::PaintTitleBar(ChromeCanvas* canvas) { + canvas->DrawStringInt(container_->GetWindowTitle(), title_font_, + GetTitleColor(), MirroredLeftPointForRect(title_bounds_), + title_bounds_.y(), title_bounds_.width(), title_bounds_.height()); +} - // Contents Border. - gfx::Rect border_bounds = client_bounds_; - border_bounds.Inset(-2, -2); - canvas->FillRectInt(kContentsBorderShadow, border_bounds.x(), - border_bounds.y(), border_bounds.width(), - border_bounds.height()); +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); - border_bounds.Inset(1, 1); - canvas->FillRectInt(kContentsBorderColor, border_bounds.x(), - border_bounds.y(), border_bounds.width(), - border_bounds.height()); + canvas->FillRectInt(kContentsBorderShadow, frame_shadow_bounds.x(), + frame_shadow_bounds.y(), frame_shadow_bounds.width(), + frame_shadow_bounds.height()); + + canvas->FillRectInt(kContentsBorderColor, client_edge_bounds.x(), + client_edge_bounds.y(), client_edge_bounds.width(), + client_edge_bounds.height()); } -void ConstrainedWindowNonClientView::PaintTitleBar(ChromeCanvas* canvas) { - if (!window_delegate_) - return; +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(), + close_button_size.height()); +} - if (window_delegate_->ShouldShowWindowTitle()) { - PaintWindowTitle(canvas); - } +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()); } -void ConstrainedWindowNonClientView::PaintWindowTitle(ChromeCanvas* canvas) { - int title_x = MirroredLeftPointForRect(title_bounds_); - canvas->DrawStringInt(container_->GetWindowTitle(), title_font_, - GetTitleColor(), title_x, title_bounds_.y(), - title_bounds_.width(), title_bounds_.height()); +void ConstrainedWindowNonClientView::LayoutClientView() { + container_->client_view()->SetBounds(CalculateClientAreaBounds(width(), + height())); } // static @@ -664,7 +620,6 @@ void ConstrainedWindowImpl::Init(TabContents* owner) { } void ConstrainedWindowImpl::InitAsDialog(const gfx::Rect& initial_bounds) { - non_client_view()->set_window_delegate(window_delegate()); CustomFrameWindow::Init(owner_->GetContainerHWND(), initial_bounds); ActivateConstrainedWindow(); } diff --git a/chrome/views/custom_frame_window.cc b/chrome/views/custom_frame_window.cc index 91dbdd2..76735fd 100644 --- a/chrome/views/custom_frame_window.cc +++ b/chrome/views/custom_frame_window.cc @@ -254,13 +254,14 @@ class DefaultNonClientView : public NonClientView, // Updates the system menu icon button. void SetWindowIcon(SkBitmap window_icon); - // Returns the height of the non-client area at the top of the window (the - // title bar, etc). - int CalculateContentsTop() 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; // Paint various sub-components of this view. - void PaintFrameBorder(ChromeCanvas* canvas); + void PaintRestoredFrameBorder(ChromeCanvas* canvas); void PaintMaximizedFrameBorder(ChromeCanvas* canvas); + void PaintTitleBar(ChromeCanvas* canvas); void PaintClientEdge(ChromeCanvas* canvas); // Layout various sub-components of this view. @@ -290,9 +291,6 @@ class DefaultNonClientView : public NonClientView, Button* system_menu_button_; // Uses the window icon if visible. bool should_show_minmax_buttons_; - // The window icon. - SkBitmap window_icon_; - // The window that owns this view. CustomFrameWindow* container_; @@ -387,75 +385,58 @@ DefaultNonClientView::~DefaultNonClientView() { gfx::Rect DefaultNonClientView::CalculateClientAreaBounds(int width, int height) const { - int top_margin = CalculateContentsTop(); - return gfx::Rect(kWindowHorizontalBorderSize, top_margin, - std::max(0, width - (2 * kWindowHorizontalBorderSize)), - std::max(0, height - top_margin - kWindowVerticalBorderSize)); + int top_height = NonClientTopBorderHeight(); + int border_thickness = kWindowHorizontalBorderSize; + return gfx::Rect(border_thickness, top_height, + std::max(0, width - (2 * border_thickness)), + std::max(0, height - top_height - kWindowVerticalBorderSize)); } gfx::Size DefaultNonClientView::CalculateWindowSizeForClientSize( int width, int height) const { return gfx::Size(width + (2 * kWindowHorizontalBorderSize), - height + CalculateContentsTop() + kWindowVerticalBorderSize); + height + NonClientTopBorderHeight() + kWindowVerticalBorderSize); } CPoint DefaultNonClientView::GetSystemMenuPoint() const { - CPoint system_menu_point( - system_menu_button_->x(), + // TODO(pkasting): This is wrong; Windows native runs the menu at the bottom + // of the titlebar, not the bottom of the window icon. + CPoint system_menu_point(system_menu_button_->x(), system_menu_button_->y() + system_menu_button_->height()); MapWindowPoints(container_->GetHWND(), HWND_DESKTOP, &system_menu_point, 1); return system_menu_point; } -// There is a subtle point that needs to be explained regarding the manner in -// which this function returns the HT* code Windows is expecting: -// -// |point| contains the cursor position in this View's coordinate system. If -// this View uses a right-to-left UI layout, the position represented by -// |point| will not reflect the UI mirroring because we don't create the -// container's HWND with WS_EX_LAYOUTRTL. Therefore, whenever the cursor -// position resides within the boundaries of one of our child Views (for -// example, the close_button_), we must retrieve the child View bounds such -// that bound are mirrored if the View uses right-to-left UI layout. This is -// why this function passes APPLY_MIRRORING_TRANSFORMATION as the |settings| -// whenever it calls GetBounds(). int DefaultNonClientView::NonClientHitTest(const gfx::Point& point) { // First see if it's within the grow box area, since that overlaps the client // bounds. - int component = container_->client_view()->NonClientHitTest(point); - if (component != HTNOWHERE) - return component; + int frame_component = container_->client_view()->NonClientHitTest(point); + if (frame_component != HTNOWHERE) + return frame_component; // Then see if the point is within any of the window controls. - gfx::Rect button_bounds = - close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION); - if (button_bounds.Contains(point)) + if (close_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains(point)) return HTCLOSE; - button_bounds = restore_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION); - if (button_bounds.Contains(point)) + if (restore_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( + point)) return HTMAXBUTTON; - button_bounds = maximize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION); - if (button_bounds.Contains(point)) + if (maximize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( + point)) return HTMAXBUTTON; - button_bounds = minimize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION); - if (button_bounds.Contains(point)) + if (minimize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( + point)) return HTMINBUTTON; - button_bounds = - system_menu_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION); - if (button_bounds.Contains(point)) + if (system_menu_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( + point)) return HTSYSMENU; - component = GetHTComponentForFrame(point, kResizeAreaNorthSize, + int window_component = GetHTComponentForFrame(point, kResizeAreaNorthSize, kResizeAreaSize, kResizeAreaCornerSize, container_->window_delegate()->CanResize()); - if (component == HTNOWHERE) { - // Finally fall back to the caption. - if (bounds().Contains(point)) - component = HTCAPTION; - // Otherwise, the point is outside the window's bounds. - } - return component; + // Fall back to the caption if no other component matches. + return ((window_component == HTNOWHERE) && bounds().Contains(point)) ? + HTCAPTION : window_component; } void DefaultNonClientView::GetWindowMask(const gfx::Size& size, @@ -496,32 +477,24 @@ void DefaultNonClientView::ResetWindowControls() { // DefaultNonClientView, View overrides: void DefaultNonClientView::Paint(ChromeCanvas* canvas) { - if (container_->IsMaximized()) { + if (container_->IsMaximized()) PaintMaximizedFrameBorder(canvas); - } else { - PaintFrameBorder(canvas); - } + else + PaintRestoredFrameBorder(canvas); + PaintTitleBar(canvas); PaintClientEdge(canvas); - - WindowDelegate* d = container_->window_delegate(); - if (d->ShouldShowWindowTitle()) { - canvas->DrawStringInt(d->GetWindowTitle(), title_font_, SK_ColorWHITE, - title_bounds_.x(), title_bounds_.y(), - title_bounds_.width(), title_bounds_.height()); - } } void DefaultNonClientView::Layout() { LayoutWindowControls(); LayoutTitleBar(); LayoutClientView(); - SchedulePaint(); } gfx::Size DefaultNonClientView::GetPreferredSize() { - gfx::Size prefsize = container_->client_view()->GetPreferredSize(); + gfx::Size prefsize(container_->client_view()->GetPreferredSize()); prefsize.Enlarge(2 * kWindowHorizontalBorderSize, - CalculateContentsTop() + kWindowVerticalBorderSize); + NonClientTopBorderHeight() + kWindowVerticalBorderSize); return prefsize; } @@ -538,36 +511,25 @@ void DefaultNonClientView::ViewHierarchyChanged(bool is_add, // DefaultNonClientView, BaseButton::ButtonListener implementation: void DefaultNonClientView::ButtonPressed(BaseButton* sender) { - if (sender == close_button_) { + if (sender == close_button_) container_->ExecuteSystemMenuCommand(SC_CLOSE); - } else if (sender == minimize_button_) { + else if (sender == minimize_button_) container_->ExecuteSystemMenuCommand(SC_MINIMIZE); - } else if (sender == maximize_button_) { + else if (sender == maximize_button_) container_->ExecuteSystemMenuCommand(SC_MAXIMIZE); - } else if (sender == restore_button_) { + else if (sender == restore_button_) container_->ExecuteSystemMenuCommand(SC_RESTORE); - } } /////////////////////////////////////////////////////////////////////////////// // DefaultNonClientView, private: -void DefaultNonClientView::SetWindowIcon(SkBitmap window_icon) { - // TODO(beng): (Cleanup) remove this persistent cache of the icon when Button - // takes a SkBitmap rather than SkBitmap*. - window_icon_ = window_icon; - system_menu_button_->SetImage(Button::BS_NORMAL, &window_icon); -} - -int DefaultNonClientView::CalculateContentsTop() const { - if (container_->window_delegate()->ShouldShowWindowTitle()) - return kTitleTopOffset + title_font_.height() + kTitleBottomSpacing; - return kNoTitleTopSpacing; +int DefaultNonClientView::NonClientTopBorderHeight() const { + return kTitleTopOffset + title_font_.height() + kTitleBottomSpacing; } -void DefaultNonClientView::PaintFrameBorder(ChromeCanvas* canvas) { - SkBitmap* top_left_corner = - resources()->GetPartBitmap(FRAME_TOP_LEFT_CORNER); +void DefaultNonClientView::PaintRestoredFrameBorder(ChromeCanvas* canvas) { + SkBitmap* top_left_corner = resources()->GetPartBitmap(FRAME_TOP_LEFT_CORNER); SkBitmap* top_right_corner = resources()->GetPartBitmap(FRAME_TOP_RIGHT_CORNER); SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); @@ -587,10 +549,9 @@ void DefaultNonClientView::PaintFrameBorder(ChromeCanvas* canvas) { width() - top_right_corner->width(), 0); // Right. - int top_stack_height = top_right_corner->height(); canvas->TileImageInt(*right_edge, width() - right_edge->width(), - top_stack_height, right_edge->width(), - height() - top_stack_height - + top_right_corner->height(), right_edge->width(), + height() - top_right_corner->height() - bottom_right_corner->height()); // Bottom. @@ -606,23 +567,28 @@ void DefaultNonClientView::PaintFrameBorder(ChromeCanvas* canvas) { height() - bottom_left_corner->height()); // Left. - top_stack_height = top_left_corner->height(); - canvas->TileImageInt(*left_edge, 0, top_stack_height, left_edge->width(), - height() - top_stack_height - - bottom_left_corner->height()); + canvas->TileImageInt(*left_edge, 0, top_left_corner->height(), + left_edge->width(), + height() - top_left_corner->height() - bottom_left_corner->height()); } void DefaultNonClientView::PaintMaximizedFrameBorder( ChromeCanvas* canvas) { SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); - SkBitmap* bottom_edge = - resources()->GetPartBitmap(FRAME_BOTTOM_EDGE); canvas->TileImageInt(*top_edge, 0, 0, width(), top_edge->height()); - canvas->TileImageInt(*bottom_edge, 0, height() - bottom_edge->height(), - width(), bottom_edge->height()); +} + +void DefaultNonClientView::PaintTitleBar(ChromeCanvas* canvas) { + WindowDelegate* d = container_->window_delegate(); + canvas->DrawStringInt(d->GetWindowTitle(), title_font_, SK_ColorWHITE, + MirroredLeftPointForRect(title_bounds_), title_bounds_.y(), + title_bounds_.width(), title_bounds_.height()); } void DefaultNonClientView::PaintClientEdge(ChromeCanvas* canvas) { + gfx::Rect client_area_bounds = container_->client_view()->bounds(); + int client_area_top = client_area_bounds.y(); + SkBitmap* top_left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); SkBitmap* top = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); SkBitmap* top_right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); @@ -634,19 +600,23 @@ void DefaultNonClientView::PaintClientEdge(ChromeCanvas* canvas) { resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); SkBitmap* left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); - gfx::Rect client_area_bounds = container_->client_view()->bounds(); - + // Top. + // This next calculation is necessary because the top center bitmap is shorter + // than the top left and right bitmaps. We need their top edges to line up, + // and we need the left and right edges to start below the corners' bottoms. + int top_edge_y = client_area_top - top->height(); + client_area_top = top_edge_y + top_left->height(); canvas->DrawBitmapInt(*top_left, client_area_bounds.x() - top_left->width(), - client_area_bounds.y() - top->height()); - canvas->TileImageInt(*top, client_area_bounds.x(), - client_area_bounds.y() - top->height(), + top_edge_y); + canvas->TileImageInt(*top, client_area_bounds.x(), top_edge_y, client_area_bounds.width(), top->height()); - canvas->DrawBitmapInt(*top_right, client_area_bounds.right(), - client_area_bounds.y() - top->height()); - canvas->TileImageInt(*right, client_area_bounds.right(), - client_area_bounds.y() - top->height() + - top_right->height(), + canvas->DrawBitmapInt(*top_right, client_area_bounds.right(), top_edge_y); + + // Right. + canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top, right->width(), client_area_bounds.height()); + + // Bottom. canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(), client_area_bounds.bottom()); canvas->TileImageInt(*bottom, client_area_bounds.x(), @@ -655,49 +625,47 @@ void DefaultNonClientView::PaintClientEdge(ChromeCanvas* canvas) { canvas->DrawBitmapInt(*bottom_left, client_area_bounds.x() - bottom_left->width(), client_area_bounds.bottom()); + + // Left. canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), - client_area_bounds.y() - top->height() + - top_left->height(), - left->width(), client_area_bounds.height()); + client_area_top, left->width(), client_area_bounds.height()); } void DefaultNonClientView::LayoutWindowControls() { - // TODO(pkasting): This function is almost identical to - // OpaqueNonClientView::LayoutWindowControls(), they should be combined. - int top_offset, top_extra_height, right_offset, right_extra_width; - Button* invisible_button, * visible_button; - if (container_->IsMaximized()) { - top_offset = 0; - top_extra_height = kWindowControlsTopZoomedOffset; - right_offset = kWindowControlsRightZoomedOffset; - right_extra_width = right_offset; - invisible_button = maximize_button_; - visible_button = restore_button_; - } else { - top_offset = kWindowControlsTopOffset; - top_extra_height = 0; - right_offset = kWindowControlsRightOffset; - right_extra_width = 0; - invisible_button = restore_button_; - visible_button = maximize_button_; - } - close_button_->SetImageAlignment(Button::ALIGN_LEFT, Button::ALIGN_BOTTOM); + // 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; + // 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_spacing = is_maximized ? + kWindowControlsRightZoomedOffset : kWindowControlsRightOffset; gfx::Size close_button_size = close_button_->GetPreferredSize(); - close_button_->SetBounds(width() - right_offset - close_button_size.width(), - top_offset, + close_button_->SetBounds(width() - close_button_size.width() - right_spacing, + caption_y, close_button_size.width() + right_extra_width, close_button_size.height() + top_extra_height); + // When the window is restored, we show a maximized button; otherwise, we show + // a restore button. + bool is_restored = !is_maximized && !container_->IsMinimized(); + views::Button* invisible_button = is_restored ? + restore_button_ : maximize_button_; invisible_button->SetVisible(false); + views::Button* visible_button = is_restored ? + maximize_button_ : restore_button_; FramePartBitmap normal_part, hot_part, pushed_part; if (should_show_minmax_buttons_) { visible_button->SetVisible(true); visible_button->SetImageAlignment(Button::ALIGN_LEFT, Button::ALIGN_BOTTOM); gfx::Size visible_button_size = visible_button->GetPreferredSize(); visible_button->SetBounds(close_button_->x() - visible_button_size.width(), - top_offset, visible_button_size.width(), + caption_y, visible_button_size.width(), visible_button_size.height() + top_extra_height); minimize_button_->SetVisible(true); @@ -705,7 +673,7 @@ void DefaultNonClientView::LayoutWindowControls() { Button::ALIGN_BOTTOM); gfx::Size minimize_button_size = minimize_button_->GetPreferredSize(); minimize_button_->SetBounds( - visible_button->x() - minimize_button_size.width(), top_offset, + visible_button->x() - minimize_button_size.width(), caption_y, minimize_button_size.width(), minimize_button_size.height() + top_extra_height); @@ -747,44 +715,29 @@ void DefaultNonClientView::LayoutTitleBar() { kWindowIconTopOffset, 0, 0); } - // Size the title, if visible. - if (d->ShouldShowWindowTitle()) { - 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()); - - // We draw the custom frame window's title directly rather than using a - // views::Label child view. Therefore, we have to mirror the title - // position manually if the View's UI layout is right-to-left. Child Views - // are automatically mirrored, which means that the parent view doesn't - // need to manually modify their position depending on the View's UI - // layout. - // - // Mirroring the title's position manually is certainly far from being - // elegant, but we have no choice (other than changing the - // DefaultNonClientView subclass to use a ChromeView::Label as a child View - // instead of drawing the title's text directly on the canvas). - title_bounds_.set_x(MirroredLeftPointForRect(title_bounds_)); - - // 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()); - } + // 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()); } } void DefaultNonClientView::LayoutClientView() { - gfx::Rect client_bounds = CalculateClientAreaBounds(width(), height()); - container_->client_view()->SetBounds(client_bounds); + container_->client_view()->SetBounds(CalculateClientAreaBounds(width(), + height())); } // static |