panel_frame_view.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/panels/panel_frame_view.h" 6 7#include "chrome/browser/ui/panels/panel.h" 8#include "chrome/browser/ui/panels/panel_constants.h" 9#include "chrome/browser/ui/views/panels/panel_view.h" 10#include "chrome/browser/ui/views/tab_icon_view.h" 11#include "content/public/browser/web_contents.h" 12#include "grit/generated_resources.h" 13#include "grit/theme_resources.h" 14#include "grit/ui_resources.h" 15#include "ui/base/hit_test.h" 16#include "ui/base/l10n/l10n_util.h" 17#include "ui/base/resource/resource_bundle.h" 18#include "ui/gfx/canvas.h" 19#include "ui/gfx/path.h" 20#include "ui/views/controls/button/image_button.h" 21#include "ui/views/controls/label.h" 22#include "ui/views/widget/widget.h" 23#include "ui/views/widget/widget_delegate.h" 24 25#if defined(OS_WIN) 26#include "base/win/scoped_gdi_object.h" 27#include "ui/base/win/shell.h" 28#include "ui/gfx/path_win.h" 29#include "ui/views/win/hwnd_util.h" 30#endif 31 32#if defined(USE_AURA) 33#include "ui/aura/window.h" 34#endif 35 36namespace { 37 38// The thickness of the border when Aero is not enabled. In this case, the 39// shadow around the window will not be painted by the system and we need to 40// paint a frame in order to differentiate the client area from the background. 41const int kNonAeroBorderThickness = 1; 42 43// The height and width in pixels of the icon. 44const int kIconSize = 16; 45 46// The font to use to draw the title. 47const char* kTitleFontName = "Arial Bold"; 48const int kTitleFontSize = 14; 49 50// The extra padding between the button and the top edge. 51const int kExtraPaddingBetweenButtonAndTop = 1; 52 53// Colors used to draw titlebar background under default theme. 54const SkColor kActiveBackgroundDefaultColor = SkColorSetRGB(0x3a, 0x3d, 0x3d); 55const SkColor kInactiveBackgroundDefaultColor = SkColorSetRGB(0x7a, 0x7c, 0x7c); 56const SkColor kAttentionBackgroundDefaultColor = 57 SkColorSetRGB(0x53, 0xa9, 0x3f); 58 59// Color used to draw the minimized panel. 60const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0); 61 62// Color used to draw the title text under default theme. 63const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9); 64 65gfx::ImageSkia* CreateImageForColor(SkColor color) { 66 gfx::Canvas canvas(gfx::Size(1, 1), 1.0f, true); 67 canvas.DrawColor(color); 68 return new gfx::ImageSkia(canvas.ExtractImageRep()); 69} 70 71const gfx::ImageSkia& GetTopLeftCornerImage(panel::CornerStyle corner_style) { 72 static gfx::ImageSkia* rounded_image = NULL; 73 static gfx::ImageSkia* non_rounded_image = NULL; 74 if (!rounded_image) { 75 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 76 rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_LEFT_CORNER); 77 non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_TOP_LEFT_CORNER); 78 } 79 return (corner_style & panel::TOP_ROUNDED) ? *rounded_image 80 : *non_rounded_image; 81} 82 83const gfx::ImageSkia& GetTopRightCornerImage(panel::CornerStyle corner_style) { 84 static gfx::ImageSkia* rounded_image = NULL; 85 static gfx::ImageSkia* non_rounded_image = NULL; 86 if (!rounded_image) { 87 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 88 rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_RIGHT_CORNER); 89 non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_TOP_RIGHT_CORNER); 90 } 91 return (corner_style & panel::TOP_ROUNDED) ? *rounded_image 92 : *non_rounded_image; 93} 94 95const gfx::ImageSkia& GetBottomLeftCornerImage( 96 panel::CornerStyle corner_style) { 97 static gfx::ImageSkia* rounded_image = NULL; 98 static gfx::ImageSkia* non_rounded_image = NULL; 99 if (!rounded_image) { 100 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 101 rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER); 102 non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_BOTTOM_LEFT_CORNER); 103 } 104 return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image 105 : *non_rounded_image; 106} 107 108const gfx::ImageSkia& GetBottomRightCornerImage( 109 panel::CornerStyle corner_style) { 110 static gfx::ImageSkia* rounded_image = NULL; 111 static gfx::ImageSkia* non_rounded_image = NULL; 112 if (!rounded_image) { 113 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 114 rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER); 115 non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_BOTTOM_RIGHT_CORNER); 116 } 117 return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image 118 : *non_rounded_image; 119} 120 121const gfx::ImageSkia& GetTopEdgeImage() { 122 static gfx::ImageSkia* image = NULL; 123 if (!image) { 124 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 125 image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_CENTER); 126 } 127 return *image; 128} 129 130const gfx::ImageSkia& GetBottomEdgeImage() { 131 static gfx::ImageSkia* image = NULL; 132 if (!image) { 133 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 134 image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_CENTER); 135 } 136 return *image; 137} 138 139const gfx::ImageSkia& GetLeftEdgeImage() { 140 static gfx::ImageSkia* image = NULL; 141 if (!image) { 142 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 143 image = rb.GetImageSkiaNamed(IDR_WINDOW_LEFT_SIDE); 144 } 145 return *image; 146} 147 148const gfx::ImageSkia& GetRightEdgeImage() { 149 static gfx::ImageSkia* image = NULL; 150 if (!image) { 151 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 152 image = rb.GetImageSkiaNamed(IDR_WINDOW_RIGHT_SIDE); 153 } 154 return *image; 155} 156 157const gfx::Font& GetTitleFont() { 158 static gfx::Font* font = NULL; 159 if (!font) 160 font = new gfx::Font(kTitleFontName, kTitleFontSize); 161 return *font; 162} 163 164const gfx::ImageSkia* GetActiveBackgroundDefaultImage() { 165 static gfx::ImageSkia* image = NULL; 166 if (!image) 167 image = CreateImageForColor(kActiveBackgroundDefaultColor); 168 return image; 169} 170 171const gfx::ImageSkia* GetInactiveBackgroundDefaultImage() { 172 static gfx::ImageSkia* image = NULL; 173 if (!image) 174 image = CreateImageForColor(kInactiveBackgroundDefaultColor); 175 return image; 176} 177 178const gfx::ImageSkia* GetAttentionBackgroundDefaultImage() { 179 static gfx::ImageSkia* image = NULL; 180 if (!image) 181 image = CreateImageForColor(kAttentionBackgroundDefaultColor); 182 return image; 183} 184 185const gfx::ImageSkia* GetMinimizeBackgroundDefaultImage() { 186 static gfx::ImageSkia* image = NULL; 187 if (!image) 188 image = CreateImageForColor(kMinimizeBackgroundDefaultColor); 189 return image; 190} 191 192int GetFrameEdgeHitTest(const gfx::Point& point, 193 const gfx::Size& frame_size, 194 int resize_area_size, 195 panel::Resizability resizability) { 196 int x = point.x(); 197 int y = point.y(); 198 int width = frame_size.width(); 199 int height = frame_size.height(); 200 if (x < resize_area_size) { 201 if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP_LEFT)) { 202 return HTTOPLEFT; 203 } else if (y >= height - resize_area_size && 204 (resizability & panel::RESIZABLE_BOTTOM_LEFT)) { 205 return HTBOTTOMLEFT; 206 } else if (resizability & panel::RESIZABLE_LEFT) { 207 return HTLEFT; 208 } 209 } else if (x >= width - resize_area_size) { 210 if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP_RIGHT)) { 211 return HTTOPRIGHT; 212 } else if (y >= height - resize_area_size && 213 (resizability & panel::RESIZABLE_BOTTOM_RIGHT)) { 214 return HTBOTTOMRIGHT; 215 } else if (resizability & panel::RESIZABLE_RIGHT) { 216 return HTRIGHT; 217 } 218 } 219 220 if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP)) { 221 return HTTOP; 222 } else if (y >= height - resize_area_size && 223 (resizability & panel::RESIZABLE_BOTTOM)) { 224 return HTBOTTOM; 225 } 226 227 return HTNOWHERE; 228} 229 230// Frameless is only supported when Aero is enabled and shadow effect is 231// present. 232bool ShouldRenderAsFrameless() { 233#if defined(OS_WIN) 234 bool is_frameless = ui::win::IsAeroGlassEnabled(); 235 if (is_frameless) { 236 BOOL shadow_enabled = FALSE; 237 if (::SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow_enabled, 0) && 238 !shadow_enabled) 239 is_frameless = false; 240 } 241 return is_frameless; 242#else 243 return false; 244#endif 245} 246 247} // namespace 248 249// static 250const char PanelFrameView::kViewClassName[] = "PanelFrameView"; 251 252PanelFrameView::PanelFrameView(PanelView* panel_view) 253 : is_frameless_(ShouldRenderAsFrameless()), 254 panel_view_(panel_view), 255 close_button_(NULL), 256 minimize_button_(NULL), 257 restore_button_(NULL), 258 title_icon_(NULL), 259 title_label_(NULL), 260 corner_style_(panel::ALL_ROUNDED) { 261} 262 263PanelFrameView::~PanelFrameView() { 264} 265 266void PanelFrameView::Init() { 267 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 268 269 close_button_ = new views::ImageButton(this); 270 close_button_->SetImage(views::CustomButton::STATE_NORMAL, 271 rb.GetImageSkiaNamed(IDR_PANEL_CLOSE)); 272 close_button_->SetImage(views::CustomButton::STATE_HOVERED, 273 rb.GetImageSkiaNamed(IDR_PANEL_CLOSE_H)); 274 close_button_->SetImage(views::CustomButton::STATE_PRESSED, 275 rb.GetImageSkiaNamed(IDR_PANEL_CLOSE_C)); 276 close_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, 277 views::ImageButton::ALIGN_MIDDLE); 278 string16 tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_CLOSE_TOOLTIP); 279 close_button_->SetTooltipText(tooltip_text); 280 AddChildView(close_button_); 281 282 minimize_button_ = new views::ImageButton(this); 283 minimize_button_->SetImage(views::CustomButton::STATE_NORMAL, 284 rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE)); 285 minimize_button_->SetImage(views::CustomButton::STATE_HOVERED, 286 rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE_H)); 287 minimize_button_->SetImage(views::CustomButton::STATE_PRESSED, 288 rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE_C)); 289 tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_MINIMIZE_TOOLTIP); 290 minimize_button_->SetTooltipText(tooltip_text); 291 minimize_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, 292 views::ImageButton::ALIGN_MIDDLE); 293 AddChildView(minimize_button_); 294 295 restore_button_ = new views::ImageButton(this); 296 restore_button_->SetImage(views::CustomButton::STATE_NORMAL, 297 rb.GetImageSkiaNamed(IDR_PANEL_RESTORE)); 298 restore_button_->SetImage(views::CustomButton::STATE_HOVERED, 299 rb.GetImageSkiaNamed(IDR_PANEL_RESTORE_H)); 300 restore_button_->SetImage(views::CustomButton::STATE_PRESSED, 301 rb.GetImageSkiaNamed(IDR_PANEL_RESTORE_C)); 302 restore_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, 303 views::ImageButton::ALIGN_MIDDLE); 304 tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_RESTORE_TOOLTIP); 305 restore_button_->SetTooltipText(tooltip_text); 306 restore_button_->SetVisible(false); // only visible when panel is minimized 307 AddChildView(restore_button_); 308 309 title_icon_ = new TabIconView(this); 310 title_icon_->set_is_light(true); 311 AddChildView(title_icon_); 312 title_icon_->Update(); 313 314 title_label_ = new views::Label(panel_view_->panel()->GetWindowTitle()); 315 title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 316 title_label_->SetAutoColorReadabilityEnabled(false); 317 title_label_->SetFont(GetTitleFont()); 318 AddChildView(title_label_); 319 320#if defined(USE_AURA) 321 // Compute the thickness of the client area that needs to be counted towards 322 // mouse resizing. 323 int thickness_for_mouse_resizing = 324 PanelView::kResizeInsideBoundsSize - BorderThickness(); 325 aura::Window* window = panel_view_->GetNativePanelWindow(); 326 window->set_hit_test_bounds_override_inner( 327 gfx::Insets(thickness_for_mouse_resizing, thickness_for_mouse_resizing, 328 thickness_for_mouse_resizing, thickness_for_mouse_resizing)); 329#endif 330} 331 332void PanelFrameView::UpdateTitle() { 333 UpdateWindowTitle(); 334} 335 336void PanelFrameView::UpdateIcon() { 337 UpdateWindowIcon(); 338} 339 340void PanelFrameView::UpdateThrobber() { 341 title_icon_->Update(); 342} 343 344void PanelFrameView::UpdateTitlebarMinimizeRestoreButtonVisibility() { 345 Panel* panel = panel_view_->panel(); 346 minimize_button_->SetVisible(panel->CanShowMinimizeButton()); 347 restore_button_->SetVisible(panel->CanShowRestoreButton()); 348 349 // Reset the button states in case that the hover states are not cleared when 350 // mouse is clicked but not moved. 351 minimize_button_->SetState(views::CustomButton::STATE_NORMAL); 352 restore_button_->SetState(views::CustomButton::STATE_NORMAL); 353} 354 355void PanelFrameView::SetWindowCornerStyle(panel::CornerStyle corner_style) { 356 corner_style_ = corner_style; 357 358#if defined(OS_WIN) 359 // Changing the window region is going to force a paint. Only change the 360 // window region if the region really differs. 361 HWND native_window = views::HWNDForWidget(panel_view_->window()); 362 base::win::ScopedRegion current_region(::CreateRectRgn(0, 0, 0, 0)); 363 int current_region_result = ::GetWindowRgn(native_window, current_region); 364 365 gfx::Path window_mask; 366 GetWindowMask(size(), &window_mask); 367 base::win::ScopedRegion new_region(gfx::CreateHRGNFromSkPath(window_mask)); 368 369 if (current_region_result == ERROR || 370 !::EqualRgn(current_region, new_region)) { 371 // SetWindowRgn takes ownership of the new_region. 372 ::SetWindowRgn(native_window, new_region.release(), TRUE); 373 } 374#endif 375} 376 377gfx::Rect PanelFrameView::GetBoundsForClientView() const { 378 // The origin of client-area bounds starts after left border and titlebar and 379 // spans until hitting the right and bottom borders. 380 // +------------------------------+ 381 // | Top Titlebar | 382 // |-+--------------------------+-| 383 // |L| |R| 384 // |e| |i| 385 // |f| |g| 386 // |t| |h| 387 // | | Client |t| 388 // | | | | 389 // |B| Area |B| 390 // |o| |o| 391 // |r| |r| 392 // |d| |d| 393 // |e| |e| 394 // |r| |r| 395 // | +--------------------------+ | 396 // | Bottom Border | 397 // +------------------------------+ 398 int titlebar_height = TitlebarHeight(); 399 int border_thickness = BorderThickness(); 400 return gfx::Rect(border_thickness, 401 titlebar_height, 402 std::max(0, width() - border_thickness * 2), 403 std::max(0, height() - titlebar_height - border_thickness)); 404} 405 406gfx::Rect PanelFrameView::GetWindowBoundsForClientBounds( 407 const gfx::Rect& client_bounds) const { 408 int titlebar_height = TitlebarHeight(); 409 int border_thickness = BorderThickness(); 410 // The window bounds include both client area and non-client area (titlebar 411 // and left, right and bottom borders). 412 return gfx::Rect(client_bounds.x() - border_thickness, 413 client_bounds.y() - titlebar_height, 414 client_bounds.width() + border_thickness * 2, 415 client_bounds.height() + titlebar_height + border_thickness); 416} 417 418int PanelFrameView::NonClientHitTest(const gfx::Point& point) { 419 panel::Resizability resizability = panel_view_->panel()->CanResizeByMouse(); 420 421 // Check the frame first, as we allow a small area overlapping the contents 422 // to be used for resize handles. 423 int frame_component = GetFrameEdgeHitTest( 424 point, size(), PanelView::kResizeInsideBoundsSize, resizability); 425 426 if (frame_component != HTNOWHERE) 427 return frame_component; 428 429 int client_component = 430 panel_view_->window()->client_view()->NonClientHitTest(point); 431 if (client_component != HTNOWHERE) 432 return client_component; 433 434 if (close_button_ && close_button_->visible() && 435 close_button_->GetMirroredBounds().Contains(point)) 436 return HTCLOSE; 437 438 if (minimize_button_ && minimize_button_->visible() && 439 minimize_button_->GetMirroredBounds().Contains(point)) 440 return HTMINBUTTON; 441 442 if (restore_button_ && restore_button_->visible() && 443 restore_button_->GetMirroredBounds().Contains(point)) 444 return HTMAXBUTTON; 445 446 return HTNOWHERE; 447} 448 449void PanelFrameView::GetWindowMask(const gfx::Size& size, 450 gfx::Path* window_mask) { 451 int width = size.width(); 452 int height = size.height(); 453 454 if (corner_style_ & panel::TOP_ROUNDED) { 455 window_mask->moveTo(0, 3); 456 window_mask->lineTo(1, 2); 457 window_mask->lineTo(1, 1); 458 window_mask->lineTo(2, 1); 459 window_mask->lineTo(3, 0); 460 window_mask->lineTo(SkIntToScalar(width - 3), 0); 461 window_mask->lineTo(SkIntToScalar(width - 2), 1); 462 window_mask->lineTo(SkIntToScalar(width - 1), 1); 463 window_mask->lineTo(SkIntToScalar(width - 1), 2); 464 window_mask->lineTo(SkIntToScalar(width - 1), 3); 465 } else { 466 window_mask->moveTo(0, 0); 467 window_mask->lineTo(width, 0); 468 } 469 470 if (corner_style_ & panel::BOTTOM_ROUNDED) { 471 window_mask->lineTo(SkIntToScalar(width - 1), SkIntToScalar(height - 4)); 472 window_mask->lineTo(SkIntToScalar(width - 2), SkIntToScalar(height - 3)); 473 window_mask->lineTo(SkIntToScalar(width - 2), SkIntToScalar(height - 2)); 474 window_mask->lineTo(SkIntToScalar(width - 3), SkIntToScalar(height - 2)); 475 window_mask->lineTo(SkIntToScalar(width - 4), SkIntToScalar(height - 1)); 476 window_mask->lineTo(3, SkIntToScalar(height - 1)); 477 window_mask->lineTo(2, SkIntToScalar(height - 2)); 478 window_mask->lineTo(1, SkIntToScalar(height - 2)); 479 window_mask->lineTo(1, SkIntToScalar(height - 3)); 480 window_mask->lineTo(0, SkIntToScalar(height - 4)); 481 } else { 482 window_mask->lineTo(SkIntToScalar(width), SkIntToScalar(height)); 483 window_mask->lineTo(0, SkIntToScalar(height)); 484 } 485 486 window_mask->close(); 487} 488 489void PanelFrameView::ResetWindowControls() { 490 // The controls aren't affected by this constraint. 491} 492 493void PanelFrameView::UpdateWindowIcon() { 494 title_icon_->SchedulePaint(); 495} 496 497void PanelFrameView::UpdateWindowTitle() { 498 title_label_->SetText(panel_view_->panel()->GetWindowTitle()); 499} 500 501gfx::Size PanelFrameView::GetPreferredSize() { 502 gfx::Size pref_size = 503 panel_view_->window()->client_view()->GetPreferredSize(); 504 gfx::Rect bounds(0, 0, pref_size.width(), pref_size.height()); 505 return panel_view_->window()->non_client_view()-> 506 GetWindowBoundsForClientBounds(bounds).size(); 507} 508 509const char* PanelFrameView::GetClassName() const { 510 return kViewClassName; 511} 512 513gfx::Size PanelFrameView::GetMinimumSize() { 514 return panel_view_->GetMinimumSize(); 515} 516 517gfx::Size PanelFrameView::GetMaximumSize() { 518 return panel_view_->GetMaximumSize(); 519} 520 521void PanelFrameView::Layout() { 522 is_frameless_ = ShouldRenderAsFrameless(); 523 524 // Layout the close button. 525 int right = width(); 526 close_button_->SetBounds( 527 width() - panel::kTitlebarRightPadding - panel::kPanelButtonSize, 528 (TitlebarHeight() - panel::kPanelButtonSize) / 2 + 529 kExtraPaddingBetweenButtonAndTop, 530 panel::kPanelButtonSize, 531 panel::kPanelButtonSize); 532 right = close_button_->x(); 533 534 // Layout the minimize and restore button. Both occupy the same space, 535 // but at most one is visible at any time. 536 minimize_button_->SetBounds( 537 right - panel::kButtonPadding - panel::kPanelButtonSize, 538 (TitlebarHeight() - panel::kPanelButtonSize) / 2 + 539 kExtraPaddingBetweenButtonAndTop, 540 panel::kPanelButtonSize, 541 panel::kPanelButtonSize); 542 restore_button_->SetBoundsRect(minimize_button_->bounds()); 543 right = minimize_button_->x(); 544 545 // Layout the icon. 546 int icon_y = (TitlebarHeight() - kIconSize) / 2; 547 title_icon_->SetBounds( 548 panel::kTitlebarLeftPadding, 549 icon_y, 550 kIconSize, 551 kIconSize); 552 553 // Layout the title. 554 int title_x = title_icon_->bounds().right() + panel::kIconAndTitlePadding; 555 int title_height = GetTitleFont().GetHeight(); 556 title_label_->SetBounds( 557 title_x, 558 icon_y + ((kIconSize - title_height - 1) / 2), 559 std::max(0, right - panel::kTitleAndButtonPadding - title_x), 560 title_height); 561} 562 563void PanelFrameView::OnPaint(gfx::Canvas* canvas) { 564 UpdateControlStyles(GetPaintState()); 565 PaintFrameBackground(canvas); 566 PaintFrameEdge(canvas); 567} 568 569bool PanelFrameView::OnMousePressed(const ui::MouseEvent& event) { 570 if (event.IsOnlyLeftMouseButton()) { 571 // |event.location| is in the view's coordinate system. Convert it to the 572 // screen coordinate system. 573 gfx::Point mouse_location = event.location(); 574 views::View::ConvertPointToScreen(this, &mouse_location); 575 576 // If the mouse location falls within the resizing area of the titlebar, 577 // do not handle the event so that the system resizing logic could kick in. 578 if (!panel_view_->IsWithinResizingArea(mouse_location) && 579 panel_view_->OnTitlebarMousePressed(mouse_location)) 580 return true; 581 } 582 return NonClientFrameView::OnMousePressed(event); 583} 584 585bool PanelFrameView::OnMouseDragged(const ui::MouseEvent& event) { 586 // |event.location| is in the view's coordinate system. Convert it to the 587 // screen coordinate system. 588 gfx::Point mouse_location = event.location(); 589 views::View::ConvertPointToScreen(this, &mouse_location); 590 591 if (panel_view_->OnTitlebarMouseDragged(mouse_location)) 592 return true; 593 return NonClientFrameView::OnMouseDragged(event); 594} 595 596void PanelFrameView::OnMouseReleased(const ui::MouseEvent& event) { 597 if (panel_view_->OnTitlebarMouseReleased( 598 event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER)) 599 return; 600 NonClientFrameView::OnMouseReleased(event); 601} 602 603void PanelFrameView::OnMouseCaptureLost() { 604 if (panel_view_->OnTitlebarMouseCaptureLost()) 605 return; 606 NonClientFrameView::OnMouseCaptureLost(); 607} 608 609void PanelFrameView::ButtonPressed(views::Button* sender, 610 const ui::Event& event) { 611 if (sender == close_button_) { 612 panel_view_->ClosePanel(); 613 } else { 614 panel::ClickModifier modifier = 615 event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER; 616 if (sender == minimize_button_) 617 panel_view_->panel()->OnMinimizeButtonClicked(modifier); 618 else if (sender == restore_button_) 619 panel_view_->panel()->OnRestoreButtonClicked(modifier); 620 } 621} 622 623bool PanelFrameView::ShouldTabIconViewAnimate() const { 624 // This function is queried during the creation of the window as the 625 // TabIconView we host is initialized, so we need to NULL check the selected 626 // WebContents because in this condition there is not yet a selected tab. 627 content::WebContents* contents = panel_view_->panel()->GetWebContents(); 628 return contents ? contents->IsLoading() : false; 629} 630 631gfx::ImageSkia PanelFrameView::GetFaviconForTabIconView() { 632 return panel_view_->window()->widget_delegate()->GetWindowIcon(); 633} 634 635gfx::Size PanelFrameView::NonClientAreaSize() const { 636 if (is_frameless_) 637 return gfx::Size(0, TitlebarHeight()); 638 // When the frame is present, the width of non-client area consists of 639 // left and right borders, while the height consists of the top area 640 // (titlebar) and the bottom border. 641 return gfx::Size(2 * kNonAeroBorderThickness, 642 TitlebarHeight() + kNonAeroBorderThickness); 643} 644 645int PanelFrameView::TitlebarHeight() const { 646 return panel::kTitlebarHeight; 647} 648 649int PanelFrameView::BorderThickness() const { 650 return is_frameless_ ? 0 : kNonAeroBorderThickness; 651} 652 653PanelFrameView::PaintState PanelFrameView::GetPaintState() const { 654 if (panel_view_->panel()->IsDrawingAttention()) 655 return PAINT_FOR_ATTENTION; 656 if (bounds().height() <= panel::kMinimizedPanelHeight) 657 return PAINT_AS_MINIMIZED; 658 if (panel_view_->IsPanelActive() && 659 !panel_view_->force_to_paint_as_inactive()) 660 return PAINT_AS_ACTIVE; 661 return PAINT_AS_INACTIVE; 662} 663 664SkColor PanelFrameView::GetTitleColor(PaintState paint_state) const { 665 return kTitleTextDefaultColor; 666} 667 668const gfx::ImageSkia* PanelFrameView::GetFrameBackground( 669 PaintState paint_state) const { 670 switch (paint_state) { 671 case PAINT_AS_INACTIVE: 672 return GetInactiveBackgroundDefaultImage(); 673 case PAINT_AS_ACTIVE: 674 return GetActiveBackgroundDefaultImage(); 675 case PAINT_AS_MINIMIZED: 676 return GetMinimizeBackgroundDefaultImage(); 677 case PAINT_FOR_ATTENTION: 678 return GetAttentionBackgroundDefaultImage(); 679 default: 680 NOTREACHED(); 681 return GetInactiveBackgroundDefaultImage(); 682 } 683} 684 685void PanelFrameView::UpdateControlStyles(PaintState paint_state) { 686 title_label_->SetEnabledColor(GetTitleColor(paint_state)); 687} 688 689void PanelFrameView::PaintFrameBackground(gfx::Canvas* canvas) { 690 // We only need to paint the title-bar since no resizing border is shown. 691 // Instead, we allow part of the inner content area be used to trigger the 692 // mouse resizing. 693 int titlebar_height = TitlebarHeight(); 694 const gfx::ImageSkia* image = GetFrameBackground(GetPaintState()); 695 canvas->TileImageInt(*image, 0, 0, width(), titlebar_height); 696 697 if (is_frameless_) 698 return; 699 700 // Left border, below title-bar. 701 canvas->TileImageInt(*image, 0, titlebar_height, kNonAeroBorderThickness, 702 height() - titlebar_height); 703 704 // Right border, below title-bar. 705 canvas->TileImageInt(*image, width() - kNonAeroBorderThickness, 706 titlebar_height, kNonAeroBorderThickness, height() - titlebar_height); 707 708 // Bottom border. 709 canvas->TileImageInt(*image, 0, height() - kNonAeroBorderThickness, width(), 710 kNonAeroBorderThickness); 711} 712 713void PanelFrameView::PaintFrameEdge(gfx::Canvas* canvas) { 714#if defined(OS_WIN) 715 // Border is not needed when panel is not shown as minimized. 716 if (GetPaintState() != PAINT_AS_MINIMIZED) 717 return; 718 719 const gfx::ImageSkia& top_left_image = GetTopLeftCornerImage(corner_style_); 720 const gfx::ImageSkia& top_right_image = GetTopRightCornerImage(corner_style_); 721 const gfx::ImageSkia& bottom_left_image = 722 GetBottomLeftCornerImage(corner_style_); 723 const gfx::ImageSkia& bottom_right_image = 724 GetBottomRightCornerImage(corner_style_); 725 const gfx::ImageSkia& top_image = GetTopEdgeImage(); 726 const gfx::ImageSkia& bottom_image = GetBottomEdgeImage(); 727 const gfx::ImageSkia& left_image = GetLeftEdgeImage(); 728 const gfx::ImageSkia& right_image = GetRightEdgeImage(); 729 730 // Draw the top border. 731 canvas->DrawImageInt(top_left_image, 0, 0); 732 canvas->TileImageInt(top_image, 733 top_left_image.width(), 734 0, 735 width() - top_right_image.width(), 736 top_image.height()); 737 canvas->DrawImageInt(top_right_image, width() - top_right_image.width(), 0); 738 739 // Draw the right border. 740 canvas->TileImageInt(right_image, 741 width() - right_image.width(), 742 top_right_image.height(), 743 right_image.width(), 744 height() - top_right_image.height() - 745 bottom_right_image.height()); 746 747 // Draw the bottom border. 748 canvas->DrawImageInt(bottom_right_image, 749 width() - bottom_right_image.width(), 750 height() - bottom_right_image.height()); 751 canvas->TileImageInt(bottom_image, 752 bottom_left_image.width(), 753 height() - bottom_image.height(), 754 width() - bottom_left_image.width() - 755 bottom_right_image.width(), 756 bottom_image.height()); 757 canvas->DrawImageInt(bottom_left_image, 758 0, 759 height() - bottom_left_image.height()); 760 761 // Draw the left border. 762 canvas->TileImageInt(left_image, 763 0, 764 top_left_image.height(), 765 left_image.width(), 766 height() - top_left_image.height() - 767 bottom_left_image.height()); 768#endif 769} 770