| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/views/custom_frame_window.h" | 5 #include "chrome/views/custom_frame_window.h" |
| 6 | 6 |
| 7 #include "base/gfx/point.h" | 7 #include "base/gfx/point.h" |
| 8 #include "base/gfx/size.h" | 8 #include "base/gfx/size.h" |
| 9 #include "base/win_util.h" | 9 #include "base/win_util.h" |
| 10 #include "chrome/app/theme/theme_resources.h" | 10 #include "chrome/app/theme/theme_resources.h" |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 | 209 |
| 210 static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; | 210 static SkBitmap* standard_frame_bitmaps_[FRAME_PART_BITMAP_COUNT]; |
| 211 | 211 |
| 212 DISALLOW_EVIL_CONSTRUCTORS(InactiveWindowResources); | 212 DISALLOW_EVIL_CONSTRUCTORS(InactiveWindowResources); |
| 213 }; | 213 }; |
| 214 | 214 |
| 215 // static | 215 // static |
| 216 SkBitmap* ActiveWindowResources::standard_frame_bitmaps_[]; | 216 SkBitmap* ActiveWindowResources::standard_frame_bitmaps_[]; |
| 217 SkBitmap* InactiveWindowResources::standard_frame_bitmaps_[]; | 217 SkBitmap* InactiveWindowResources::standard_frame_bitmaps_[]; |
| 218 | 218 |
| 219 | |
| 220 /////////////////////////////////////////////////////////////////////////////// | 219 /////////////////////////////////////////////////////////////////////////////// |
| 221 // | 220 // |
| 222 // DefaultNonClientView | 221 // DefaultNonClientView |
| 223 // | 222 // |
| 224 // A ChromeView that provides the "frame" for CustomFrameWindows. This means | 223 // A ChromeView that provides the "frame" for CustomFrameWindows. This means |
| 225 // rendering the non-standard window caption, border, and controls. | 224 // rendering the non-standard window caption, border, and controls. |
| 226 // | 225 // |
| 227 //////////////////////////////////////////////////////////////////////////////// | 226 //////////////////////////////////////////////////////////////////////////////// |
| 228 class DefaultNonClientView : public NonClientView, | 227 class DefaultNonClientView : public NonClientView, |
| 229 public BaseButton::ButtonListener { | 228 public BaseButton::ButtonListener { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 244 // View overrides: | 243 // View overrides: |
| 245 virtual void Paint(ChromeCanvas* canvas); | 244 virtual void Paint(ChromeCanvas* canvas); |
| 246 virtual void Layout(); | 245 virtual void Layout(); |
| 247 virtual gfx::Size GetPreferredSize(); | 246 virtual gfx::Size GetPreferredSize(); |
| 248 virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); | 247 virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); |
| 249 | 248 |
| 250 // BaseButton::ButtonListener implementation: | 249 // BaseButton::ButtonListener implementation: |
| 251 virtual void ButtonPressed(BaseButton* sender); | 250 virtual void ButtonPressed(BaseButton* sender); |
| 252 | 251 |
| 253 private: | 252 private: |
| 254 // Updates the system menu icon button. | 253 // Returns the thickness of the border that makes up the window frame edges. |
| 255 void SetWindowIcon(SkBitmap window_icon); | 254 // This does not include any client edge. |
| 255 int FrameBorderThickness() const; |
| 256 |
| 257 // Returns the thickness of the entire nonclient left, right, and bottom |
| 258 // borders, including both the window frame and any client edge. |
| 259 int NonClientBorderThickness() const; |
| 256 | 260 |
| 257 // Returns the height of the entire nonclient top border, including the window | 261 // Returns the height of the entire nonclient top border, including the window |
| 258 // frame, any title area, and any connected client edge. | 262 // frame, any title area, and any connected client edge. |
| 259 int NonClientTopBorderHeight() const; | 263 int NonClientTopBorderHeight() const; |
| 260 | 264 |
| 265 // A bottom border, and, in restored mode, a client edge are drawn at the |
| 266 // bottom of the titlebar. This returns the total height drawn. |
| 267 int BottomEdgeThicknessWithinNonClientHeight() const; |
| 268 |
| 269 // Calculates multiple values related to title layout. Returns the height of |
| 270 // the entire titlebar including any connected client edge. |
| 271 int TitleCoordinates(int* title_top_spacing, |
| 272 int* title_thickness) const; |
| 273 |
| 261 // Paint various sub-components of this view. | 274 // Paint various sub-components of this view. |
| 262 void PaintRestoredFrameBorder(ChromeCanvas* canvas); | 275 void PaintRestoredFrameBorder(ChromeCanvas* canvas); |
| 263 void PaintMaximizedFrameBorder(ChromeCanvas* canvas); | 276 void PaintMaximizedFrameBorder(ChromeCanvas* canvas); |
| 264 void PaintTitleBar(ChromeCanvas* canvas); | 277 void PaintTitleBar(ChromeCanvas* canvas); |
| 265 void PaintClientEdge(ChromeCanvas* canvas); | 278 void PaintRestoredClientEdge(ChromeCanvas* canvas); |
| 266 | 279 |
| 267 // Layout various sub-components of this view. | 280 // Layout various sub-components of this view. |
| 268 void LayoutWindowControls(); | 281 void LayoutWindowControls(); |
| 269 void LayoutTitleBar(); | 282 void LayoutTitleBar(); |
| 270 void LayoutClientView(); | 283 void LayoutClientView(); |
| 271 | 284 |
| 272 // Returns the resource collection to be used when rendering the window. | 285 // Returns the resource collection to be used when rendering the window. |
| 273 WindowResources* resources() const { | 286 WindowResources* resources() const { |
| 274 return container_->is_active() || paint_as_active() ? active_resources_ | 287 return container_->is_active() || paint_as_active() ? active_resources_ |
| 275 : inactive_resources_; | 288 : inactive_resources_; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 300 static WindowResources* inactive_resources_; | 313 static WindowResources* inactive_resources_; |
| 301 static ChromeFont title_font_; | 314 static ChromeFont title_font_; |
| 302 | 315 |
| 303 DISALLOW_EVIL_CONSTRUCTORS(DefaultNonClientView); | 316 DISALLOW_EVIL_CONSTRUCTORS(DefaultNonClientView); |
| 304 }; | 317 }; |
| 305 | 318 |
| 306 // static | 319 // static |
| 307 WindowResources* DefaultNonClientView::active_resources_ = NULL; | 320 WindowResources* DefaultNonClientView::active_resources_ = NULL; |
| 308 WindowResources* DefaultNonClientView::inactive_resources_ = NULL; | 321 WindowResources* DefaultNonClientView::inactive_resources_ = NULL; |
| 309 ChromeFont DefaultNonClientView::title_font_; | 322 ChromeFont DefaultNonClientView::title_font_; |
| 310 static const int kWindowControlsTopOffset = 1; | 323 |
| 311 static const int kWindowControlsRightOffset = 5; | 324 namespace { |
| 312 static const int kWindowControlsTopZoomedOffset = 1; | 325 // The frame border is only visible in restored mode and is hardcoded to 4 px on |
| 313 static const int kWindowControlsRightZoomedOffset = 5; | 326 // each side regardless of the system window border size. |
| 314 static const int kWindowTopMarginZoomed = 1; | 327 const int kFrameBorderThickness = 4; |
| 315 static const int kWindowIconLeftOffset = 5; | 328 // Various edges of the frame border have a 1 px shadow along their edges; in a |
| 316 static const int kWindowIconTopOffset = 5; | 329 // few cases we shift elements based on this amount for visual appeal. |
| 317 static const int kTitleTopOffset = 6; | 330 const int kFrameShadowThickness = 1; |
| 318 static const int kWindowIconTitleSpacing = 3; | 331 // While resize areas on Windows are normally the same size as the window |
| 319 static const int kTitleBottomSpacing = 6; | 332 // borders, our top area is shrunk by 1 px to make it easier to move the window |
| 320 static const int kNoTitleTopSpacing = 8; | 333 // around with our thinner top grabbable strip. (Incidentally, our side and |
| 321 static const int kResizeAreaSize = 5; | 334 // bottom resize areas don't match the frame border thickness either -- they |
| 322 static const int kResizeAreaNorthSize = 3; | 335 // span the whole nonclient area, so there's no "dead zone" for the mouse.) |
| 323 static const int kResizeAreaCornerSize = 16; | 336 const int kTopResizeAdjust = 1; |
| 324 static const int kWindowHorizontalBorderSize = 4; | 337 // In the window corners, the resize areas don't actually expand bigger, but the |
| 325 static const int kWindowVerticalBorderSize = 4; | 338 // 16 px at the end of each edge triggers diagonal resizing. |
| 339 const int kResizeAreaCornerSize = 16; |
| 340 // The titlebar never shrinks to less than 18 px tall, plus the height of the |
| 341 // frame border and any bottom edge. |
| 342 const int kTitlebarMinimumHeight = 18; |
| 343 // The icon is inset 2 px from the left frame border. |
| 344 const int kIconLeftSpacing = 2; |
| 345 // The icon takes up 16/25th of the available titlebar height. (This is |
| 346 // expressed as two ints to avoid precision losses leading to off-by-one pixel |
| 347 // errors.) |
| 348 const int kIconHeightFractionNumerator = 16; |
| 349 const int kIconHeightFractionDenominator = 25; |
| 350 // The icon never shrinks below 16 px on a side. |
| 351 const int kIconMinimumSize = 16; |
| 352 // Because our frame border has a different "3D look" than Windows', with a less |
| 353 // cluttered top edge, we need to shift the icon up by 1 px in restored mode so |
| 354 // it looks more centered. |
| 355 const int kIconRestoredAdjust = 1; |
| 356 // There is a 4 px gap between the icon and the title text. |
| 357 const int kIconTitleSpacing = 4; |
| 358 // The title text starts 2 px below the bottom of the top frame border. |
| 359 const int kTitleTopSpacing = 2; |
| 360 // There is a 5 px gap between the title text and the caption buttons. |
| 361 const int kTitleCaptionSpacing = 5; |
| 362 // The caption buttons are always drawn 1 px down from the visible top of the |
| 363 // window (the true top in restored mode, or the top of the screen in maximized |
| 364 // mode). |
| 365 const int kCaptionTopSpacing = 1; |
| 366 } |
| 326 | 367 |
| 327 /////////////////////////////////////////////////////////////////////////////// | 368 /////////////////////////////////////////////////////////////////////////////// |
| 328 // DefaultNonClientView, public: | 369 // DefaultNonClientView, public: |
| 329 | 370 |
| 330 DefaultNonClientView::DefaultNonClientView( | 371 DefaultNonClientView::DefaultNonClientView( |
| 331 CustomFrameWindow* container) | 372 CustomFrameWindow* container) |
| 332 : NonClientView(), | 373 : NonClientView(), |
| 333 client_view_(NULL), | 374 client_view_(NULL), |
| 334 close_button_(new Button), | 375 close_button_(new Button), |
| 335 restore_button_(new Button), | 376 restore_button_(new Button), |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 | 420 |
| 380 DefaultNonClientView::~DefaultNonClientView() { | 421 DefaultNonClientView::~DefaultNonClientView() { |
| 381 } | 422 } |
| 382 | 423 |
| 383 /////////////////////////////////////////////////////////////////////////////// | 424 /////////////////////////////////////////////////////////////////////////////// |
| 384 // DefaultNonClientView, CustomFrameWindow::NonClientView implementation: | 425 // DefaultNonClientView, CustomFrameWindow::NonClientView implementation: |
| 385 | 426 |
| 386 gfx::Rect DefaultNonClientView::CalculateClientAreaBounds(int width, | 427 gfx::Rect DefaultNonClientView::CalculateClientAreaBounds(int width, |
| 387 int height) const { | 428 int height) const { |
| 388 int top_height = NonClientTopBorderHeight(); | 429 int top_height = NonClientTopBorderHeight(); |
| 389 int border_thickness = kWindowHorizontalBorderSize; | 430 int border_thickness = NonClientBorderThickness(); |
| 390 return gfx::Rect(border_thickness, top_height, | 431 return gfx::Rect(border_thickness, top_height, |
| 391 std::max(0, width - (2 * border_thickness)), | 432 std::max(0, width - (2 * border_thickness)), |
| 392 std::max(0, height - top_height - kWindowVerticalBorderSize)); | 433 std::max(0, height - top_height - border_thickness)); |
| 393 } | 434 } |
| 394 | 435 |
| 395 gfx::Size DefaultNonClientView::CalculateWindowSizeForClientSize( | 436 gfx::Size DefaultNonClientView::CalculateWindowSizeForClientSize( |
| 396 int width, | 437 int width, |
| 397 int height) const { | 438 int height) const { |
| 398 return gfx::Size(width + (2 * kWindowHorizontalBorderSize), | 439 int border_thickness = NonClientBorderThickness(); |
| 399 height + NonClientTopBorderHeight() + kWindowVerticalBorderSize); | 440 return gfx::Size(width + (2 * border_thickness), |
| 441 height + NonClientTopBorderHeight() + border_thickness); |
| 400 } | 442 } |
| 401 | 443 |
| 402 CPoint DefaultNonClientView::GetSystemMenuPoint() const { | 444 CPoint DefaultNonClientView::GetSystemMenuPoint() const { |
| 403 // TODO(pkasting): This is wrong; Windows native runs the menu at the bottom | 445 // TODO(pkasting): This is wrong; Windows native runs the menu at the bottom |
| 404 // of the titlebar, not the bottom of the window icon. | 446 // of the titlebar, not the bottom of the window icon. |
| 405 CPoint system_menu_point(system_menu_button_->x(), | 447 CPoint system_menu_point(system_menu_button_->x(), |
| 406 system_menu_button_->y() + system_menu_button_->height()); | 448 system_menu_button_->y() + system_menu_button_->height()); |
| 407 MapWindowPoints(container_->GetHWND(), HWND_DESKTOP, &system_menu_point, 1); | 449 MapWindowPoints(container_->GetHWND(), HWND_DESKTOP, &system_menu_point, 1); |
| 408 return system_menu_point; | 450 return system_menu_point; |
| 409 } | 451 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 424 if (maximize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( | 466 if (maximize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( |
| 425 point)) | 467 point)) |
| 426 return HTMAXBUTTON; | 468 return HTMAXBUTTON; |
| 427 if (minimize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( | 469 if (minimize_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( |
| 428 point)) | 470 point)) |
| 429 return HTMINBUTTON; | 471 return HTMINBUTTON; |
| 430 if (system_menu_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( | 472 if (system_menu_button_->GetBounds(APPLY_MIRRORING_TRANSFORMATION).Contains( |
| 431 point)) | 473 point)) |
| 432 return HTSYSMENU; | 474 return HTSYSMENU; |
| 433 | 475 |
| 434 int window_component = GetHTComponentForFrame(point, kResizeAreaNorthSize, | 476 int window_component = GetHTComponentForFrame(point, FrameBorderThickness(), |
| 435 kResizeAreaSize, kResizeAreaCornerSize, | 477 NonClientBorderThickness(), kResizeAreaCornerSize, |
| 436 container_->window_delegate()->CanResize()); | 478 container_->window_delegate()->CanResize()); |
| 437 // Fall back to the caption if no other component matches. | 479 // Fall back to the caption if no other component matches. |
| 438 return ((window_component == HTNOWHERE) && bounds().Contains(point)) ? | 480 return ((window_component == HTNOWHERE) && bounds().Contains(point)) ? |
| 439 HTCAPTION : window_component; | 481 HTCAPTION : window_component; |
| 440 } | 482 } |
| 441 | 483 |
| 442 void DefaultNonClientView::GetWindowMask(const gfx::Size& size, | 484 void DefaultNonClientView::GetWindowMask(const gfx::Size& size, |
| 443 gfx::Path* window_mask) { | 485 gfx::Path* window_mask) { |
| 444 DCHECK(window_mask); | 486 DCHECK(window_mask); |
| 445 | 487 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 475 | 517 |
| 476 /////////////////////////////////////////////////////////////////////////////// | 518 /////////////////////////////////////////////////////////////////////////////// |
| 477 // DefaultNonClientView, View overrides: | 519 // DefaultNonClientView, View overrides: |
| 478 | 520 |
| 479 void DefaultNonClientView::Paint(ChromeCanvas* canvas) { | 521 void DefaultNonClientView::Paint(ChromeCanvas* canvas) { |
| 480 if (container_->IsMaximized()) | 522 if (container_->IsMaximized()) |
| 481 PaintMaximizedFrameBorder(canvas); | 523 PaintMaximizedFrameBorder(canvas); |
| 482 else | 524 else |
| 483 PaintRestoredFrameBorder(canvas); | 525 PaintRestoredFrameBorder(canvas); |
| 484 PaintTitleBar(canvas); | 526 PaintTitleBar(canvas); |
| 485 PaintClientEdge(canvas); | 527 if (!container_->IsMaximized()) |
| 528 PaintRestoredClientEdge(canvas); |
| 486 } | 529 } |
| 487 | 530 |
| 488 void DefaultNonClientView::Layout() { | 531 void DefaultNonClientView::Layout() { |
| 489 LayoutWindowControls(); | 532 LayoutWindowControls(); |
| 490 LayoutTitleBar(); | 533 LayoutTitleBar(); |
| 491 LayoutClientView(); | 534 LayoutClientView(); |
| 492 } | 535 } |
| 493 | 536 |
| 494 gfx::Size DefaultNonClientView::GetPreferredSize() { | 537 gfx::Size DefaultNonClientView::GetPreferredSize() { |
| 495 gfx::Size prefsize(container_->client_view()->GetPreferredSize()); | 538 gfx::Size prefsize(container_->client_view()->GetPreferredSize()); |
| 496 prefsize.Enlarge(2 * kWindowHorizontalBorderSize, | 539 int border_thickness = NonClientBorderThickness(); |
| 497 NonClientTopBorderHeight() + kWindowVerticalBorderSize); | 540 prefsize.Enlarge(2 * border_thickness, |
| 541 NonClientTopBorderHeight() + border_thickness); |
| 498 return prefsize; | 542 return prefsize; |
| 499 } | 543 } |
| 500 | 544 |
| 501 void DefaultNonClientView::ViewHierarchyChanged(bool is_add, | 545 void DefaultNonClientView::ViewHierarchyChanged(bool is_add, |
| 502 View* parent, | 546 View* parent, |
| 503 View* child) { | 547 View* child) { |
| 504 // Add our Client View as we are added to the Widget so that if we are | 548 // Add our Client View as we are added to the Widget so that if we are |
| 505 // subsequently resized all the parent-child relationships are established. | 549 // subsequently resized all the parent-child relationships are established. |
| 506 if (is_add && GetWidget() && child == this) | 550 if (is_add && GetWidget() && child == this) |
| 507 AddChildView(container_->client_view()); | 551 AddChildView(container_->client_view()); |
| 508 } | 552 } |
| 509 | 553 |
| 510 /////////////////////////////////////////////////////////////////////////////// | 554 /////////////////////////////////////////////////////////////////////////////// |
| 511 // DefaultNonClientView, BaseButton::ButtonListener implementation: | 555 // DefaultNonClientView, BaseButton::ButtonListener implementation: |
| 512 | 556 |
| 513 void DefaultNonClientView::ButtonPressed(BaseButton* sender) { | 557 void DefaultNonClientView::ButtonPressed(BaseButton* sender) { |
| 514 if (sender == close_button_) | 558 if (sender == close_button_) |
| 515 container_->ExecuteSystemMenuCommand(SC_CLOSE); | 559 container_->ExecuteSystemMenuCommand(SC_CLOSE); |
| 516 else if (sender == minimize_button_) | 560 else if (sender == minimize_button_) |
| 517 container_->ExecuteSystemMenuCommand(SC_MINIMIZE); | 561 container_->ExecuteSystemMenuCommand(SC_MINIMIZE); |
| 518 else if (sender == maximize_button_) | 562 else if (sender == maximize_button_) |
| 519 container_->ExecuteSystemMenuCommand(SC_MAXIMIZE); | 563 container_->ExecuteSystemMenuCommand(SC_MAXIMIZE); |
| 520 else if (sender == restore_button_) | 564 else if (sender == restore_button_) |
| 521 container_->ExecuteSystemMenuCommand(SC_RESTORE); | 565 container_->ExecuteSystemMenuCommand(SC_RESTORE); |
| 522 } | 566 } |
| 523 | 567 |
| 524 /////////////////////////////////////////////////////////////////////////////// | 568 /////////////////////////////////////////////////////////////////////////////// |
| 525 // DefaultNonClientView, private: | 569 // DefaultNonClientView, private: |
| 526 | 570 |
| 571 int DefaultNonClientView::FrameBorderThickness() const { |
| 572 return container_->IsMaximized() ? |
| 573 GetSystemMetrics(SM_CXSIZEFRAME) : kFrameBorderThickness; |
| 574 } |
| 575 |
| 576 int DefaultNonClientView::NonClientBorderThickness() const { |
| 577 // In maximized mode, we don't show a client edge. |
| 578 return FrameBorderThickness() + |
| 579 (container_->IsMaximized() ? 0 : kClientEdgeThickness); |
| 580 } |
| 581 |
| 527 int DefaultNonClientView::NonClientTopBorderHeight() const { | 582 int DefaultNonClientView::NonClientTopBorderHeight() const { |
| 528 return kTitleTopOffset + title_font_.height() + kTitleBottomSpacing; | 583 int title_top_spacing, title_thickness; |
| 584 return TitleCoordinates(&title_top_spacing, &title_thickness); |
| 585 } |
| 586 |
| 587 int DefaultNonClientView::BottomEdgeThicknessWithinNonClientHeight() const { |
| 588 return kFrameShadowThickness + |
| 589 (container_->IsMaximized() ? 0 : kClientEdgeThickness); |
| 590 } |
| 591 |
| 592 int DefaultNonClientView::TitleCoordinates(int* title_top_spacing, |
| 593 int* title_thickness) const { |
| 594 int frame_thickness = FrameBorderThickness(); |
| 595 int min_titlebar_height = kTitlebarMinimumHeight + frame_thickness; |
| 596 *title_top_spacing = frame_thickness + kTitleTopSpacing; |
| 597 // The bottom spacing should be the same apparent height as the top spacing. |
| 598 // Because the actual top spacing height varies based on the system border |
| 599 // thickness, we calculate this based on the restored top spacing and then |
| 600 // adjust for maximized mode. We also don't include the frame shadow here, |
| 601 // since while it's part of the bottom spacing it will be added in at the end. |
| 602 int title_bottom_spacing = |
| 603 kFrameBorderThickness + kTitleTopSpacing - kFrameShadowThickness; |
| 604 if (container_->IsMaximized()) { |
| 605 // When we maximize, the top border appears to be chopped off; shift the |
| 606 // title down to stay centered within the remaining space. |
| 607 int title_adjust = (kFrameBorderThickness / 2); |
| 608 *title_top_spacing += title_adjust; |
| 609 title_bottom_spacing -= title_adjust; |
| 610 } |
| 611 *title_thickness = std::max(title_font_.height(), |
| 612 min_titlebar_height - *title_top_spacing - title_bottom_spacing); |
| 613 return *title_top_spacing + *title_thickness + title_bottom_spacing + |
| 614 BottomEdgeThicknessWithinNonClientHeight(); |
| 529 } | 615 } |
| 530 | 616 |
| 531 void DefaultNonClientView::PaintRestoredFrameBorder(ChromeCanvas* canvas) { | 617 void DefaultNonClientView::PaintRestoredFrameBorder(ChromeCanvas* canvas) { |
| 532 SkBitmap* top_left_corner = resources()->GetPartBitmap(FRAME_TOP_LEFT_CORNER); | 618 SkBitmap* top_left_corner = resources()->GetPartBitmap(FRAME_TOP_LEFT_CORNER); |
| 533 SkBitmap* top_right_corner = | 619 SkBitmap* top_right_corner = |
| 534 resources()->GetPartBitmap(FRAME_TOP_RIGHT_CORNER); | 620 resources()->GetPartBitmap(FRAME_TOP_RIGHT_CORNER); |
| 535 SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); | 621 SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); |
| 536 SkBitmap* right_edge = resources()->GetPartBitmap(FRAME_RIGHT_EDGE); | 622 SkBitmap* right_edge = resources()->GetPartBitmap(FRAME_RIGHT_EDGE); |
| 537 SkBitmap* left_edge = resources()->GetPartBitmap(FRAME_LEFT_EDGE); | 623 SkBitmap* left_edge = resources()->GetPartBitmap(FRAME_LEFT_EDGE); |
| 538 SkBitmap* bottom_left_corner = | 624 SkBitmap* bottom_left_corner = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 568 | 654 |
| 569 // Left. | 655 // Left. |
| 570 canvas->TileImageInt(*left_edge, 0, top_left_corner->height(), | 656 canvas->TileImageInt(*left_edge, 0, top_left_corner->height(), |
| 571 left_edge->width(), | 657 left_edge->width(), |
| 572 height() - top_left_corner->height() - bottom_left_corner->height()); | 658 height() - top_left_corner->height() - bottom_left_corner->height()); |
| 573 } | 659 } |
| 574 | 660 |
| 575 void DefaultNonClientView::PaintMaximizedFrameBorder( | 661 void DefaultNonClientView::PaintMaximizedFrameBorder( |
| 576 ChromeCanvas* canvas) { | 662 ChromeCanvas* canvas) { |
| 577 SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); | 663 SkBitmap* top_edge = resources()->GetPartBitmap(FRAME_TOP_EDGE); |
| 578 canvas->TileImageInt(*top_edge, 0, 0, width(), top_edge->height()); | 664 canvas->TileImageInt(*top_edge, 0, FrameBorderThickness(), width(), |
| 665 top_edge->height()); |
| 666 |
| 667 // The bottom of the titlebar actually comes from the top of the Client Edge |
| 668 // graphic, with the actual client edge clipped off the bottom. |
| 669 SkBitmap* titlebar_bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); |
| 670 int edge_height = titlebar_bottom->height() - kClientEdgeThickness; |
| 671 canvas->TileImageInt(*titlebar_bottom, 0, |
| 672 container_->client_view()->y() - edge_height, width(), edge_height); |
| 579 } | 673 } |
| 580 | 674 |
| 581 void DefaultNonClientView::PaintTitleBar(ChromeCanvas* canvas) { | 675 void DefaultNonClientView::PaintTitleBar(ChromeCanvas* canvas) { |
| 582 WindowDelegate* d = container_->window_delegate(); | 676 WindowDelegate* d = container_->window_delegate(); |
| 583 canvas->DrawStringInt(d->GetWindowTitle(), title_font_, SK_ColorWHITE, | 677 canvas->DrawStringInt(d->GetWindowTitle(), title_font_, SK_ColorWHITE, |
| 584 MirroredLeftPointForRect(title_bounds_), title_bounds_.y(), | 678 MirroredLeftPointForRect(title_bounds_), title_bounds_.y(), |
| 585 title_bounds_.width(), title_bounds_.height()); | 679 title_bounds_.width(), title_bounds_.height()); |
| 586 } | 680 } |
| 587 | 681 |
| 588 void DefaultNonClientView::PaintClientEdge(ChromeCanvas* canvas) { | 682 void DefaultNonClientView::PaintRestoredClientEdge(ChromeCanvas* canvas) { |
| 589 gfx::Rect client_area_bounds = container_->client_view()->bounds(); | 683 gfx::Rect client_area_bounds = container_->client_view()->bounds(); |
| 590 int client_area_top = client_area_bounds.y(); | 684 int client_area_top = client_area_bounds.y(); |
| 591 | 685 |
| 592 SkBitmap* top_left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); | 686 SkBitmap* top_left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_LEFT); |
| 593 SkBitmap* top = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); | 687 SkBitmap* top = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP); |
| 594 SkBitmap* top_right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); | 688 SkBitmap* top_right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_TOP_RIGHT); |
| 595 SkBitmap* right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT); | 689 SkBitmap* right = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_RIGHT); |
| 596 SkBitmap* bottom_right = | 690 SkBitmap* bottom_right = |
| 597 resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT); | 691 resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_RIGHT); |
| 598 SkBitmap* bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM); | 692 SkBitmap* bottom = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM); |
| 599 SkBitmap* bottom_left = | 693 SkBitmap* bottom_left = |
| 600 resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); | 694 resources()->GetPartBitmap(FRAME_CLIENT_EDGE_BOTTOM_LEFT); |
| 601 SkBitmap* left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); | 695 SkBitmap* left = resources()->GetPartBitmap(FRAME_CLIENT_EDGE_LEFT); |
| 602 | 696 |
| 603 // Top. | 697 // Top. |
| 604 // This next calculation is necessary because the top center bitmap is shorter | 698 // This next calculation is necessary because the top center bitmap is shorter |
| 605 // than the top left and right bitmaps. We need their top edges to line up, | 699 // than the top left and right bitmaps. We need their top edges to line up, |
| 606 // and we need the left and right edges to start below the corners' bottoms. | 700 // and we need the left and right edges to start below the corners' bottoms. |
| 607 int top_edge_y = client_area_top - top->height(); | 701 int top_edge_y = client_area_top - top->height(); |
| 608 client_area_top = top_edge_y + top_left->height(); | 702 client_area_top = top_edge_y + top_left->height(); |
| 609 canvas->DrawBitmapInt(*top_left, client_area_bounds.x() - top_left->width(), | 703 canvas->DrawBitmapInt(*top_left, client_area_bounds.x() - top_left->width(), |
| 610 top_edge_y); | 704 top_edge_y); |
| 611 canvas->TileImageInt(*top, client_area_bounds.x(), top_edge_y, | 705 canvas->TileImageInt(*top, client_area_bounds.x(), top_edge_y, |
| 612 client_area_bounds.width(), top->height()); | 706 client_area_bounds.width(), top->height()); |
| 613 canvas->DrawBitmapInt(*top_right, client_area_bounds.right(), top_edge_y); | 707 canvas->DrawBitmapInt(*top_right, client_area_bounds.right(), top_edge_y); |
| 614 | 708 |
| 615 // Right. | 709 // Right. |
| 710 int client_area_bottom = |
| 711 std::max(client_area_top, client_area_bounds.bottom()); |
| 712 int client_area_height = client_area_bottom - client_area_top; |
| 616 canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top, | 713 canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top, |
| 617 right->width(), client_area_bounds.height()); | 714 right->width(), client_area_height); |
| 618 | 715 |
| 619 // Bottom. | 716 // Bottom. |
| 620 canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(), | 717 canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(), |
| 621 client_area_bounds.bottom()); | 718 client_area_bottom); |
| 622 canvas->TileImageInt(*bottom, client_area_bounds.x(), | 719 canvas->TileImageInt(*bottom, client_area_bounds.x(), client_area_bottom, |
| 623 client_area_bounds.bottom(), | |
| 624 client_area_bounds.width(), bottom_right->height()); | 720 client_area_bounds.width(), bottom_right->height()); |
| 625 canvas->DrawBitmapInt(*bottom_left, | 721 canvas->DrawBitmapInt(*bottom_left, |
| 626 client_area_bounds.x() - bottom_left->width(), | 722 client_area_bounds.x() - bottom_left->width(), client_area_bottom); |
| 627 client_area_bounds.bottom()); | |
| 628 | 723 |
| 629 // Left. | 724 // Left. |
| 630 canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), | 725 canvas->TileImageInt(*left, client_area_bounds.x() - left->width(), |
| 631 client_area_top, left->width(), client_area_bounds.height()); | 726 client_area_top, left->width(), client_area_height); |
| 632 } | 727 } |
| 633 | 728 |
| 634 void DefaultNonClientView::LayoutWindowControls() { | 729 void DefaultNonClientView::LayoutWindowControls() { |
| 635 close_button_->SetImageAlignment(Button::ALIGN_LEFT, Button::ALIGN_BOTTOM); | 730 close_button_->SetImageAlignment(Button::ALIGN_LEFT, Button::ALIGN_BOTTOM); |
| 636 // Maximized buttons start at window top so that even if their images aren't | 731 // Maximized buttons start at window top so that even if their images aren't |
| 637 // drawn flush with the screen edge, they still obey Fitts' Law. | 732 // drawn flush with the screen edge, they still obey Fitts' Law. |
| 638 bool is_maximized = container_->IsMaximized(); | 733 bool is_maximized = container_->IsMaximized(); |
| 639 int caption_y = is_maximized ? 0 : kWindowControlsTopOffset; | 734 int frame_thickness = FrameBorderThickness(); |
| 640 int top_extra_height = is_maximized ? kWindowControlsTopZoomedOffset : 0; | 735 int caption_y = is_maximized ? frame_thickness : kCaptionTopSpacing; |
| 736 int top_extra_height = is_maximized ? kCaptionTopSpacing : 0; |
| 641 // There should always be the same number of non-shadow pixels visible to the | 737 // There should always be the same number of non-shadow pixels visible to the |
| 642 // side of the caption buttons. In maximized mode we extend the rightmost | 738 // side of the caption buttons. In maximized mode we extend the rightmost |
| 643 // button to the screen corner to obey Fitts' Law. | 739 // button to the screen corner to obey Fitts' Law. |
| 644 int right_extra_width = is_maximized ? kWindowControlsRightZoomedOffset : 0; | 740 int right_extra_width = is_maximized ? |
| 741 (kFrameBorderThickness - kFrameShadowThickness) : 0; |
| 645 int right_spacing = is_maximized ? | 742 int right_spacing = is_maximized ? |
| 646 kWindowControlsRightZoomedOffset : kWindowControlsRightOffset; | 743 (GetSystemMetrics(SM_CXSIZEFRAME) + right_extra_width) : frame_thickness; |
| 647 gfx::Size close_button_size = close_button_->GetPreferredSize(); | 744 gfx::Size close_button_size = close_button_->GetPreferredSize(); |
| 648 close_button_->SetBounds(width() - close_button_size.width() - right_spacing, | 745 close_button_->SetBounds(width() - close_button_size.width() - right_spacing, |
| 649 caption_y, | 746 caption_y, |
| 650 close_button_size.width() + right_extra_width, | 747 close_button_size.width() + right_extra_width, |
| 651 close_button_size.height() + top_extra_height); | 748 close_button_size.height() + top_extra_height); |
| 652 | 749 |
| 653 // When the window is restored, we show a maximized button; otherwise, we show | 750 // When the window is restored, we show a maximized button; otherwise, we show |
| 654 // a restore button. | 751 // a restore button. |
| 655 bool is_restored = !is_maximized && !container_->IsMinimized(); | 752 bool is_restored = !is_maximized && !container_->IsMinimized(); |
| 656 views::Button* invisible_button = is_restored ? | 753 views::Button* invisible_button = is_restored ? |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 | 788 |
| 692 close_button_->SetImage(Button::BS_NORMAL, | 789 close_button_->SetImage(Button::BS_NORMAL, |
| 693 active_resources_->GetPartBitmap(normal_part)); | 790 active_resources_->GetPartBitmap(normal_part)); |
| 694 close_button_->SetImage(Button::BS_HOT, | 791 close_button_->SetImage(Button::BS_HOT, |
| 695 active_resources_->GetPartBitmap(hot_part)); | 792 active_resources_->GetPartBitmap(hot_part)); |
| 696 close_button_->SetImage(Button::BS_PUSHED, | 793 close_button_->SetImage(Button::BS_PUSHED, |
| 697 active_resources_->GetPartBitmap(pushed_part)); | 794 active_resources_->GetPartBitmap(pushed_part)); |
| 698 } | 795 } |
| 699 | 796 |
| 700 void DefaultNonClientView::LayoutTitleBar() { | 797 void DefaultNonClientView::LayoutTitleBar() { |
| 701 int top_offset = container_->IsMaximized() ? kWindowTopMarginZoomed : 0; | 798 // Always lay out the icon, even when it's not present, so we can lay out the |
| 702 WindowDelegate* d = container_->window_delegate(); | 799 // window title based on its position. |
| 800 int frame_thickness = FrameBorderThickness(); |
| 801 int icon_x = frame_thickness + kIconLeftSpacing; |
| 703 | 802 |
| 704 // Size the window icon, if visible. | 803 // The usable height of the titlebar area is the total height minus the top |
| 705 if (d->ShouldShowWindowIcon()) { | 804 // resize border and any edge area we draw at its bottom. |
| 706 system_menu_button_->SetVisible(true); | 805 int title_top_spacing, title_thickness; |
| 707 gfx::Size ps = system_menu_button_->GetPreferredSize(); | 806 int top_height = TitleCoordinates(&title_top_spacing, &title_thickness); |
| 708 system_menu_button_->SetBounds( | 807 int available_height = top_height - frame_thickness - |
| 709 kWindowIconLeftOffset, kWindowIconTopOffset + top_offset, ps.width(), | 808 BottomEdgeThicknessWithinNonClientHeight(); |
| 710 ps.height()); | 809 |
| 711 } else { | 810 // The icon takes up a constant fraction of the available height, down to a |
| 712 // Put the menu in the right place at least even if it is hidden so we | 811 // minimum size, and is always an even number of pixels on a side (presumably |
| 713 // can size the title based on its position. | 812 // to make scaled icons look better). It's centered within the usable height. |
| 714 system_menu_button_->SetBounds(kWindowIconLeftOffset, | 813 int icon_size = std::max((available_height * kIconHeightFractionNumerator / |
| 715 kWindowIconTopOffset, 0, 0); | 814 kIconHeightFractionDenominator) / 2 * 2, kIconMinimumSize); |
| 716 } | 815 int icon_y = ((available_height - icon_size) / 2) + frame_thickness; |
| 816 |
| 817 // Hack: Our frame border has a different "3D look" than Windows'. Theirs has |
| 818 // a more complex gradient on the top that they push their icon/title below; |
| 819 // then the maximized window cuts this off and the icon/title are centered in |
| 820 // the remaining space. Because the apparent shape of our border is simpler, |
| 821 // using the same positioning makes things look slightly uncentered with |
| 822 // restored windows, so we come up to compensate. |
| 823 if (!container_->IsMaximized()) |
| 824 icon_y -= kIconRestoredAdjust; |
| 825 |
| 826 views::WindowDelegate* d = container_->window_delegate(); |
| 827 if (!d->ShouldShowWindowIcon()) |
| 828 icon_size = 0; |
| 829 system_menu_button_->SetBounds(icon_x, icon_y, icon_size, icon_size); |
| 717 | 830 |
| 718 // Size the title. | 831 // Size the title. |
| 719 gfx::Rect system_menu_bounds = system_menu_button_->bounds(); | 832 int icon_right = icon_x + icon_size; |
| 720 int spacing = d->ShouldShowWindowIcon() ? kWindowIconTitleSpacing : 0; | 833 int title_x = |
| 721 int title_right = should_show_minmax_buttons_ ? | 834 icon_right + (d->ShouldShowWindowIcon() ? kIconTitleSpacing : 0); |
| 722 minimize_button_->x() : close_button_->x(); | 835 int title_right = (should_show_minmax_buttons_ ? |
| 723 int title_left = system_menu_bounds.right() + spacing; | 836 minimize_button_->x() : close_button_->x()) - kTitleCaptionSpacing; |
| 724 title_bounds_.SetRect(title_left, kTitleTopOffset + top_offset, | 837 title_bounds_.SetRect(title_x, |
| 725 std::max(0, static_cast<int>(title_right - system_menu_bounds.right())), | 838 title_top_spacing + ((title_thickness - title_font_.height()) / 2), |
| 726 title_font_.height()); | 839 std::max(0, title_right - title_x), title_font_.height()); |
| 727 | |
| 728 // Center the icon within the height of the title if the title is taller. | |
| 729 int delta_y = title_bounds_.height() - system_menu_button_->height(); | |
| 730 if (delta_y > 0) { | |
| 731 int new_y = title_bounds_.y() + static_cast<int>(delta_y / 2); | |
| 732 system_menu_button_->SetBounds(system_menu_button_->x(), new_y, | |
| 733 system_menu_button_->width(), | |
| 734 system_menu_button_->height()); | |
| 735 } | |
| 736 } | 840 } |
| 737 | 841 |
| 738 void DefaultNonClientView::LayoutClientView() { | 842 void DefaultNonClientView::LayoutClientView() { |
| 739 container_->client_view()->SetBounds(CalculateClientAreaBounds(width(), | 843 container_->client_view()->SetBounds(CalculateClientAreaBounds(width(), |
| 740 height())); | 844 height())); |
| 741 } | 845 } |
| 742 | 846 |
| 743 // static | 847 // static |
| 744 void DefaultNonClientView::InitClass() { | 848 void DefaultNonClientView::InitClass() { |
| 745 static bool initialized = false; | 849 static bool initialized = false; |
| 746 if (!initialized) { | 850 if (!initialized) { |
| 747 active_resources_ = new ActiveWindowResources; | 851 active_resources_ = new ActiveWindowResources; |
| 748 inactive_resources_ = new InactiveWindowResources; | 852 inactive_resources_ = new InactiveWindowResources; |
| 853 |
| 749 title_font_ = win_util::GetWindowTitleFont(); | 854 title_font_ = win_util::GetWindowTitleFont(); |
| 855 |
| 750 initialized = true; | 856 initialized = true; |
| 751 } | 857 } |
| 752 } | 858 } |
| 753 | 859 |
| 754 /////////////////////////////////////////////////////////////////////////////// | 860 /////////////////////////////////////////////////////////////////////////////// |
| 755 // NonClientViewLayout | 861 // NonClientViewLayout |
| 756 | 862 |
| 757 class NonClientViewLayout : public LayoutManager { | 863 class NonClientViewLayout : public LayoutManager { |
| 758 public: | 864 public: |
| 759 // The size of the default window border and padding used by Windows Vista | 865 // The size of the default window border and padding used by Windows Vista |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 if ((GetKeyState(VK_CONTROL) & 0x80) == 0x80) | 1367 if ((GetKeyState(VK_CONTROL) & 0x80) == 0x80) |
| 1262 message_flags |= MK_CONTROL; | 1368 message_flags |= MK_CONTROL; |
| 1263 if ((GetKeyState(VK_SHIFT) & 0x80) == 0x80) | 1369 if ((GetKeyState(VK_SHIFT) & 0x80) == 0x80) |
| 1264 message_flags |= MK_SHIFT; | 1370 message_flags |= MK_SHIFT; |
| 1265 message_flags |= flags; | 1371 message_flags |= flags; |
| 1266 ProcessMousePressed(temp, message_flags, false); | 1372 ProcessMousePressed(temp, message_flags, false); |
| 1267 } | 1373 } |
| 1268 | 1374 |
| 1269 } // namespace views | 1375 } // namespace views |
| 1270 | 1376 |
| OLD | NEW |