Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / panels / panel_frame_view.cc
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
37 namespace {
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.
42 const int kNonAeroBorderThickness = 1;
43
44 // The height and width in pixels of the icon.
45 const int kIconSize = 16;
46
47 // The extra padding between the button and the top edge.
48 const int kExtraPaddingBetweenButtonAndTop = 1;
49
50 // Colors used to draw titlebar background under default theme.
51 const SkColor kActiveBackgroundDefaultColor = SkColorSetRGB(0x3a, 0x3d, 0x3d);
52 const SkColor kInactiveBackgroundDefaultColor = SkColorSetRGB(0x7a, 0x7c, 0x7c);
53 const SkColor kAttentionBackgroundDefaultColor =
54     SkColorSetRGB(0x53, 0xa9, 0x3f);
55
56 // Color used to draw the minimized panel.
57 const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0);
58
59 // Color used to draw the title text under default theme.
60 const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9);
61
62 gfx::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)
69 const 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
81 const 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
93 const 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
106 const 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
119 const 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
128 const 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
137 const 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
146 const 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
156 const gfx::ImageSkia* GetActiveBackgroundDefaultImage() {
157   static gfx::ImageSkia* image = NULL;
158   if (!image)
159     image = CreateImageForColor(kActiveBackgroundDefaultColor);
160   return image;
161 }
162
163 const gfx::ImageSkia* GetInactiveBackgroundDefaultImage() {
164   static gfx::ImageSkia* image = NULL;
165   if (!image)
166     image = CreateImageForColor(kInactiveBackgroundDefaultColor);
167   return image;
168 }
169
170 const gfx::ImageSkia* GetAttentionBackgroundDefaultImage() {
171   static gfx::ImageSkia* image = NULL;
172   if (!image)
173     image = CreateImageForColor(kAttentionBackgroundDefaultColor);
174   return image;
175 }
176
177 const gfx::ImageSkia* GetMinimizeBackgroundDefaultImage() {
178   static gfx::ImageSkia* image = NULL;
179   if (!image)
180     image = CreateImageForColor(kMinimizeBackgroundDefaultColor);
181   return image;
182 }
183
184 int 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.
224 bool 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
242 const char PanelFrameView::kViewClassName[] = "PanelFrameView";
243
244 PanelFrameView::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
255 PanelFrameView::~PanelFrameView() {
256 }
257
258 void 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
327 void PanelFrameView::UpdateTitle() {
328   UpdateWindowTitle();
329 }
330
331 void PanelFrameView::UpdateIcon() {
332   UpdateWindowIcon();
333 }
334
335 void PanelFrameView::UpdateThrobber() {
336   title_icon_->Update();
337 }
338
339 void 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
350 void 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
372 gfx::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
401 gfx::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
413 int 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
444 void 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
484 void PanelFrameView::ResetWindowControls() {
485   // The controls aren't affected by this constraint.
486 }
487
488 void PanelFrameView::UpdateWindowIcon() {
489   title_icon_->SchedulePaint();
490 }
491
492 void PanelFrameView::UpdateWindowTitle() {
493   title_label_->SetText(panel_view_->panel()->GetWindowTitle());
494 }
495
496 gfx::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
504 const char* PanelFrameView::GetClassName() const {
505   return kViewClassName;
506 }
507
508 gfx::Size PanelFrameView::GetMinimumSize() {
509   return panel_view_->GetMinimumSize();
510 }
511
512 gfx::Size PanelFrameView::GetMaximumSize() {
513   return panel_view_->GetMaximumSize();
514 }
515
516 void 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
558 void PanelFrameView::OnPaint(gfx::Canvas* canvas) {
559   UpdateControlStyles(GetPaintState());
560   PaintFrameBackground(canvas);
561   PaintFrameEdge(canvas);
562 }
563
564 bool 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
580 bool 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
591 void 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
598 void PanelFrameView::OnMouseCaptureLost() {
599   if (panel_view_->OnTitlebarMouseCaptureLost())
600     return;
601   NonClientFrameView::OnMouseCaptureLost();
602 }
603
604 void 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
618 bool 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
626 gfx::ImageSkia PanelFrameView::GetFaviconForTabIconView() {
627   return panel_view_->window()->widget_delegate()->GetWindowIcon();
628 }
629
630 gfx::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
640 int PanelFrameView::TitlebarHeight() const {
641   return panel::kTitlebarHeight;
642 }
643
644 int PanelFrameView::BorderThickness() const {
645   return is_frameless_ ? 0 : kNonAeroBorderThickness;
646 }
647
648 PanelFrameView::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
659 SkColor PanelFrameView::GetTitleColor(PaintState paint_state) const {
660   return kTitleTextDefaultColor;
661 }
662
663 const 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
680 void PanelFrameView::UpdateControlStyles(PaintState paint_state) {
681   title_label_->SetEnabledColor(GetTitleColor(paint_state));
682 }
683
684 void 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
708 void 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 }