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