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