172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/app_panel_browser_frame_view.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h" 83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/utf_string_conversions.h" 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_frame.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas.h" 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/font.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/path.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/image_button.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window_resources.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/hit_test.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The frame border is only visible in restored mode and is hardcoded to 1 px on 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// each side regardless of the system window border size. 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kFrameBorderThickness = 1; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In the window corners, the resize areas don't actually expand bigger, but the 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 16 px at the end of each edge triggers diagonal resizing. 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kResizeAreaCornerSize = 16; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The titlebar never shrinks too short to show the caption button plus some 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// padding below it. 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCaptionButtonHeightWithPadding = 27; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The titlebar has a 2 px 3D edge along the bottom, and we reserve 2 px (1 for 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// border, 1 for padding) along the top. 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTitlebarTopAndBottomEdgeThickness = 2; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The icon is inset 6 px from the left frame border. 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIconLeftSpacing = 6; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The icon never shrinks below 16 px on a side. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIconMinimumSize = 16; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is a 4 px gap between the icon and the title text. 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIconTitleSpacing = 4; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is a 5 px gap between the title text and the close button. 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTitleCloseButtonSpacing = 5; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is a 4 px gap between the close button and the frame border. 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCloseButtonFrameBorderSpacing = 4; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, public: 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAppPanelBrowserFrameView::AppPanelBrowserFrameView(BrowserFrame* frame, 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserView* browser_view) 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BrowserNonClientFrameView(), 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST( 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_(new views::ImageButton(this))), 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_icon_(NULL), 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_(frame), 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_view_(browser_view) { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser_view->ShouldShowWindowIcon()); 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser_view->ShouldShowWindowTitle()); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetImage(views::CustomButton::BS_NORMAL, 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_CLOSE_BAR)); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetImage(views::CustomButton::BS_HOT, 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetImage(views::CustomButton::BS_PUSHED, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); 753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen close_button_->SetAccessibleName( 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(close_button_); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_icon_ = new TabIconView(this); 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_icon_->set_is_light(true); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(window_icon_); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_icon_->Update(); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAppPanelBrowserFrameView::~AppPanelBrowserFrameView() { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, BrowserNonClientFrameView implementation: 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::GetBoundsForTabStrip( 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen views::View* tabstrip) const { 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // App panels never show a tab strip. 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint AppPanelBrowserFrameView::GetHorizontalTabStripVerticalOffset( 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool restored) const { 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // App panels are not themed and don't need this. 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return 0; 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::UpdateThrobber(bool running) { 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_icon_->Update(); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size AppPanelBrowserFrameView::GetMinimumSize() { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size min_size(browser_view_->GetMinimumSize()); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int border_thickness = NonClientBorderThickness(); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch min_size.Enlarge(2 * border_thickness, 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NonClientTopBorderHeight() + border_thickness); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch min_size.set_width(std::max(min_size.width(), 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (2 * FrameBorderThickness()) + kIconLeftSpacing + IconSize() + 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kTitleCloseButtonSpacing + kCloseButtonFrameBorderSpacing)); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return min_size; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, views::NonClientFrameView implementation: 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::GetBoundsForClientView() const { 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return client_view_bounds_; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AppPanelBrowserFrameView::AlwaysUseCustomFrame() const { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AppPanelBrowserFrameView::AlwaysUseNativeFrame() const { 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return frame_->AlwaysUseNativeFrame(); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::GetWindowBoundsForClientBounds( 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Rect& client_bounds) const { 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int top_height = NonClientTopBorderHeight(); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int border_thickness = NonClientBorderThickness(); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(std::max(0, client_bounds.x() - border_thickness), 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(0, client_bounds.y() - top_height), 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_bounds.width() + (2 * border_thickness), 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_bounds.height() + top_height + border_thickness); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::NonClientHitTest(const gfx::Point& point) { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!bounds().Contains(point)) 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return HTNOWHERE; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int frame_component = 150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen frame_->GetWindow()->client_view()->NonClientHitTest(point); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if we're in the sysmenu region. (We check the ClientView first to be 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // consistent with OpaqueBrowserFrameView; it's not really necessary here.) 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect sysmenu_rect(IconBounds()); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In maximized mode we extend the rect to the screen corner to take advantage 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of Fitts' Law. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame_->GetWindow()->IsMaximized()) 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sysmenu_rect.SetRect(0, 0, sysmenu_rect.right(), sysmenu_rect.bottom()); 15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect)); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sysmenu_rect.Contains(point)) 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame_component != HTNOWHERE) 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return frame_component; 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Then see if the point is within any of the window controls. 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (close_button_->IsVisible() && 16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen close_button_->GetMirroredBounds().Contains(point)) 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return HTCLOSE; 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int window_component = GetHTComponentForFrame(point, 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NonClientBorderThickness(), NonClientBorderThickness(), 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kResizeAreaCornerSize, kResizeAreaCornerSize, 174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen frame_->GetWindow()->window_delegate()->CanResize()); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fall back to the caption if no other component matches. 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (window_component == HTNOWHERE) ? HTCAPTION : window_component; 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::GetWindowMask(const gfx::Size& size, 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Path* window_mask) { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(window_mask); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame_->GetWindow()->IsMaximized()) 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Redefine the window visible region for the new size. 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->moveTo(0, 3); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(1, 2); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(1, 1); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(2, 1); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(3, 0); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(SkIntToScalar(size.width() - 3), 0); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(SkIntToScalar(size.width() - 2), 1); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(SkIntToScalar(size.width() - 1), 1); 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(SkIntToScalar(size.width() - 1), 2); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(SkIntToScalar(size.width()), 3); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(SkIntToScalar(size.width()), 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkIntToScalar(size.height())); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->lineTo(0, SkIntToScalar(size.height())); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_mask->close(); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::EnableClose(bool enable) { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetEnabled(enable); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::ResetWindowControls() { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The close button isn't affected by this constraint. 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AppPanelBrowserFrameView::UpdateWindowIcon() { 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen window_icon_->SchedulePaint(); 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, views::View overrides: 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AppPanelBrowserFrameView::OnPaint(gfx::Canvas* canvas) { 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Window* window = frame_->GetWindow(); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (window->IsMaximized()) 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintMaximizedFrameBorder(canvas); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintRestoredFrameBorder(canvas); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintTitleBar(canvas); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!window->IsMaximized()) 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintRestoredClientEdge(canvas); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::Layout() { 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LayoutWindowControls(); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LayoutTitleBar(); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_view_bounds_ = CalculateClientAreaBounds(width(), height()); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, views::ButtonListener implementation: 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::ButtonPressed(views::Button* sender, 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const views::Event& event) { 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sender == close_button_) 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen frame_->GetWindow()->CloseWindow(); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, TabIconView::TabContentsProvider implementation: 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AppPanelBrowserFrameView::ShouldTabIconViewAnimate() const { 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This function is queried during the creation of the window as the 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabIconView we host is initialized, so we need to NULL check the selected 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TabContents because in this condition there is not yet a selected tab. 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* current_tab = browser_view_->GetSelectedTabContents(); 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return current_tab ? current_tab->is_loading() : false; 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSkBitmap AppPanelBrowserFrameView::GetFaviconForTabIconView() { 259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return frame_->GetWindow()->window_delegate()->GetWindowIcon(); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, private: 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::FrameBorderThickness() const { 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return frame_->GetWindow()->IsMaximized() ? 0 : kFrameBorderThickness; 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::NonClientBorderThickness() const { 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FrameBorderThickness() + 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (frame_->GetWindow()->IsMaximized() ? 0 : kClientEdgeThickness); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::NonClientTopBorderHeight() const { 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return std::max(FrameBorderThickness() + IconSize(), 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FrameBorderThickness() + kCaptionButtonHeightWithPadding) + 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TitlebarBottomThickness(); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::TitlebarBottomThickness() const { 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kTitlebarTopAndBottomEdgeThickness + 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (frame_->GetWindow()->IsMaximized() ? 0 : kClientEdgeThickness); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::IconSize() const { 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This metric scales up if either the titlebar height or the titlebar font 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // size are increased. 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetSystemMetrics(SM_CYSMICON); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return std::max(BrowserFrame::GetTitleFont().height(), kIconMinimumSize); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::IconBounds() const { 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int size = IconSize(); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int frame_thickness = FrameBorderThickness(); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Our frame border has a different "3D look" than Windows'. Theirs has a 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // more complex gradient on the top that they push their icon/title below; 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // then the maximized window cuts this off and the icon/title are centered 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in the remaining space. Because the apparent shape of our border is 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // simpler, using the same positioning makes things look slightly uncentered 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with restored windows, so when the window is restored, instead of 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // calculating the remaining space from below the frame border, we calculate 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from below the top border-plus-padding. 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int unavailable_px_at_top = frame_->GetWindow()->IsMaximized() ? 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_thickness : kTitlebarTopAndBottomEdgeThickness; 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the icon is shorter than the minimum space we reserve for the caption 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // button, we vertically center it. We want to bias rounding to put extra 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // space above the icon, since the 3D edge (+ client edge, for restored 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // windows) below looks (to the eye) more like additional space than does the 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // border + padding (or nothing at all, for maximized windows) above; hence 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the +1. 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int y = unavailable_px_at_top + (NonClientTopBorderHeight() - 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2; 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(frame_thickness + kIconLeftSpacing, y, size, size); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) { 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* top_left_corner = rb.GetBitmapNamed(IDR_WINDOW_TOP_LEFT_CORNER); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* top_right_corner = 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_WINDOW_TOP_RIGHT_CORNER); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* top_edge = rb.GetBitmapNamed(IDR_WINDOW_TOP_CENTER); 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* right_edge = rb.GetBitmapNamed(IDR_WINDOW_RIGHT_SIDE); 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* left_edge = rb.GetBitmapNamed(IDR_WINDOW_LEFT_SIDE); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* bottom_left_corner = 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* bottom_right_corner = 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* bottom_edge = rb.GetBitmapNamed(IDR_WINDOW_BOTTOM_CENTER); 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Window frame mode and color. 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* theme_frame; 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColor frame_color; 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ShouldPaintAsActive()) { 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_frame = rb.GetBitmapNamed(IDR_FRAME_APP_PANEL); 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_color = ResourceBundle::frame_color_app_panel; 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_frame = rb.GetBitmapNamed(IDR_FRAME_APP_PANEL); // TODO 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_color = ResourceBundle::frame_color_app_panel_inactive; 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fill with the frame color first so we have a constant background for 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // areas not covered by the theme image. 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->FillRectInt(frame_color, 0, 0, width(), theme_frame->height()); 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now fill down the sides. 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->FillRectInt(frame_color, 0, theme_frame->height(), left_edge->width(), 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - theme_frame->height()); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->FillRectInt(frame_color, width() - right_edge->width(), 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_frame->height(), right_edge->width(), 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - theme_frame->height()); 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now fill the bottom area. 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->FillRectInt(frame_color, left_edge->width(), 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - bottom_edge->height(), 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - left_edge->width() - right_edge->width(), 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bottom_edge->height()); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the theme frame. 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*theme_frame, 0, 0, width(), theme_frame->height()); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Top. 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*top_left_corner, 0, 0); 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*top_edge, top_left_corner->width(), 0, 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - top_right_corner->width(), top_edge->height()); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*top_right_corner, 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - top_right_corner->width(), 0); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Right. 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*right_edge, width() - right_edge->width(), 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch top_right_corner->height(), right_edge->width(), 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - top_right_corner->height() - bottom_right_corner->height()); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bottom. 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*bottom_right_corner, 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - bottom_right_corner->width(), 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - bottom_right_corner->height()); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*bottom_edge, bottom_left_corner->width(), 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - bottom_edge->height(), 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - bottom_left_corner->width() - bottom_right_corner->width(), 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bottom_edge->height()); 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*bottom_left_corner, 0, 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - bottom_left_corner->height()); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Left. 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*left_edge, 0, top_left_corner->height(), 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch left_edge->width(), 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - top_left_corner->height() - bottom_left_corner->height()); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) { 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* frame_image = rb.GetBitmapNamed(IDR_FRAME_APP_PANEL); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*frame_image, 0, FrameBorderThickness(), width(), 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_image->height()); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The bottom of the titlebar actually comes from the top of the Client Edge 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // graphic, with the actual client edge clipped off the bottom. 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* titlebar_bottom = rb.GetBitmapNamed(IDR_APP_TOP_CENTER); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int edge_height = titlebar_bottom->height() - kClientEdgeThickness; 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*titlebar_bottom, 0, 404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen frame_->GetWindow()->client_view()->y() - edge_height, 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width(), edge_height); 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintTitleBar(gfx::Canvas* canvas) { 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The window icon is painted by the TabIconView. 410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen views::WindowDelegate* d = frame_->GetWindow()->window_delegate(); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawStringInt(d->GetWindowTitle(), BrowserFrame::GetTitleFont(), 41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SK_ColorBLACK, GetMirroredXForRect(title_bounds_), title_bounds_.y(), 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_bounds_.width(), title_bounds_.height()); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height()); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int client_area_top = client_area_bounds.y(); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* top_left = rb.GetBitmapNamed(IDR_APP_TOP_LEFT); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* top = rb.GetBitmapNamed(IDR_APP_TOP_CENTER); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* top_right = rb.GetBitmapNamed(IDR_APP_TOP_RIGHT); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* right = rb.GetBitmapNamed(IDR_CONTENT_RIGHT_SIDE); 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* bottom_right = 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER); 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* bottom = rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_CENTER); 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* bottom_left = 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER); 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* left = rb.GetBitmapNamed(IDR_CONTENT_LEFT_SIDE); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Top. 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int top_edge_y = client_area_top - top->height(); 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*top_left, client_area_bounds.x() - top_left->width(), 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch top_edge_y); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*top, client_area_bounds.x(), top_edge_y, 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_bounds.width(), top->height()); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*top_right, client_area_bounds.right(), top_edge_y); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Right. 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int client_area_bottom = 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(client_area_top, client_area_bounds.bottom()); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int client_area_height = client_area_bottom - client_area_top; 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top, 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch right->width(), client_area_height); 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bottom. 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(), 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_bottom); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*bottom, client_area_bounds.x(), client_area_bottom, 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_bounds.width(), bottom_right->height()); 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*bottom_left, 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_bounds.x() - bottom_left->width(), client_area_bottom); 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Left. 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_top, left->width(), client_area_height); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw the toolbar color to fill in the edges. 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawRectInt(ResourceBundle::toolbar_color, 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_bounds.x() - kClientEdgeThickness, 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_top - kClientEdgeThickness, 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_bounds.width() + kClientEdgeThickness, 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_area_bottom - client_area_top + kClientEdgeThickness); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::LayoutWindowControls() { 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::ImageButton::ALIGN_BOTTOM); 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_maximized = frame_->GetWindow()->IsMaximized(); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There should always be the same number of non-border pixels visible to the 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // side of the close button. In maximized mode we extend the button to the 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // screen corner to obey Fitts' Law. 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int right_extra_width = is_maximized ? kCloseButtonFrameBorderSpacing : 0; 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size close_button_size = close_button_->GetPreferredSize(); 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int close_button_y = 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (NonClientTopBorderHeight() - close_button_size.height()) / 2; 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int top_extra_height = is_maximized ? close_button_y : 0; 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetBounds(width() - FrameBorderThickness() - 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCloseButtonFrameBorderSpacing - close_button_size.width(), 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_y - top_extra_height, 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_size.width() + right_extra_width, 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_size.height() + top_extra_height); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::LayoutTitleBar() { 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Size the icon first; the window title is based on the icon position. 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect icon_bounds(IconBounds()); 48972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen window_icon_->SetBoundsRect(icon_bounds); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Size the title. 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int title_x = icon_bounds.right() + kIconTitleSpacing; 4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int title_height = BrowserFrame::GetTitleFont().GetHeight(); 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We bias the title position so that when the difference between the icon 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and title heights is odd, the extra pixel of the title is above the 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // vertical midline rather than below. This compensates for how the icon is 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already biased downwards (see IconBounds()) and helps prevent descenders 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // on the title from overlapping the 3D edge at the bottom of the titlebar. 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_bounds_.SetRect(title_x, 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2), 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(0, close_button_->x() - kTitleCloseButtonSpacing - title_x), 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_height); 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::CalculateClientAreaBounds(int width, 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int height) const { 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int top_height = NonClientTopBorderHeight(); 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int border_thickness = NonClientBorderThickness(); 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(border_thickness, top_height, 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(0, width - (2 * border_thickness)), 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(0, height - top_height - border_thickness)); 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 513