15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/custom_frame_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/font.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/path.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/rect.h" 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/strings/grit/ui_strings.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/color_constants.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/image_button.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/views_delegate.h" 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/widget/native_widget_private.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/client_view.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/frame_background.h" 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/window/window_button_order_provider.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/window_resources.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/window_shape.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The frame border is only visible in restored mode and is hardcoded to 4 px on 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// each side regardless of the system window border size. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFrameBorderThickness = 4; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the window corners, the resize areas don't actually expand bigger, but the 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 16 px at the end of each edge triggers diagonal resizing. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kResizeAreaCornerSize = 16; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The titlebar never shrinks too short to show the caption button plus some 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// padding below it. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCaptionButtonHeightWithPadding = 19; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The titlebar has a 2 px 3D edge along the top and bottom. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTitlebarTopAndBottomEdgeThickness = 2; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The icon is inset 2 px from the left frame border. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kIconLeftSpacing = 2; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The icon never shrinks below 16 px on a side. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kIconMinimumSize = 16; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The space between the window icon and the title text. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTitleIconOffsetX = 4; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The space between the title text and the caption buttons. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTitleCaptionSpacing = 5; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_CHROMEOS) 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Chrome OS uses a dark gray. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkColor kDefaultColorFrame = SkColorSetRGB(109, 109, 109); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkColor kDefaultColorFrameInactive = SkColorSetRGB(176, 176, 176); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Windows and Linux use a blue. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const gfx::FontList& GetTitleFontList() { 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const gfx::FontList title_font_list = 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu internal::NativeWidgetPrivate::GetWindowTitleFontList(); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return title_font_list; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LayoutButton(ImageButton* button, const gfx::Rect& bounds) { 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->SetVisible(true); 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->SetImageAlignment(ImageButton::ALIGN_LEFT, 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ImageButton::ALIGN_BOTTOM); 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->SetBoundsRect(bounds); 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, public: 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomFrameView::CustomFrameView() 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : frame_(NULL), 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_icon_(NULL), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minimize_button_(NULL), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximize_button_(NULL), 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restore_button_(NULL), 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_button_(NULL), 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frame_background_(new FrameBackground()), 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) minimum_title_bar_x_(0), 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maximum_title_bar_x_(-1) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomFrameView::~CustomFrameView() { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::Init(Widget* frame) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_ = frame; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) close_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_CLOSE, 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minimize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MINIMIZE, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MAXIMIZE, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restore_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_RESTORE, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_->widget_delegate()->ShouldShowWindowIcon()) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_icon_ = new ImageButton(this); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(window_icon_); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, NonClientFrameView implementation: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameView::GetBoundsForClientView() const { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return client_view_bounds_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameView::GetWindowBoundsForClientBounds( 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& client_bounds) const { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top_height = NonClientTopBorderHeight(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int border_thickness = NonClientBorderThickness(); 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return gfx::Rect(client_bounds.x() - border_thickness, 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client_bounds.y() - top_height, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_bounds.width() + (2 * border_thickness), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_bounds.height() + top_height + border_thickness); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::NonClientHitTest(const gfx::Point& point) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sanity check. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bounds().Contains(point)) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTNOWHERE; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frame_component = frame_->client_view()->NonClientHitTest(point); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if we're in the sysmenu region. (We check the ClientView first to be 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consistent with OpaqueBrowserFrameView; it's not really necessary here.) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect sysmenu_rect(IconBounds()); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In maximized mode we extend the rect to the screen corner to take advantage 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of Fitts' Law. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_->IsMaximized()) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sysmenu_rect.SetRect(0, 0, sysmenu_rect.right(), sysmenu_rect.bottom()); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sysmenu_rect.Contains(point)) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_component != HTNOWHERE) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_component; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then see if the point is within any of the window controls. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (close_button_->GetMirroredBounds().Contains(point)) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTCLOSE; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restore_button_->GetMirroredBounds().Contains(point)) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTMAXBUTTON; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (maximize_button_->GetMirroredBounds().Contains(point)) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTMAXBUTTON; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (minimize_button_->GetMirroredBounds().Contains(point)) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTMINBUTTON; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window_icon_ && window_icon_->GetMirroredBounds().Contains(point)) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTSYSMENU; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int window_component = GetHTComponentForFrame(point, FrameBorderThickness(), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NonClientBorderThickness(), kResizeAreaCornerSize, kResizeAreaCornerSize, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->widget_delegate()->CanResize()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fall back to the caption if no other component matches. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (window_component == HTNOWHERE) ? HTCAPTION : window_component; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::GetWindowMask(const gfx::Size& size, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Path* window_mask) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(window_mask); 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (frame_->IsMaximized() || !ShouldShowTitleBarAndBorder()) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDefaultWindowMask(size, window_mask); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::ResetWindowControls() { 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) restore_button_->SetState(CustomButton::STATE_NORMAL); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) minimize_button_->SetState(CustomButton::STATE_NORMAL); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) maximize_button_->SetState(CustomButton::STATE_NORMAL); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The close button isn't affected by this constraint. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::UpdateWindowIcon() { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window_icon_) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_icon_->SchedulePaint(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::UpdateWindowTitle() { 197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (frame_->widget_delegate()->ShouldShowWindowTitle()) 198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SchedulePaintInRect(title_bounds_); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CustomFrameView::SizeConstraintsChanged() { 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ResetWindowControls(); 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LayoutWindowControls(); 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, View overrides: 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::OnPaint(gfx::Canvas* canvas) { 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ShouldShowTitleBarAndBorder()) 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_->IsMaximized()) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintMaximizedFrameBorder(canvas); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintRestoredFrameBorder(canvas); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintTitleBar(canvas); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldShowClientEdge()) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintRestoredClientEdge(canvas); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::Layout() { 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ShouldShowTitleBarAndBorder()) { 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LayoutWindowControls(); 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LayoutTitleBar(); 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LayoutClientView(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size CustomFrameView::GetPreferredSize() const { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_->non_client_view()->GetWindowBoundsForClientBounds( 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect(frame_->client_view()->GetPreferredSize())).size(); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size CustomFrameView::GetMinimumSize() const { 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return frame_->non_client_view()->GetWindowBoundsForClientBounds( 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect(frame_->client_view()->GetMinimumSize())).size(); 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size CustomFrameView::GetMaximumSize() const { 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Size max_size = frame_->client_view()->GetMaximumSize(); 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Size converted_size = 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_->non_client_view()->GetWindowBoundsForClientBounds( 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect(max_size)).size(); 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return gfx::Size(max_size.width() == 0 ? 0 : converted_size.width(), 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) max_size.height() == 0 ? 0 : converted_size.height()); 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, ButtonListener implementation: 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::ButtonPressed(Button* sender, const ui::Event& event) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sender == close_button_) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Close(); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender == minimize_button_) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Minimize(); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender == maximize_button_) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Maximize(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender == restore_button_) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Restore(); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, private: 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::FrameBorderThickness() const { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_->IsMaximized() ? 0 : kFrameBorderThickness; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::NonClientBorderThickness() const { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In maximized mode, we don't show a client edge. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FrameBorderThickness() + 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ShouldShowClientEdge() ? kClientEdgeThickness : 0); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::NonClientTopBorderHeight() const { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(FrameBorderThickness() + IconSize(), 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CaptionButtonY() + kCaptionButtonHeightWithPadding) + 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TitlebarBottomThickness(); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::CaptionButtonY() const { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maximized buttons start at window top so that even if their images aren't 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drawn flush with the screen edge, they still obey Fitts' Law. 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return FrameBorderThickness(); 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return frame_->IsMaximized() ? FrameBorderThickness() : kFrameShadowThickness; 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::TitlebarBottomThickness() const { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kTitlebarTopAndBottomEdgeThickness + 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ShouldShowClientEdge() ? kClientEdgeThickness : 0); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::IconSize() const { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This metric scales up if either the titlebar height or the titlebar font 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size are increased. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetSystemMetrics(SM_CYSMICON); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::max(GetTitleFontList().GetHeight(), kIconMinimumSize); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameView::IconBounds() const { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size = IconSize(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frame_thickness = FrameBorderThickness(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our frame border has a different "3D look" than Windows'. Theirs has a 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more complex gradient on the top that they push their icon/title below; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then the maximized window cuts this off and the icon/title are centered 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the remaining space. Because the apparent shape of our border is 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // simpler, using the same positioning makes things look slightly uncentered 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with restored windows, so when the window is restored, instead of 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calculating the remaining space from below the frame border, we calculate 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from below the 3D edge. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unavailable_px_at_top = frame_->IsMaximized() ? 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_thickness : kTitlebarTopAndBottomEdgeThickness; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the icon is shorter than the minimum space we reserve for the caption 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // button, we vertically center it. We want to bias rounding to put extra 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // space above the icon, since the 3D edge (+ client edge, for restored 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows) below looks (to the eye) more like additional space than does the 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3D edge (or nothing at all, for maximized windows) above; hence the +1. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = unavailable_px_at_top + (NonClientTopBorderHeight() - 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2; 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return gfx::Rect(frame_thickness + kIconLeftSpacing + minimum_title_bar_x_, 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) y, size, size); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CustomFrameView::ShouldShowTitleBarAndBorder() const { 33323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (frame_->IsFullscreen()) 33423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 33523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ViewsDelegate::views_delegate) { 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !ViewsDelegate::views_delegate->WindowManagerProvidesTitleBar( 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame_->IsMaximized()); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CustomFrameView::ShouldShowClientEdge() const { 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !frame_->IsMaximized() && ShouldShowTitleBarAndBorder(); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_frame_color(GetFrameColor()); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* frame_image = GetFrameImage(); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_theme_image(frame_image); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_top_area_height(frame_image->height()); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->SetCornerImages( 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_TOP_LEFT_CORNER).ToImageSkia(), 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_TOP_RIGHT_CORNER).ToImageSkia(), 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER).ToImageSkia(), 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER).ToImageSkia()); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->SetSideImages( 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_LEFT_SIDE).ToImageSkia(), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_TOP_CENTER).ToImageSkia(), 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_RIGHT_SIDE).ToImageSkia(), 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_BOTTOM_CENTER).ToImageSkia()); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->PaintRestored(canvas, this); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* frame_image = GetFrameImage(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_theme_image(frame_image); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_top_area_height(frame_image->height()); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->PaintMaximized(canvas, this); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jamescook): Migrate this into FrameBackground. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The bottom of the titlebar actually comes from the top of the Client Edge 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // graphic, with the actual client edge clipped off the bottom. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* titlebar_bottom = rb.GetImageNamed( 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_APP_TOP_CENTER).ToImageSkia(); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int edge_height = titlebar_bottom->height() - 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ShouldShowClientEdge() ? kClientEdgeThickness : 0); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->TileImageInt(*titlebar_bottom, 0, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->client_view()->y() - edge_height, width(), edge_height); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintTitleBar(gfx::Canvas* canvas) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WidgetDelegate* delegate = frame_->widget_delegate(); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It seems like in some conditions we can be asked to paint after the window 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that contains us is WM_DESTROYed. At this point, our delegate is NULL. The 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correct long term fix may be to shut down the RootView in WM_DESTROY. 395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!delegate || !delegate->ShouldShowWindowTitle()) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect rect = title_bounds_; 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rect.set_x(GetMirroredXForRect(title_bounds_)); 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas->DrawStringRect(delegate->GetWindowTitle(), GetTitleFontList(), 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SK_ColorWHITE, rect); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect client_area_bounds = frame_->client_view()->bounds(); 40603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The shadows have a 1 pixel gap on the inside, so draw them 1 pixel inwards. 40703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Rect shadowed_area_bounds = client_area_bounds; 40803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.Inset(gfx::Insets(1, 1, 1, 1)); 40903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int shadowed_area_top = shadowed_area_bounds.y(); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Top: left, center, right sides. 414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* top_left = rb.GetImageSkiaNamed(IDR_APP_TOP_LEFT); 415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* top_center = rb.GetImageSkiaNamed(IDR_APP_TOP_CENTER); 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* top_right = rb.GetImageSkiaNamed(IDR_APP_TOP_RIGHT); 41703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int top_edge_y = shadowed_area_top - top_center->height(); 418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->DrawImageInt(*top_left, 41903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.x() - top_left->width(), 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_edge_y); 421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*top_center, 42203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.x(), 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) top_edge_y, 42403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.width(), 425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) top_center->height()); 42603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) canvas->DrawImageInt(*top_right, shadowed_area_bounds.right(), top_edge_y); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Right side. 429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* right = rb.GetImageSkiaNamed(IDR_CONTENT_RIGHT_SIDE); 43003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int shadowed_area_bottom = 43103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::max(shadowed_area_top, shadowed_area_bounds.bottom()); 43203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int shadowed_area_height = shadowed_area_bottom - shadowed_area_top; 433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*right, 43403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.right(), 43503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_top, 436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) right->width(), 43703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_height); 438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Bottom: left, center, right sides. 440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* bottom_left = 441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rb.GetImageSkiaNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER); 442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* bottom_center = 443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rb.GetImageSkiaNamed(IDR_CONTENT_BOTTOM_CENTER); 444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* bottom_right = 445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rb.GetImageSkiaNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*bottom_left, 44803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.x() - bottom_left->width(), 44903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bottom); 450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*bottom_center, 45203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.x(), 45303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bottom, 45403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.width(), 455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bottom_right->height()); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->DrawImageInt(*bottom_right, 45803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.right(), 45903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bottom); 460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Left side. 461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* left = rb.GetImageSkiaNamed(IDR_CONTENT_LEFT_SIDE); 462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*left, 46303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_bounds.x() - left->width(), 46403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_top, 465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) left->width(), 46603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shadowed_area_height); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor CustomFrameView::GetFrameColor() const { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_->IsActive() ? kDefaultColorFrame : kDefaultColorFrameInactive; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::ImageSkia* CustomFrameView::GetFrameImage() const { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::ResourceBundle::GetSharedInstance().GetImageNamed( 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->IsActive() ? IDR_FRAME : IDR_FRAME_INACTIVE).ToImageSkia(); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::LayoutWindowControls() { 479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) minimum_title_bar_x_ = 0; 480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maximum_title_bar_x_ = width(); 481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (bounds().IsEmpty()) 483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int caption_y = CaptionButtonY(); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_maximized = frame_->IsMaximized(); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There should always be the same number of non-shadow pixels visible to the 488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // side of the caption buttons. In maximized mode we extend the edge button 489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // to the screen corner to obey Fitts' Law. 490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int extra_width = is_maximized ? 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kFrameBorderThickness - kFrameShadowThickness) : 0; 492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int next_button_x = FrameBorderThickness(); 493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_restored = !is_maximized && !frame_->IsMinimized(); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageButton* invisible_button = is_restored ? restore_button_ 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : maximize_button_; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invisible_button->SetVisible(false); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WindowButtonOrderProvider* button_order = 500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WindowButtonOrderProvider::GetInstance(); 501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<views::FrameButton>& leading_buttons = 502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button_order->leading_buttons(); 503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<views::FrameButton>& trailing_buttons = 504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button_order->trailing_buttons(); 505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ImageButton* button = NULL; 507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::vector<views::FrameButton>::const_iterator it = 508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leading_buttons.begin(); it != leading_buttons.end(); ++it) { 509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = GetImageButton(*it); 510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!button) 511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y), 513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->GetPreferredSize()); 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it == leading_buttons.begin()) 515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) target_bounds.set_width(target_bounds.width() + extra_width); 516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LayoutButton(button, target_bounds); 517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_button_x += button->width(); 518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) minimum_title_bar_x_ = std::min(width(), next_button_x); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Trailing buttions are laid out in a RTL fashion 522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_button_x = width() - FrameBorderThickness(); 523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::vector<views::FrameButton>::const_reverse_iterator it = 524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) trailing_buttons.rbegin(); it != trailing_buttons.rend(); ++it) { 525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = GetImageButton(*it); 526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!button) 527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y), 529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->GetPreferredSize()); 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it == trailing_buttons.rbegin()) 531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) target_bounds.set_width(target_bounds.width() + extra_width); 532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) target_bounds.Offset(-target_bounds.width(), 0); 533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LayoutButton(button, target_bounds); 534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_button_x = button->x(); 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maximum_title_bar_x_ = std::max(minimum_title_bar_x_, next_button_x); 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::LayoutTitleBar() { 540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_GE(maximum_title_bar_x_, 0); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window title position is calculated based on the icon position, even 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no icon. 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect icon_bounds(IconBounds()); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool show_window_icon = window_icon_ != NULL; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_window_icon) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_icon_->SetBoundsRect(icon_bounds); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!frame_->widget_delegate()->ShouldShowWindowTitle()) 549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 550010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The offset between the window left edge and the title text. 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int title_x = show_window_icon ? icon_bounds.right() + kTitleIconOffsetX 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : icon_bounds.x(); 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int title_height = GetTitleFontList().GetHeight(); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We bias the title position so that when the difference between the icon and 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // title heights is odd, the extra pixel of the title is above the vertical 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // midline rather than below. This compensates for how the icon is already 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // biased downwards (see IconBounds()) and helps prevent descenders on the 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // title from overlapping the 3D edge at the bottom of the titlebar. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_bounds_.SetRect(title_x, 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2), 562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::max(0, maximum_title_bar_x_ - kTitleCaptionSpacing - 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_x), title_height); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::LayoutClientView() { 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ShouldShowTitleBarAndBorder()) { 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_view_bounds_ = bounds(); 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top_height = NonClientTopBorderHeight(); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int border_thickness = NonClientBorderThickness(); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_view_bounds_.SetRect(border_thickness, top_height, 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, width() - (2 * border_thickness)), 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, height() - top_height - border_thickness)); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageButton* CustomFrameView::InitWindowCaptionButton( 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int accessibility_string_id, 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int normal_image_id, 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int hot_image_id, 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pushed_image_id) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageButton* button = new ImageButton(this); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->SetAccessibleName(l10n_util::GetStringUTF16(accessibility_string_id)); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(CustomButton::STATE_NORMAL, 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(normal_image_id).ToImageSkia()); 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(CustomButton::STATE_HOVERED, 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(hot_image_id).ToImageSkia()); 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(CustomButton::STATE_PRESSED, 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(pushed_image_id).ToImageSkia()); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(button); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return button; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ImageButton* CustomFrameView::GetImageButton(views::FrameButton frame_button) { 598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ImageButton* button = NULL; 599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (frame_button) { 600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case views::FRAME_BUTTON_MINIMIZE: { 601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = minimize_button_; 6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If we should not show the minimize button, then we return NULL as we 6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // don't want this button to become visible and to be laid out. 6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool should_show = frame_->widget_delegate()->CanMinimize(); 6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci button->SetVisible(should_show); 6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!should_show) 6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case views::FRAME_BUTTON_MAXIMIZE: { 612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool is_restored = !frame_->IsMaximized() && !frame_->IsMinimized(); 613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = is_restored ? maximize_button_ : restore_button_; 6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If we should not show the maximize/restore button, then we return 6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // NULL as we don't want this button to become visible and to be laid 6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // out. 6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool should_show = frame_->widget_delegate()->CanMaximize(); 6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci button->SetVisible(should_show); 6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!should_show) 620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case views::FRAME_BUTTON_CLOSE: { 625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = close_button_; 626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 627cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 629cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return button; 630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 633