custom_frame_view.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 "grit/ui_resources.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_strings.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/font.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/path.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/rect.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), 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) should_show_maximize_button_(false), 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frame_background_(new FrameBackground()), 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) minimum_title_bar_x_(0), 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maximum_title_bar_x_(-1) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomFrameView::~CustomFrameView() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::Init(Widget* frame) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_ = frame; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) close_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_CLOSE, 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minimize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MINIMIZE, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maximize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MAXIMIZE, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restore_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_RESTORE, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) should_show_maximize_button_ = frame_->widget_delegate()->CanMaximize(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_->widget_delegate()->ShouldShowWindowIcon()) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_icon_ = new ImageButton(this); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(window_icon_); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, NonClientFrameView implementation: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameView::GetBoundsForClientView() const { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return client_view_bounds_; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameView::GetWindowBoundsForClientBounds( 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& client_bounds) const { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top_height = NonClientTopBorderHeight(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int border_thickness = NonClientBorderThickness(); 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return gfx::Rect(client_bounds.x() - border_thickness, 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client_bounds.y() - top_height, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_bounds.width() + (2 * border_thickness), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_bounds.height() + top_height + border_thickness); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::NonClientHitTest(const gfx::Point& point) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sanity check. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bounds().Contains(point)) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTNOWHERE; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frame_component = frame_->client_view()->NonClientHitTest(point); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if we're in the sysmenu region. (We check the ClientView first to be 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consistent with OpaqueBrowserFrameView; it's not really necessary here.) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect sysmenu_rect(IconBounds()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In maximized mode we extend the rect to the screen corner to take advantage 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of Fitts' Law. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_->IsMaximized()) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sysmenu_rect.SetRect(0, 0, sysmenu_rect.right(), sysmenu_rect.bottom()); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect)); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sysmenu_rect.Contains(point)) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_component != HTNOWHERE) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_component; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then see if the point is within any of the window controls. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (close_button_->GetMirroredBounds().Contains(point)) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTCLOSE; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restore_button_->GetMirroredBounds().Contains(point)) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTMAXBUTTON; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (maximize_button_->GetMirroredBounds().Contains(point)) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTMAXBUTTON; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (minimize_button_->GetMirroredBounds().Contains(point)) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTMINBUTTON; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window_icon_ && window_icon_->GetMirroredBounds().Contains(point)) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HTSYSMENU; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int window_component = GetHTComponentForFrame(point, FrameBorderThickness(), 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NonClientBorderThickness(), kResizeAreaCornerSize, kResizeAreaCornerSize, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->widget_delegate()->CanResize()); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fall back to the caption if no other component matches. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (window_component == HTNOWHERE) ? HTCAPTION : window_component; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::GetWindowMask(const gfx::Size& size, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Path* window_mask) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(window_mask); 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (frame_->IsMaximized() || !ShouldShowTitleBarAndBorder()) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDefaultWindowMask(size, window_mask); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::ResetWindowControls() { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) restore_button_->SetState(CustomButton::STATE_NORMAL); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) minimize_button_->SetState(CustomButton::STATE_NORMAL); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) maximize_button_->SetState(CustomButton::STATE_NORMAL); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The close button isn't affected by this constraint. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::UpdateWindowIcon() { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window_icon_) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_icon_->SchedulePaint(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::UpdateWindowTitle() { 200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (frame_->widget_delegate()->ShouldShowWindowTitle()) 201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SchedulePaintInRect(title_bounds_); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, View overrides: 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::OnPaint(gfx::Canvas* canvas) { 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ShouldShowTitleBarAndBorder()) 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_->IsMaximized()) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintMaximizedFrameBorder(canvas); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintRestoredFrameBorder(canvas); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintTitleBar(canvas); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldShowClientEdge()) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintRestoredClientEdge(canvas); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::Layout() { 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ShouldShowTitleBarAndBorder()) { 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LayoutWindowControls(); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LayoutTitleBar(); 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LayoutClientView(); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size CustomFrameView::GetPreferredSize() const { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_->non_client_view()->GetWindowBoundsForClientBounds( 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect(frame_->client_view()->GetPreferredSize())).size(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size CustomFrameView::GetMinimumSize() const { 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return frame_->non_client_view()->GetWindowBoundsForClientBounds( 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect(frame_->client_view()->GetMinimumSize())).size(); 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size CustomFrameView::GetMaximumSize() const { 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Size max_size = frame_->client_view()->GetMaximumSize(); 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Size converted_size = 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_->non_client_view()->GetWindowBoundsForClientBounds( 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect(max_size)).size(); 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return gfx::Size(max_size.width() == 0 ? 0 : converted_size.width(), 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) max_size.height() == 0 ? 0 : converted_size.height()); 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, ButtonListener implementation: 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::ButtonPressed(Button* sender, const ui::Event& event) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sender == close_button_) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Close(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender == minimize_button_) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Minimize(); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender == maximize_button_) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Maximize(); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (sender == restore_button_) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->Restore(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameView, private: 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::FrameBorderThickness() const { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_->IsMaximized() ? 0 : kFrameBorderThickness; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::NonClientBorderThickness() const { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In maximized mode, we don't show a client edge. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FrameBorderThickness() + 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ShouldShowClientEdge() ? kClientEdgeThickness : 0); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::NonClientTopBorderHeight() const { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(FrameBorderThickness() + IconSize(), 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CaptionButtonY() + kCaptionButtonHeightWithPadding) + 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TitlebarBottomThickness(); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::CaptionButtonY() const { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maximized buttons start at window top so that even if their images aren't 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drawn flush with the screen edge, they still obey Fitts' Law. 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return FrameBorderThickness(); 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return frame_->IsMaximized() ? FrameBorderThickness() : kFrameShadowThickness; 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::TitlebarBottomThickness() const { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kTitlebarTopAndBottomEdgeThickness + 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ShouldShowClientEdge() ? kClientEdgeThickness : 0); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameView::IconSize() const { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This metric scales up if either the titlebar height or the titlebar font 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size are increased. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetSystemMetrics(SM_CYSMICON); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::max(GetTitleFontList().GetHeight(), kIconMinimumSize); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameView::IconBounds() const { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size = IconSize(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frame_thickness = FrameBorderThickness(); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our frame border has a different "3D look" than Windows'. Theirs has a 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more complex gradient on the top that they push their icon/title below; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then the maximized window cuts this off and the icon/title are centered 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the remaining space. Because the apparent shape of our border is 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // simpler, using the same positioning makes things look slightly uncentered 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with restored windows, so when the window is restored, instead of 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calculating the remaining space from below the frame border, we calculate 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from below the 3D edge. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unavailable_px_at_top = frame_->IsMaximized() ? 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_thickness : kTitlebarTopAndBottomEdgeThickness; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the icon is shorter than the minimum space we reserve for the caption 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // button, we vertically center it. We want to bias rounding to put extra 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // space above the icon, since the 3D edge (+ client edge, for restored 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows) below looks (to the eye) more like additional space than does the 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3D edge (or nothing at all, for maximized windows) above; hence the +1. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = unavailable_px_at_top + (NonClientTopBorderHeight() - 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2; 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return gfx::Rect(frame_thickness + kIconLeftSpacing + minimum_title_bar_x_, 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) y, size, size); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CustomFrameView::ShouldShowTitleBarAndBorder() const { 33123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (frame_->IsFullscreen()) 33223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 33323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ViewsDelegate::views_delegate) { 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !ViewsDelegate::views_delegate->WindowManagerProvidesTitleBar( 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame_->IsMaximized()); 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CustomFrameView::ShouldShowClientEdge() const { 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !frame_->IsMaximized() && ShouldShowTitleBarAndBorder(); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_frame_color(GetFrameColor()); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* frame_image = GetFrameImage(); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_theme_image(frame_image); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_top_area_height(frame_image->height()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->SetCornerImages( 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_TOP_LEFT_CORNER).ToImageSkia(), 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_TOP_RIGHT_CORNER).ToImageSkia(), 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER).ToImageSkia(), 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER).ToImageSkia()); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->SetSideImages( 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_LEFT_SIDE).ToImageSkia(), 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_TOP_CENTER).ToImageSkia(), 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_RIGHT_SIDE).ToImageSkia(), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(IDR_WINDOW_BOTTOM_CENTER).ToImageSkia()); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->PaintRestored(canvas, this); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* frame_image = GetFrameImage(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_theme_image(frame_image); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->set_top_area_height(frame_image->height()); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_background_->PaintMaximized(canvas, this); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jamescook): Migrate this into FrameBackground. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The bottom of the titlebar actually comes from the top of the Client Edge 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // graphic, with the actual client edge clipped off the bottom. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* titlebar_bottom = rb.GetImageNamed( 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_APP_TOP_CENTER).ToImageSkia(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int edge_height = titlebar_bottom->height() - 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ShouldShowClientEdge() ? kClientEdgeThickness : 0); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->TileImageInt(*titlebar_bottom, 0, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->client_view()->y() - edge_height, width(), edge_height); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintTitleBar(gfx::Canvas* canvas) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WidgetDelegate* delegate = frame_->widget_delegate(); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It seems like in some conditions we can be asked to paint after the window 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that contains us is WM_DESTROYed. At this point, our delegate is NULL. The 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correct long term fix may be to shut down the RootView in WM_DESTROY. 393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!delegate || !delegate->ShouldShowWindowTitle()) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect rect = title_bounds_; 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rect.set_x(GetMirroredXForRect(title_bounds_)); 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas->DrawStringRect(delegate->GetWindowTitle(), GetTitleFontList(), 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SK_ColorWHITE, rect); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect client_area_bounds = frame_->client_view()->bounds(); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int client_area_top = client_area_bounds.y(); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Top: left, center, right sides. 409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* top_left = rb.GetImageSkiaNamed(IDR_APP_TOP_LEFT); 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* top_center = rb.GetImageSkiaNamed(IDR_APP_TOP_CENTER); 411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* top_right = rb.GetImageSkiaNamed(IDR_APP_TOP_RIGHT); 412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int top_edge_y = client_area_top - top_center->height(); 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->DrawImageInt(*top_left, 414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.x() - top_left->width(), 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_edge_y); 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*top_center, 417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.x(), 418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) top_edge_y, 419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.width(), 420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) top_center->height()); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*top_right, client_area_bounds.right(), top_edge_y); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Right side. 424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* right = rb.GetImageSkiaNamed(IDR_CONTENT_RIGHT_SIDE); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int client_area_bottom = 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(client_area_top, client_area_bounds.bottom()); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int client_area_height = client_area_bottom - client_area_top; 428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*right, 429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.right(), 430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_top, 431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) right->width(), 432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_height); 433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Bottom: left, center, right sides. 435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* bottom_left = 436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rb.GetImageSkiaNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER); 437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* bottom_center = 438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rb.GetImageSkiaNamed(IDR_CONTENT_BOTTOM_CENTER); 439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* bottom_right = 440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rb.GetImageSkiaNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*bottom_left, 443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.x() - bottom_left->width(), 444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bottom); 445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*bottom_center, 447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.x(), 448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bottom, 449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.width(), 450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bottom_right->height()); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->DrawImageInt(*bottom_right, 453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.right(), 454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bottom); 455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Left side. 456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::ImageSkia* left = rb.GetImageSkiaNamed(IDR_CONTENT_LEFT_SIDE); 457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->TileImageInt(*left, 458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.x() - left->width(), 459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_top, 460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) left->width(), 461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_height); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw the color to fill in the edges. 464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) canvas->FillRect(gfx::Rect(client_area_bounds.x() - 1, 465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_top - 1, 466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bounds.width() + 1, 467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_area_bottom - client_area_top + 1), 468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kClientEdgeColor); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor CustomFrameView::GetFrameColor() const { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame_->IsActive() ? kDefaultColorFrame : kDefaultColorFrameInactive; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::ImageSkia* CustomFrameView::GetFrameImage() const { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::ResourceBundle::GetSharedInstance().GetImageNamed( 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_->IsActive() ? IDR_FRAME : IDR_FRAME_INACTIVE).ToImageSkia(); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::LayoutWindowControls() { 481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) minimum_title_bar_x_ = 0; 482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maximum_title_bar_x_ = width(); 483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (bounds().IsEmpty()) 485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int caption_y = CaptionButtonY(); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_maximized = frame_->IsMaximized(); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There should always be the same number of non-shadow pixels visible to the 490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // side of the caption buttons. In maximized mode we extend the edge button 491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // to the screen corner to obey Fitts' Law. 492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int extra_width = is_maximized ? 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kFrameBorderThickness - kFrameShadowThickness) : 0; 494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int next_button_x = FrameBorderThickness(); 495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_restored = !is_maximized && !frame_->IsMinimized(); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageButton* invisible_button = is_restored ? restore_button_ 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : maximize_button_; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invisible_button->SetVisible(false); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WindowButtonOrderProvider* button_order = 502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WindowButtonOrderProvider::GetInstance(); 503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<views::FrameButton>& leading_buttons = 504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button_order->leading_buttons(); 505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<views::FrameButton>& trailing_buttons = 506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button_order->trailing_buttons(); 507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ImageButton* button = NULL; 509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::vector<views::FrameButton>::const_iterator it = 510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leading_buttons.begin(); it != leading_buttons.end(); ++it) { 511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = GetImageButton(*it); 512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!button) 513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y), 515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->GetPreferredSize()); 516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it == leading_buttons.begin()) 517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) target_bounds.set_width(target_bounds.width() + extra_width); 518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LayoutButton(button, target_bounds); 519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_button_x += button->width(); 520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) minimum_title_bar_x_ = std::min(width(), next_button_x); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Trailing buttions are laid out in a RTL fashion 524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_button_x = width() - FrameBorderThickness(); 525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::vector<views::FrameButton>::const_reverse_iterator it = 526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) trailing_buttons.rbegin(); it != trailing_buttons.rend(); ++it) { 527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = GetImageButton(*it); 528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!button) 529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y), 531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->GetPreferredSize()); 532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it == trailing_buttons.rbegin()) 533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) target_bounds.set_width(target_bounds.width() + extra_width); 534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) target_bounds.Offset(-target_bounds.width(), 0); 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LayoutButton(button, target_bounds); 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) next_button_x = button->x(); 537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maximum_title_bar_x_ = std::max(minimum_title_bar_x_, next_button_x); 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::LayoutTitleBar() { 542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_GE(maximum_title_bar_x_, 0); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window title position is calculated based on the icon position, even 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no icon. 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect icon_bounds(IconBounds()); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool show_window_icon = window_icon_ != NULL; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_window_icon) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_icon_->SetBoundsRect(icon_bounds); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 550010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!frame_->widget_delegate()->ShouldShowWindowTitle()) 551010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The offset between the window left edge and the title text. 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int title_x = show_window_icon ? icon_bounds.right() + kTitleIconOffsetX 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : icon_bounds.x(); 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int title_height = GetTitleFontList().GetHeight(); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We bias the title position so that when the difference between the icon and 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // title heights is odd, the extra pixel of the title is above the vertical 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // midline rather than below. This compensates for how the icon is already 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // biased downwards (see IconBounds()) and helps prevent descenders on the 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // title from overlapping the 3D edge at the bottom of the titlebar. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_bounds_.SetRect(title_x, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2), 564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::max(0, maximum_title_bar_x_ - kTitleCaptionSpacing - 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title_x), title_height); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameView::LayoutClientView() { 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ShouldShowTitleBarAndBorder()) { 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) client_view_bounds_ = bounds(); 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int top_height = NonClientTopBorderHeight(); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int border_thickness = NonClientBorderThickness(); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_view_bounds_.SetRect(border_thickness, top_height, 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, width() - (2 * border_thickness)), 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, height() - top_height - border_thickness)); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageButton* CustomFrameView::InitWindowCaptionButton( 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int accessibility_string_id, 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int normal_image_id, 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int hot_image_id, 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pushed_image_id) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageButton* button = new ImageButton(this); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->SetAccessibleName(l10n_util::GetStringUTF16(accessibility_string_id)); 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(CustomButton::STATE_NORMAL, 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(normal_image_id).ToImageSkia()); 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(CustomButton::STATE_HOVERED, 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(hot_image_id).ToImageSkia()); 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(CustomButton::STATE_PRESSED, 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetImageNamed(pushed_image_id).ToImageSkia()); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(button); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return button; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ImageButton* CustomFrameView::GetImageButton(views::FrameButton frame_button) { 600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ImageButton* button = NULL; 601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (frame_button) { 602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case views::FRAME_BUTTON_MINIMIZE: { 603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = minimize_button_; 604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case views::FRAME_BUTTON_MAXIMIZE: { 607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool is_restored = !frame_->IsMaximized() && !frame_->IsMinimized(); 608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = is_restored ? maximize_button_ : restore_button_; 609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!should_show_maximize_button_) { 610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If we should not show the maximize/restore button, then we return 611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // NULL as we don't want this button to become visible and to be laid 612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // out. 613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button->SetVisible(false); 614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case views::FRAME_BUTTON_CLOSE: { 619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button = close_button_; 620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return button; 624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 627