app_window_frame_view.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Copyright 2014 The Chromium Authors. All rights reserved. 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Use of this source code is governed by a BSD-style license that can be 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// found in the LICENSE file. 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "apps/ui/views/app_window_frame_view.h" 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "base/strings/utf_string_conversions.h" 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "extensions/common/draggable_region.h" 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "grit/theme_resources.h" 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "grit/ui_strings.h" // Accessibility names 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "third_party/skia/include/core/SkPaint.h" 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "third_party/skia/include/core/SkRegion.h" 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/base/hit_test.h" 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/base/l10n/l10n_util.h" 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/base/resource/resource_bundle.h" 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/gfx/canvas.h" 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/gfx/image/image.h" 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/gfx/path.h" 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/views/controls/button/image_button.h" 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/views/layout/grid_layout.h" 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/views/views_delegate.h" 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/views/widget/widget.h" 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/views/widget/widget_delegate.h" 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#if defined(USE_AURA) 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/aura/env.h" 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "ui/aura/window.h" 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#endif 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksnamespace { 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// Height of the chrome-style caption, in pixels. 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksconst int kCaptionHeight = 25; 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} // namespace 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksnamespace apps { 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksconst char AppWindowFrameView::kViewClassName[] = 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "browser/ui/views/extensions/AppWindowFrameView"; 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin HendricksAppWindowFrameView::AppWindowFrameView() 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks : widget_(NULL), 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks draggable_region_(NULL), 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks close_button_(NULL), 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maximize_button_(NULL), 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks restore_button_(NULL), 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks minimize_button_(NULL), 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks resize_inside_bounds_size_(0), 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks resize_outside_bounds_size_(0), 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks resize_area_corner_size_(0) {} 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin HendricksAppWindowFrameView::~AppWindowFrameView() {} 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksvoid AppWindowFrameView::Init(views::Widget* widget, 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks bool draw_frame, 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const SkColor& frame_color, 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks const SkRegion* draggable_region, 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int resize_inside_bounds_size, 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int resize_outside_bounds_size, 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int resize_outside_scale_for_touch, 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks int resize_area_corner_size) { 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks widget_ = widget; 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks draw_frame_ = draw_frame; 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks frame_color_ = frame_color; 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks draggable_region_ = draggable_region; 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks resize_inside_bounds_size_ = resize_inside_bounds_size; 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks resize_outside_bounds_size_ = resize_outside_bounds_size; 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks resize_area_corner_size_ = resize_area_corner_size; 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (draw_frame) { 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks close_button_ = new views::ImageButton(this); 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks close_button_->SetImage( 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_NORMAL, 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE).ToImageSkia()); 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks close_button_->SetImage( 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_HOVERED, 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_H).ToImageSkia()); 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks close_button_->SetImage( 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_PRESSED, 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_P).ToImageSkia()); 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks close_button_->SetAccessibleName( 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks AddChildView(close_button_); 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maximize_button_ = new views::ImageButton(this); 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maximize_button_->SetImage( 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_NORMAL, 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE).ToImageSkia()); 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maximize_button_->SetImage( 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_HOVERED, 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_H).ToImageSkia()); 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maximize_button_->SetImage( 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_PRESSED, 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_P).ToImageSkia()); 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maximize_button_->SetImage( 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_DISABLED, 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_D).ToImageSkia()); 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maximize_button_->SetAccessibleName( 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE)); 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks AddChildView(maximize_button_); 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks restore_button_ = new views::ImageButton(this); 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks restore_button_->SetImage( 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_NORMAL, 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE).ToImageSkia()); 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks restore_button_->SetImage( 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_HOVERED, 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE_H).ToImageSkia()); 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks restore_button_->SetImage( 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_PRESSED, 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE_P).ToImageSkia()); 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks restore_button_->SetAccessibleName( 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks l10n_util::GetStringUTF16(IDS_APP_ACCNAME_RESTORE)); 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks AddChildView(restore_button_); 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks minimize_button_ = new views::ImageButton(this); 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks minimize_button_->SetImage( 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks views::CustomButton::STATE_NORMAL, 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE).ToImageSkia()); 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks minimize_button_->SetImage( 118 views::CustomButton::STATE_HOVERED, 119 rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE_H).ToImageSkia()); 120 minimize_button_->SetImage( 121 views::CustomButton::STATE_PRESSED, 122 rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE_P).ToImageSkia()); 123 minimize_button_->SetAccessibleName( 124 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE)); 125 AddChildView(minimize_button_); 126 } 127} 128 129// views::NonClientFrameView implementation. 130 131gfx::Rect AppWindowFrameView::GetBoundsForClientView() const { 132 if (!draw_frame_ || widget_->IsFullscreen()) 133 return bounds(); 134 return gfx::Rect( 135 0, kCaptionHeight, width(), std::max(0, height() - kCaptionHeight)); 136} 137 138gfx::Rect AppWindowFrameView::GetWindowBoundsForClientBounds( 139 const gfx::Rect& client_bounds) const { 140 gfx::Rect window_bounds = client_bounds; 141#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 142 // Get the difference between the widget's client area bounds and window 143 // bounds, and grow |window_bounds| by that amount. 144 gfx::Insets native_frame_insets = 145 widget_->GetClientAreaBoundsInScreen().InsetsFrom( 146 widget_->GetWindowBoundsInScreen()); 147 window_bounds.Inset(native_frame_insets); 148#endif 149 if (!draw_frame_) { 150 // Enforce minimum size (1, 1) in case that client_bounds is passed with 151 // empty size. This could occur when the frameless window is being 152 // initialized. 153 if (window_bounds.IsEmpty()) { 154 window_bounds.set_width(1); 155 window_bounds.set_height(1); 156 } 157 return window_bounds; 158 } 159 160 int closeButtonOffsetX = (kCaptionHeight - close_button_->height()) / 2; 161 int header_width = close_button_->width() + closeButtonOffsetX * 2; 162 return gfx::Rect(window_bounds.x(), 163 window_bounds.y() - kCaptionHeight, 164 std::max(header_width, window_bounds.width()), 165 window_bounds.height() + kCaptionHeight); 166} 167 168int AppWindowFrameView::NonClientHitTest(const gfx::Point& point) { 169 if (widget_->IsFullscreen()) 170 return HTCLIENT; 171 172 gfx::Rect expanded_bounds = bounds(); 173 if (resize_outside_bounds_size_) { 174 expanded_bounds.Inset(gfx::Insets(-resize_outside_bounds_size_, 175 -resize_outside_bounds_size_, 176 -resize_outside_bounds_size_, 177 -resize_outside_bounds_size_)); 178 } 179 // Points outside the (possibly expanded) bounds can be discarded. 180 if (!expanded_bounds.Contains(point)) 181 return HTNOWHERE; 182 183 // Check the frame first, as we allow a small area overlapping the contents 184 // to be used for resize handles. 185 bool can_ever_resize = widget_->widget_delegate() 186 ? widget_->widget_delegate()->CanResize() 187 : false; 188 // Don't allow overlapping resize handles when the window is maximized or 189 // fullscreen, as it can't be resized in those states. 190 int resize_border = (widget_->IsMaximized() || widget_->IsFullscreen()) 191 ? 0 192 : resize_inside_bounds_size_; 193 int frame_component = GetHTComponentForFrame(point, 194 resize_border, 195 resize_border, 196 resize_area_corner_size_, 197 resize_area_corner_size_, 198 can_ever_resize); 199 if (frame_component != HTNOWHERE) 200 return frame_component; 201 202 // Check for possible draggable region in the client area for the frameless 203 // window. 204 if (draggable_region_ && draggable_region_->contains(point.x(), point.y())) 205 return HTCAPTION; 206 207 int client_component = widget_->client_view()->NonClientHitTest(point); 208 if (client_component != HTNOWHERE) 209 return client_component; 210 211 // Then see if the point is within any of the window controls. 212 if (close_button_ && close_button_->visible() && 213 close_button_->GetMirroredBounds().Contains(point)) { 214 return HTCLOSE; 215 } 216 if ((maximize_button_ && maximize_button_->visible() && 217 maximize_button_->GetMirroredBounds().Contains(point)) || 218 (restore_button_ && restore_button_->visible() && 219 restore_button_->GetMirroredBounds().Contains(point))) { 220 return HTMAXBUTTON; 221 } 222 if (minimize_button_ && minimize_button_->visible() && 223 minimize_button_->GetMirroredBounds().Contains(point)) { 224 return HTMINBUTTON; 225 } 226 227 // Caption is a safe default. 228 return HTCAPTION; 229} 230 231void AppWindowFrameView::GetWindowMask(const gfx::Size& size, 232 gfx::Path* window_mask) { 233 // We got nothing to say about no window mask. 234} 235 236// views::View implementation. 237 238gfx::Size AppWindowFrameView::GetPreferredSize() { 239 gfx::Size pref = widget_->client_view()->GetPreferredSize(); 240 gfx::Rect bounds(0, 0, pref.width(), pref.height()); 241 return widget_->non_client_view() 242 ->GetWindowBoundsForClientBounds(bounds) 243 .size(); 244} 245 246void AppWindowFrameView::Layout() { 247 if (!draw_frame_) 248 return; 249 gfx::Size close_size = close_button_->GetPreferredSize(); 250 const int kButtonOffsetY = 0; 251 const int kButtonSpacing = 1; 252 const int kRightMargin = 3; 253 254 close_button_->SetBounds(width() - kRightMargin - close_size.width(), 255 kButtonOffsetY, 256 close_size.width(), 257 close_size.height()); 258 259 bool can_ever_resize = widget_->widget_delegate() 260 ? widget_->widget_delegate()->CanResize() 261 : false; 262 maximize_button_->SetEnabled(can_ever_resize); 263 gfx::Size maximize_size = maximize_button_->GetPreferredSize(); 264 maximize_button_->SetBounds( 265 close_button_->x() - kButtonSpacing - maximize_size.width(), 266 kButtonOffsetY, 267 maximize_size.width(), 268 maximize_size.height()); 269 gfx::Size restore_size = restore_button_->GetPreferredSize(); 270 restore_button_->SetBounds( 271 close_button_->x() - kButtonSpacing - restore_size.width(), 272 kButtonOffsetY, 273 restore_size.width(), 274 restore_size.height()); 275 276 bool maximized = widget_->IsMaximized(); 277 maximize_button_->SetVisible(!maximized); 278 restore_button_->SetVisible(maximized); 279 if (maximized) 280 maximize_button_->SetState(views::CustomButton::STATE_NORMAL); 281 else 282 restore_button_->SetState(views::CustomButton::STATE_NORMAL); 283 284 gfx::Size minimize_size = minimize_button_->GetPreferredSize(); 285 minimize_button_->SetState(views::CustomButton::STATE_NORMAL); 286 minimize_button_->SetBounds( 287 maximize_button_->x() - kButtonSpacing - minimize_size.width(), 288 kButtonOffsetY, 289 minimize_size.width(), 290 minimize_size.height()); 291} 292 293void AppWindowFrameView::OnPaint(gfx::Canvas* canvas) { 294 if (!draw_frame_) 295 return; 296 297 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 298 if (ShouldPaintAsActive()) { 299 close_button_->SetImage( 300 views::CustomButton::STATE_NORMAL, 301 rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE).ToImageSkia()); 302 } else { 303 close_button_->SetImage( 304 views::CustomButton::STATE_NORMAL, 305 rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_U).ToImageSkia()); 306 } 307 308 // TODO(jeremya): different look for inactive? 309 SkPaint paint; 310 paint.setAntiAlias(false); 311 paint.setStyle(SkPaint::kFill_Style); 312 paint.setColor(frame_color_); 313 gfx::Path path; 314 path.moveTo(0, 0); 315 path.lineTo(width(), 0); 316 path.lineTo(width(), kCaptionHeight); 317 path.lineTo(0, kCaptionHeight); 318 path.close(); 319 canvas->DrawPath(path, paint); 320} 321 322const char* AppWindowFrameView::GetClassName() const { return kViewClassName; } 323 324gfx::Size AppWindowFrameView::GetMinimumSize() { 325 gfx::Size min_size = widget_->client_view()->GetMinimumSize(); 326 if (!draw_frame_) 327 return min_size; 328 329 // Ensure we can display the top of the caption area. 330 gfx::Rect client_bounds = GetBoundsForClientView(); 331 min_size.Enlarge(0, client_bounds.y()); 332 // Ensure we have enough space for the window icon and buttons. We allow 333 // the title string to collapse to zero width. 334 int closeButtonOffsetX = (kCaptionHeight - close_button_->height()) / 2; 335 int header_width = close_button_->width() + closeButtonOffsetX * 2; 336 if (header_width > min_size.width()) 337 min_size.set_width(header_width); 338 return min_size; 339} 340 341gfx::Size AppWindowFrameView::GetMaximumSize() { 342 gfx::Size max_size = widget_->client_view()->GetMaximumSize(); 343 344 // Add to the client maximum size the height of any title bar and borders. 345 gfx::Size client_size = GetBoundsForClientView().size(); 346 if (max_size.width()) 347 max_size.Enlarge(width() - client_size.width(), 0); 348 if (max_size.height()) 349 max_size.Enlarge(0, height() - client_size.height()); 350 351 return max_size; 352} 353 354// views::ButtonListener implementation. 355 356void AppWindowFrameView::ButtonPressed(views::Button* sender, 357 const ui::Event& event) { 358 DCHECK(draw_frame_); 359 if (sender == close_button_) 360 widget_->Close(); 361 else if (sender == maximize_button_) 362 widget_->Maximize(); 363 else if (sender == restore_button_) 364 widget_->Restore(); 365 else if (sender == minimize_button_) 366 widget_->Minimize(); 367} 368 369} // namespace apps 370