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