OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/frame_painter.h" | 5 #include "ash/wm/frame_painter.h" |
6 | 6 |
7 #include "ash/wm/window_util.h" | 7 #include "ash/wm/window_util.h" |
8 #include "base/logging.h" // DCHECK | 8 #include "base/logging.h" // DCHECK |
9 #include "grit/ui_resources.h" | 9 #include "grit/ui_resources.h" |
10 #include "third_party/skia/include/core/SkCanvas.h" | 10 #include "third_party/skia/include/core/SkCanvas.h" |
11 #include "third_party/skia/include/core/SkColor.h" | 11 #include "third_party/skia/include/core/SkColor.h" |
12 #include "third_party/skia/include/core/SkPaint.h" | 12 #include "third_party/skia/include/core/SkPaint.h" |
13 #include "third_party/skia/include/core/SkPath.h" | 13 #include "third_party/skia/include/core/SkPath.h" |
14 #include "third_party/skia/include/core/SkShader.h" | 14 #include "third_party/skia/include/core/SkShader.h" |
15 #include "ui/aura/client/aura_constants.h" | 15 #include "ui/aura/client/aura_constants.h" |
16 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
17 #include "ui/base/animation/slide_animation.h" | |
18 #include "ui/base/hit_test.h" | 17 #include "ui/base/hit_test.h" |
19 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
20 #include "ui/base/theme_provider.h" | 19 #include "ui/base/theme_provider.h" |
21 #include "ui/gfx/canvas.h" | 20 #include "ui/gfx/canvas.h" |
22 #include "ui/gfx/font.h" | 21 #include "ui/gfx/font.h" |
23 #include "ui/gfx/image/image.h" | 22 #include "ui/gfx/image/image.h" |
24 #include "ui/views/controls/button/image_button.h" | 23 #include "ui/views/controls/button/image_button.h" |
25 #include "ui/views/widget/widget.h" | 24 #include "ui/views/widget/widget.h" |
26 #include "ui/views/widget/widget_delegate.h" | 25 #include "ui/views/widget/widget_delegate.h" |
27 | 26 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 const int kCloseButtonOffsetX = 0; | 61 const int kCloseButtonOffsetX = 0; |
63 // Space between close button and top edge of window. | 62 // Space between close button and top edge of window. |
64 const int kCloseButtonOffsetY = 0; | 63 const int kCloseButtonOffsetY = 0; |
65 // In the pre-Ash era the web content area had a frame along the left edge, so | 64 // In the pre-Ash era the web content area had a frame along the left edge, so |
66 // user-generated theme images for the new tab page assume they are shifted | 65 // user-generated theme images for the new tab page assume they are shifted |
67 // right relative to the header. Now that we have removed the left edge frame | 66 // right relative to the header. Now that we have removed the left edge frame |
68 // we need to copy the theme image for the window header from a few pixels | 67 // we need to copy the theme image for the window header from a few pixels |
69 // inset to preserve alignment with the NTP image, or else we'll break a bunch | 68 // inset to preserve alignment with the NTP image, or else we'll break a bunch |
70 // of existing themes. We do something similar on OS X for the same reason. | 69 // of existing themes. We do something similar on OS X for the same reason. |
71 const int kThemeFrameBitmapOffsetX = 5; | 70 const int kThemeFrameBitmapOffsetX = 5; |
72 // Duration of crossfade animation for activating and deactivating frame. | |
73 const int kActivationCrossfadeDurationMs = 200; | |
74 | 71 |
75 // Tiles an image into an area, rounding the top corners. Samples the |bitmap| | 72 // Tiles an image into an area, rounding the top corners. Samples the |bitmap| |
76 // starting |bitmap_offset_x| pixels from the left of the image. | 73 // starting |bitmap_offset_x| pixels from the left of the image. |
77 void TileRoundRect(gfx::Canvas* canvas, | 74 void TileRoundRect(gfx::Canvas* canvas, |
78 int x, int y, int w, int h, | 75 int x, int y, int w, int h, |
79 SkPaint* paint, | |
80 const SkBitmap& bitmap, | 76 const SkBitmap& bitmap, |
81 int corner_radius, | 77 int corner_radius, |
82 int bitmap_offset_x) { | 78 int bitmap_offset_x) { |
83 // To get the shader to sample the image |inset_y| pixels in but tile across | 79 // To get the shader to sample the image |inset_y| pixels in but tile across |
84 // the whole image, we adjust the target rectangle for the shader to the right | 80 // the whole image, we adjust the target rectangle for the shader to the right |
85 // and translate the canvas left to compensate. | 81 // and translate the canvas left to compensate. |
86 SkRect rect; | 82 SkRect rect; |
87 rect.iset(x + bitmap_offset_x, y, x + bitmap_offset_x + w, y + h); | 83 rect.iset(x + bitmap_offset_x, y, x + bitmap_offset_x + w, y + h); |
88 const SkScalar kRadius = SkIntToScalar(corner_radius); | 84 const SkScalar kRadius = SkIntToScalar(corner_radius); |
89 SkScalar radii[8] = { | 85 SkScalar radii[8] = { |
90 kRadius, kRadius, // top-left | 86 kRadius, kRadius, // top-left |
91 kRadius, kRadius, // top-right | 87 kRadius, kRadius, // top-right |
92 0, 0, // bottom-right | 88 0, 0, // bottom-right |
93 0, 0}; // bottom-left | 89 0, 0}; // bottom-left |
94 SkPath path; | 90 SkPath path; |
95 path.addRoundRect(rect, radii, SkPath::kCW_Direction); | 91 path.addRoundRect(rect, radii, SkPath::kCW_Direction); |
96 | 92 |
| 93 SkPaint paint; |
97 SkShader* shader = SkShader::CreateBitmapShader(bitmap, | 94 SkShader* shader = SkShader::CreateBitmapShader(bitmap, |
98 SkShader::kRepeat_TileMode, | 95 SkShader::kRepeat_TileMode, |
99 SkShader::kRepeat_TileMode); | 96 SkShader::kRepeat_TileMode); |
100 paint->setShader(shader); | 97 paint.setShader(shader); |
| 98 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
101 // CreateBitmapShader returns a Shader with a reference count of one, we | 99 // CreateBitmapShader returns a Shader with a reference count of one, we |
102 // need to unref after paint takes ownership of the shader. | 100 // need to unref after paint takes ownership of the shader. |
103 shader->unref(); | 101 shader->unref(); |
104 // Adjust canvas to compensate for image sampling offset, draw, then adjust | 102 // Adjust canvas to compensate for image sampling offset, draw, then adjust |
105 // back. This is cheaper than pushing/popping the entire canvas state. | 103 // back. This is cheaper than pushing/popping the entire canvas state. |
106 canvas->sk_canvas()->translate(SkIntToScalar(-bitmap_offset_x), 0); | 104 canvas->sk_canvas()->translate(SkIntToScalar(-bitmap_offset_x), 0); |
107 canvas->sk_canvas()->drawPath(path, *paint); | 105 canvas->sk_canvas()->drawPath(path, paint); |
108 canvas->sk_canvas()->translate(SkIntToScalar(bitmap_offset_x), 0); | 106 canvas->sk_canvas()->translate(SkIntToScalar(bitmap_offset_x), 0); |
109 } | 107 } |
110 | 108 |
111 } // namespace | 109 } // namespace |
112 | 110 |
113 namespace ash { | 111 namespace ash { |
114 | 112 |
115 /////////////////////////////////////////////////////////////////////////////// | 113 /////////////////////////////////////////////////////////////////////////////// |
116 // FramePainter, public: | 114 // FramePainter, public: |
117 | 115 |
118 FramePainter::FramePainter() | 116 FramePainter::FramePainter() |
119 : frame_(NULL), | 117 : frame_(NULL), |
120 window_icon_(NULL), | 118 window_icon_(NULL), |
121 maximize_button_(NULL), | 119 maximize_button_(NULL), |
122 close_button_(NULL), | 120 close_button_(NULL), |
123 window_(NULL), | 121 window_(NULL), |
124 button_separator_(NULL), | 122 button_separator_(NULL), |
125 top_left_corner_(NULL), | 123 top_left_corner_(NULL), |
126 top_edge_(NULL), | 124 top_edge_(NULL), |
127 top_right_corner_(NULL), | 125 top_right_corner_(NULL), |
128 header_left_edge_(NULL), | 126 header_left_edge_(NULL), |
129 header_right_edge_(NULL), | 127 header_right_edge_(NULL) { |
130 previous_theme_frame_(NULL), | |
131 crossfade_theme_frame_(NULL), | |
132 crossfade_animation_(NULL) { | |
133 } | 128 } |
134 | 129 |
135 FramePainter::~FramePainter() { | 130 FramePainter::~FramePainter() { |
136 if (window_) | 131 if (window_) |
137 window_->RemoveObserver(this); | 132 window_->RemoveObserver(this); |
138 | 133 |
139 } | 134 } |
140 | 135 |
141 void FramePainter::Init(views::Widget* frame, | 136 void FramePainter::Init(views::Widget* frame, |
142 views::View* window_icon, | 137 views::View* window_icon, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 if (title_width > min_size.width()) | 254 if (title_width > min_size.width()) |
260 min_size.set_width(title_width); | 255 min_size.set_width(title_width); |
261 return min_size; | 256 return min_size; |
262 } | 257 } |
263 | 258 |
264 void FramePainter::PaintHeader(views::NonClientFrameView* view, | 259 void FramePainter::PaintHeader(views::NonClientFrameView* view, |
265 gfx::Canvas* canvas, | 260 gfx::Canvas* canvas, |
266 const SkBitmap* theme_frame, | 261 const SkBitmap* theme_frame, |
267 const SkBitmap* theme_frame_overlay) { | 262 const SkBitmap* theme_frame_overlay) { |
268 | 263 |
269 if (previous_theme_frame_ && previous_theme_frame_ != theme_frame) { | 264 // Draw the header background, clipping the corners to be rounded. |
270 crossfade_animation_.reset(new ui::SlideAnimation(this)); | |
271 crossfade_theme_frame_ = previous_theme_frame_; | |
272 crossfade_animation_->SetSlideDuration(kActivationCrossfadeDurationMs); | |
273 crossfade_animation_->Show(); | |
274 } | |
275 | |
276 header_frame_bounds_ = gfx::Rect(0, 0, view->width(), theme_frame->height()); | |
277 const int kCornerRadius = 2; | 265 const int kCornerRadius = 2; |
278 | |
279 SkPaint paint; | |
280 if (crossfade_animation_.get() && crossfade_animation_->is_animating()) { | |
281 uint8 theme_alpha = crossfade_animation_->GetCurrentValue() * 255; | |
282 | |
283 // Draw the old header background, clipping the corners to be rounded. | |
284 paint.setAlpha(255 - theme_alpha); | |
285 paint.setXfermodeMode(SkXfermode::kPlus_Mode); | |
286 TileRoundRect(canvas, | |
287 0, 0, view->width(), theme_frame->height(), | |
288 &paint, | |
289 *crossfade_theme_frame_, | |
290 kCornerRadius, | |
291 kThemeFrameBitmapOffsetX); | |
292 | |
293 paint.setAlpha(theme_alpha); | |
294 } | |
295 | |
296 // Draw the header background, clipping the corners to be rounded. | |
297 TileRoundRect(canvas, | 266 TileRoundRect(canvas, |
298 0, 0, view->width(), theme_frame->height(), | 267 0, 0, view->width(), theme_frame->height(), |
299 &paint, | |
300 *theme_frame, | 268 *theme_frame, |
301 kCornerRadius, | 269 kCornerRadius, |
302 kThemeFrameBitmapOffsetX); | 270 kThemeFrameBitmapOffsetX); |
303 | 271 |
304 previous_theme_frame_ = theme_frame; | |
305 | |
306 // Draw the theme frame overlay, if available. | 272 // Draw the theme frame overlay, if available. |
307 if (theme_frame_overlay) | 273 if (theme_frame_overlay) |
308 canvas->DrawBitmapInt(*theme_frame_overlay, 0, 0); | 274 canvas->DrawBitmapInt(*theme_frame_overlay, 0, 0); |
309 | 275 |
310 // Separator between the maximize and close buttons. | 276 // Separator between the maximize and close buttons. |
311 canvas->DrawBitmapInt(*button_separator_, | 277 canvas->DrawBitmapInt(*button_separator_, |
312 close_button_->x() - button_separator_->width(), | 278 close_button_->x() - button_separator_->width(), |
313 close_button_->y()); | 279 close_button_->y()); |
314 | 280 |
315 // We don't need the extra lightness in the edges when we're maximized. | 281 // We don't need the extra lightness in the edges when we're maximized. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 | 423 |
458 void FramePainter::OnWindowDestroying(aura::Window* window) { | 424 void FramePainter::OnWindowDestroying(aura::Window* window) { |
459 DCHECK_EQ(window_, window); | 425 DCHECK_EQ(window_, window); |
460 // Must be removed here and not in the destructor, as the aura::Window is | 426 // Must be removed here and not in the destructor, as the aura::Window is |
461 // already destroyed when our destructor runs. | 427 // already destroyed when our destructor runs. |
462 window_->RemoveObserver(this); | 428 window_->RemoveObserver(this); |
463 window_ = NULL; | 429 window_ = NULL; |
464 } | 430 } |
465 | 431 |
466 /////////////////////////////////////////////////////////////////////////////// | 432 /////////////////////////////////////////////////////////////////////////////// |
467 // ui::AnimationDelegate overrides: | |
468 | |
469 void FramePainter::AnimationProgressed(const ui::Animation* animation) { | |
470 frame_->SchedulePaintInRect(gfx::Rect(header_frame_bounds_)); | |
471 } | |
472 | |
473 /////////////////////////////////////////////////////////////////////////////// | |
474 // FramePainter, private: | 433 // FramePainter, private: |
475 | 434 |
476 void FramePainter::SetButtonImages(views::ImageButton* button, | 435 void FramePainter::SetButtonImages(views::ImageButton* button, |
477 int normal_bitmap_id, | 436 int normal_bitmap_id, |
478 int hot_bitmap_id, | 437 int hot_bitmap_id, |
479 int pushed_bitmap_id) { | 438 int pushed_bitmap_id) { |
480 ui::ThemeProvider* theme_provider = frame_->GetThemeProvider(); | 439 ui::ThemeProvider* theme_provider = frame_->GetThemeProvider(); |
481 button->SetImage(views::CustomButton::BS_NORMAL, | 440 button->SetImage(views::CustomButton::BS_NORMAL, |
482 theme_provider->GetBitmapNamed(normal_bitmap_id)); | 441 theme_provider->GetBitmapNamed(normal_bitmap_id)); |
483 button->SetImage(views::CustomButton::BS_HOT, | 442 button->SetImage(views::CustomButton::BS_HOT, |
484 theme_provider->GetBitmapNamed(hot_bitmap_id)); | 443 theme_provider->GetBitmapNamed(hot_bitmap_id)); |
485 button->SetImage(views::CustomButton::BS_PUSHED, | 444 button->SetImage(views::CustomButton::BS_PUSHED, |
486 theme_provider->GetBitmapNamed(pushed_bitmap_id)); | 445 theme_provider->GetBitmapNamed(pushed_bitmap_id)); |
487 } | 446 } |
488 | 447 |
489 int FramePainter::GetTitleOffsetX() const { | 448 int FramePainter::GetTitleOffsetX() const { |
490 return window_icon_ ? | 449 return window_icon_ ? |
491 window_icon_->bounds().right() + kTitleIconOffsetX : | 450 window_icon_->bounds().right() + kTitleIconOffsetX : |
492 kTitleNoIconOffsetX; | 451 kTitleNoIconOffsetX; |
493 } | 452 } |
494 | 453 |
495 } // namespace ash | 454 } // namespace ash |
OLD | NEW |