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