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