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 "chrome/browser/ui/views/frame/browser_non_client_frame_view_aura.h" | 5 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_aura.h" |
6 | 6 |
7 #include "chrome/browser/ui/views/frame/browser_frame.h" | 7 #include "chrome/browser/ui/views/frame/browser_frame.h" |
8 #include "chrome/browser/ui/views/frame/browser_view.h" | 8 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 9 #include "content/public/browser/web_contents.h" |
9 #include "grit/generated_resources.h" // Accessibility names | 10 #include "grit/generated_resources.h" // Accessibility names |
| 11 #include "grit/theme_resources.h" |
| 12 #include "grit/theme_resources_standard.h" |
10 #include "grit/ui_resources.h" | 13 #include "grit/ui_resources.h" |
11 #include "third_party/skia/include/core/SkCanvas.h" | 14 #include "third_party/skia/include/core/SkCanvas.h" |
12 #include "third_party/skia/include/core/SkColor.h" | |
13 #include "third_party/skia/include/core/SkPaint.h" | 15 #include "third_party/skia/include/core/SkPaint.h" |
14 #include "ui/aura/cursor.h" | 16 #include "third_party/skia/include/core/SkPath.h" |
15 #include "ui/base/animation/throb_animation.h" | 17 #include "third_party/skia/include/core/SkShader.h" |
| 18 #include "ui/aura/window.h" |
| 19 #include "ui/base/accessibility/accessible_view_state.h" |
16 #include "ui/base/hit_test.h" | 20 #include "ui/base/hit_test.h" |
17 #include "ui/base/l10n/l10n_util.h" | 21 #include "ui/base/l10n/l10n_util.h" |
18 #include "ui/base/resource/resource_bundle.h" | 22 #include "ui/base/resource/resource_bundle.h" |
| 23 #include "ui/base/theme_provider.h" |
19 #include "ui/gfx/canvas.h" | 24 #include "ui/gfx/canvas.h" |
20 #include "ui/gfx/compositor/layer.h" | 25 #include "ui/gfx/font.h" |
21 #include "ui/views/controls/button/custom_button.h" | 26 #include "ui/views/controls/button/image_button.h" |
22 #include "ui/views/widget/widget.h" | 27 #include "ui/views/widget/widget.h" |
23 #include "ui/views/widget/widget_delegate.h" | 28 #include "ui/views/widget/widget_delegate.h" |
24 | 29 |
25 namespace { | 30 namespace { |
26 // Our window is larger than it appears, as it includes space around the edges | |
27 // where resize handles can appear. | |
28 const int kResizeBorderThickness = 8; | |
29 // The top edge is a little thinner, as it is not draggable for resize. | |
30 const int kTopBorderThickness = 4; | |
31 // Offset between top of non-client frame and top edge of opaque frame | |
32 // background at start of slide-in animation. | |
33 const int kFrameBackgroundTopOffset = 25; | |
34 | 31 |
35 // Width of a persistent border that we show around the window (using | 32 // Size of border along top edge, used for resize handle computations. |
36 // FrameBackground) even when the resize border isn't visible. | 33 const int kTopThickness = 1; |
37 const int kPersistentBorderThickness = 2; | 34 // TODO(jamescook): Border is specified to be a single pixel overlapping |
| 35 // the web content and may need to be built into the shadow layers instead. |
| 36 const int kBorderThickness = 0; |
| 37 // Number of pixels outside the window frame to look for resize events. |
| 38 const int kResizeAreaOutsideBounds = 6; |
| 39 // In the window corners, the resize areas don't actually expand bigger, but the |
| 40 // 16 px at the end of each edge triggers diagonal resizing. |
| 41 const int kResizeAreaCornerSize = 16; |
| 42 // Space between left edge of window and popup window icon. |
| 43 const int kIconOffsetX = 4; |
| 44 // Space between top of window and popup window icon. |
| 45 const int kIconOffsetY = 4; |
| 46 // Height and width of window icon. |
| 47 const int kIconSize = 16; |
| 48 // Space between the title text and the caption buttons. |
| 49 const int kTitleLogoSpacing = 5; |
| 50 // Space between title text and icon. |
| 51 const int kTitleOffsetX = 4; |
| 52 // Space between title text and top of window. |
| 53 const int kTitleOffsetY = 6; |
| 54 // Space between close button and right edge of window. |
| 55 const int kCloseButtonOffsetX = 0; |
| 56 // Space between close button and top edge of window. |
| 57 const int kCloseButtonOffsetY = 0; |
| 58 // Space between left edge of window and tabstrip. |
| 59 const int kTabstripLeftSpacing = 4; |
| 60 // Space between right edge of tabstrip and maximize button. |
| 61 const int kTabstripRightSpacing = 10; |
| 62 // Space between top of window and top of tabstrip for restored windows. |
| 63 const int kTabstripTopSpacingRestored = 10; |
| 64 // Space between top of window and top of tabstrip for maximized windows. |
| 65 const int kTabstripTopSpacingMaximized = 1; |
38 | 66 |
39 // The color used to fill the frame. Opacity is handled in the layer. | 67 // Tiles an image into an area, rounding the top corners. |
40 const SkColor kFrameColor = SK_ColorBLACK; | 68 void TileRoundRect(gfx::Canvas* canvas, |
41 // Radius of rounded rectangle corners. | 69 int x, int y, int w, int h, |
42 const int kRoundedRectRadius = 3; | 70 const SkBitmap& bitmap, |
43 // Frame border fades in over this range of opacity. | 71 int corner_radius) { |
44 const double kFrameBorderStartOpacity = 0.2; | 72 SkRect rect; |
45 const double kFrameBorderEndOpacity = 0.3; | 73 rect.iset(x, y, x + w, y + h); |
46 // How long the hover animation takes if uninterrupted. | 74 const SkScalar kRadius = SkIntToScalar(corner_radius); |
47 const int kHoverFadeDurationMs = 250; | 75 SkScalar radii[8] = { |
| 76 kRadius, kRadius, // top-left |
| 77 kRadius, kRadius, // top-right |
| 78 0, 0, // bottom-right |
| 79 0, 0}; // bottom-left |
| 80 SkPath path; |
| 81 path.addRoundRect(rect, radii, SkPath::kCW_Direction); |
48 | 82 |
49 // Color shown when window control is hovered. | 83 SkPaint paint; |
50 const SkColor kMaximizeButtonBackgroundColor = SkColorSetRGB(0, 255, 0); | 84 SkShader* shader = SkShader::CreateBitmapShader(bitmap, |
51 const SkColor kCloseButtonBackgroundColor = SkColorSetRGB(255, 0, 0); | 85 SkShader::kRepeat_TileMode, |
52 | 86 SkShader::kRepeat_TileMode); |
53 bool HitVisibleView(views::View* view, gfx::Point point) { | 87 paint.setShader(shader); |
54 return view->visible() && view->GetMirroredBounds().Contains(point); | 88 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
| 89 // CreateBitmapShader returns a Shader with a reference count of one, we |
| 90 // need to unref after paint takes ownership of the shader. |
| 91 shader->unref(); |
| 92 canvas->GetSkCanvas()->drawPath(path, paint); |
55 } | 93 } |
56 | 94 |
57 } // namespace | 95 } // namespace |
58 | 96 |
59 // Buttons for window controls - close, zoom, etc. | |
60 // Note that views::CustomButton is already a ui::AnimationDelegate. | |
61 class WindowControlButton : public views::CustomButton { | |
62 public: | |
63 WindowControlButton(BrowserNonClientFrameViewAura* owner, | |
64 SkColor color, | |
65 const SkBitmap& icon) | |
66 : views::CustomButton(owner), | |
67 owner_(owner), | |
68 color_(color), | |
69 icon_(icon), | |
70 ALLOW_THIS_IN_INITIALIZER_LIST( | |
71 show_animation_(new ui::SlideAnimation(this))) { | |
72 show_animation_->SetSlideDuration(kHoverFadeDurationMs); | |
73 SetPaintToLayer(true); | |
74 layer()->SetFillsBoundsOpaquely(false); | |
75 layer()->SetOpacity(0.f); | |
76 } | |
77 virtual ~WindowControlButton() {} | |
78 | |
79 void Show() { | |
80 show_animation_->Show(); | |
81 } | |
82 void Hide() { | |
83 show_animation_->Hide(); | |
84 } | |
85 | |
86 // Overridden from views::View: | |
87 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { | |
88 // Ensure the caption/frame background shows when we hover this button. | |
89 owner_->ShowFrameBackground(); | |
90 views::CustomButton::OnMouseEntered(event); | |
91 } | |
92 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { | |
93 owner_->HideFrameBackground(); | |
94 views::CustomButton::OnMouseExited(event); | |
95 } | |
96 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { | |
97 canvas->FillRect(GetLocalBounds(), GetBackgroundColor()); | |
98 canvas->DrawBitmapInt(icon_, 0, 0); | |
99 } | |
100 virtual gfx::Size GetPreferredSize() OVERRIDE { | |
101 return gfx::Size(icon_.width(), icon_.height()); | |
102 } | |
103 | |
104 // Overridden from ui::AnimationDelegate: | |
105 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE { | |
106 if (animation == show_animation_.get()) { | |
107 double opacity = show_animation_->GetCurrentValue(); | |
108 layer()->SetOpacity(static_cast<float>(opacity)); | |
109 return; | |
110 } | |
111 views::CustomButton::AnimationProgressed(animation); | |
112 } | |
113 | |
114 private: | |
115 SkColor GetBackgroundColor() { | |
116 // Background animates in separately, so handle opacity manually. | |
117 return SkColorSetARGB(hover_animation_->CurrentValueBetween(0, 150), | |
118 SkColorGetR(color_), | |
119 SkColorGetG(color_), | |
120 SkColorGetB(color_)); | |
121 } | |
122 | |
123 BrowserNonClientFrameViewAura* owner_; | |
124 SkColor color_; | |
125 SkBitmap icon_; | |
126 scoped_ptr<ui::SlideAnimation> show_animation_; | |
127 | |
128 DISALLOW_COPY_AND_ASSIGN(WindowControlButton); | |
129 }; | |
130 | |
131 // Layer that visually sits "behind" the window contents and expands out to | |
132 // provide visual resize handles on the sides. Hit testing and resize handling | |
133 // is in the parent NonClientFrameView. | |
134 class FrameBackgroundView : public views::View, | |
135 public ui::AnimationDelegate { | |
136 public: | |
137 FrameBackgroundView() | |
138 : ALLOW_THIS_IN_INITIALIZER_LIST( | |
139 size_animation_(new ui::SlideAnimation(this))), | |
140 ALLOW_THIS_IN_INITIALIZER_LIST( | |
141 color_animation_(new ui::SlideAnimation(this))) { | |
142 size_animation_->SetSlideDuration(kHoverFadeDurationMs); | |
143 color_animation_->SetSlideDuration(kHoverFadeDurationMs); | |
144 SetPaintToLayer(true); | |
145 UpdateOpacity(); | |
146 } | |
147 virtual ~FrameBackgroundView() { | |
148 } | |
149 | |
150 void Configure(const gfx::Rect& start_bounds, const gfx::Rect& end_bounds) { | |
151 start_bounds_ = start_bounds; | |
152 end_bounds_ = end_bounds; | |
153 UpdateBounds(); | |
154 } | |
155 void SetEndBounds(const gfx::Rect& end_bounds) { | |
156 end_bounds_ = end_bounds; | |
157 UpdateBounds(); | |
158 } | |
159 void Show() { | |
160 size_animation_->Show(); | |
161 color_animation_->Show(); | |
162 } | |
163 void Hide() { | |
164 size_animation_->Hide(); | |
165 color_animation_->Hide(); | |
166 } | |
167 | |
168 protected: | |
169 // Overridden from views::View: | |
170 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { | |
171 SkRect rect = { SkIntToScalar(0), SkIntToScalar(0), | |
172 SkIntToScalar(width()), SkIntToScalar(height()) }; | |
173 SkScalar radius = SkIntToScalar(kRoundedRectRadius); | |
174 SkPaint paint; | |
175 // Animation handles setting the opacity for the whole layer. | |
176 paint.setColor(kFrameColor); | |
177 paint.setStyle(SkPaint::kFill_Style); | |
178 canvas->GetSkCanvas()->drawRoundRect(rect, radius, radius, paint); | |
179 } | |
180 | |
181 // Overridden from ui::AnimationDelegate: | |
182 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE { | |
183 if (animation == color_animation_.get()) { | |
184 UpdateOpacity(); | |
185 } else if (animation == size_animation_.get()) { | |
186 UpdateBounds(); | |
187 } | |
188 } | |
189 | |
190 private: | |
191 void UpdateOpacity() { | |
192 double opacity = color_animation_->CurrentValueBetween( | |
193 kFrameBorderStartOpacity, kFrameBorderEndOpacity); | |
194 layer()->SetOpacity(static_cast<float>(opacity)); | |
195 } | |
196 | |
197 void UpdateBounds() { | |
198 gfx::Rect current_bounds = | |
199 size_animation_->CurrentValueBetween(start_bounds_, end_bounds_); | |
200 SetBoundsRect(current_bounds); | |
201 SchedulePaint(); | |
202 } | |
203 | |
204 scoped_ptr<ui::SlideAnimation> size_animation_; | |
205 scoped_ptr<ui::SlideAnimation> color_animation_; | |
206 // Default "hidden" rectangle. | |
207 gfx::Rect default_bounds_; | |
208 // When moving mouse from one target to another (e.g. from edge to corner) | |
209 // the size animation start point may not be the default size. | |
210 gfx::Rect start_bounds_; | |
211 // Expanded bounds, with edges visible from behind the client area. | |
212 gfx::Rect end_bounds_; | |
213 | |
214 DISALLOW_COPY_AND_ASSIGN(FrameBackgroundView); | |
215 }; | |
216 | |
217 /////////////////////////////////////////////////////////////////////////////// | 97 /////////////////////////////////////////////////////////////////////////////// |
218 // BrowserNonClientFrameViewAura, public: | 98 // BrowserNonClientFrameViewAura, public: |
219 | 99 |
220 BrowserNonClientFrameViewAura::BrowserNonClientFrameViewAura( | 100 BrowserNonClientFrameViewAura::BrowserNonClientFrameViewAura( |
221 BrowserFrame* frame, BrowserView* browser_view) | 101 BrowserFrame* frame, BrowserView* browser_view) |
222 : BrowserNonClientFrameView(frame, browser_view), | 102 : BrowserNonClientFrameView(frame, browser_view), |
223 last_hittest_code_(HTNOWHERE) { | 103 maximize_button_(NULL), |
224 frame_background_ = new FrameBackgroundView(); | 104 close_button_(NULL), |
225 AddChildView(frame_background_); | 105 window_icon_(NULL), |
| 106 button_separator_(NULL), |
| 107 top_left_corner_(NULL), |
| 108 top_edge_(NULL), |
| 109 top_right_corner_(NULL), |
| 110 header_left_edge_(NULL), |
| 111 header_right_edge_(NULL) { |
| 112 } |
226 | 113 |
227 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 114 BrowserNonClientFrameViewAura::~BrowserNonClientFrameViewAura() { |
228 maximize_button_ = | 115 } |
229 new WindowControlButton(this, | 116 |
230 kMaximizeButtonBackgroundColor, | 117 void BrowserNonClientFrameViewAura::Init() { |
231 *rb.GetBitmapNamed(IDR_AURA_WINDOW_ZOOM_ICON)); | 118 // Ensure we get resize cursors for a few pixels outside our bounds. |
| 119 frame()->GetNativeWindow()->set_hit_test_bounds_inset( |
| 120 -kResizeAreaOutsideBounds); |
| 121 |
| 122 // Caption buttons. |
| 123 maximize_button_ = new views::ImageButton(this); |
| 124 SetButtonImages(maximize_button_, |
| 125 IDR_AURA_WINDOW_MAXIMIZE, |
| 126 IDR_AURA_WINDOW_MAXIMIZE_H, |
| 127 IDR_AURA_WINDOW_MAXIMIZE_P); |
232 maximize_button_->SetAccessibleName( | 128 maximize_button_->SetAccessibleName( |
233 l10n_util::GetStringUTF16(IDS_ACCNAME_MAXIMIZE)); | 129 l10n_util::GetStringUTF16(IDS_ACCNAME_MAXIMIZE)); |
234 AddChildView(maximize_button_); | 130 AddChildView(maximize_button_); |
235 | 131 close_button_ = new views::ImageButton(this); |
236 close_button_ = | 132 SetButtonImages(close_button_, |
237 new WindowControlButton(this, | 133 IDR_AURA_WINDOW_CLOSE, |
238 kCloseButtonBackgroundColor, | 134 IDR_AURA_WINDOW_CLOSE_H, |
239 *rb.GetBitmapNamed(IDR_AURA_WINDOW_CLOSE_ICON)); | 135 IDR_AURA_WINDOW_CLOSE_P); |
240 close_button_->SetAccessibleName( | 136 close_button_->SetAccessibleName( |
241 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); | 137 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); |
242 AddChildView(close_button_); | 138 AddChildView(close_button_); |
243 | 139 |
244 // The BrowserFrame will become our owning window/widget. | 140 // Window frame image parts. |
245 frame->AsWidget()->AddObserver(this); | 141 ResourceBundle& bundle = ResourceBundle::GetSharedInstance(); |
246 // Associate our WindowFrame interface with our owning window/widget so | 142 button_separator_ = |
247 // we get callbacks from aura_shell. | 143 bundle.GetBitmapNamed(IDR_AURA_WINDOW_BUTTON_SEPARATOR); |
248 frame->AsWidget()->GetNativeWindow()->SetProperty( | 144 top_left_corner_ = |
249 ash::kWindowFrameKey, | 145 bundle.GetBitmapNamed(IDR_AURA_WINDOW_HEADER_SHADE_TOP_LEFT); |
250 static_cast<ash::WindowFrame*>(this)); | 146 top_edge_ = |
251 } | 147 bundle.GetBitmapNamed(IDR_AURA_WINDOW_HEADER_SHADE_TOP); |
| 148 top_right_corner_ = |
| 149 bundle.GetBitmapNamed(IDR_AURA_WINDOW_HEADER_SHADE_TOP_RIGHT); |
| 150 header_left_edge_ = |
| 151 bundle.GetBitmapNamed(IDR_AURA_WINDOW_HEADER_SHADE_LEFT); |
| 152 header_right_edge_ = |
| 153 bundle.GetBitmapNamed(IDR_AURA_WINDOW_HEADER_SHADE_RIGHT); |
| 154 // TODO(jamescook): Should we paint the header bottom edge here, or keep |
| 155 // it in BrowserFrameAura::ToolbarBackground as we do now? |
252 | 156 |
253 BrowserNonClientFrameViewAura::~BrowserNonClientFrameViewAura() { | 157 // Initializing the TabIconView is expensive, so only do it if we need to. |
254 // Don't need to remove the Widget observer, the window is deleted before us. | 158 if (browser_view()->ShouldShowWindowIcon()) { |
255 } | 159 window_icon_ = new TabIconView(this); |
256 | 160 window_icon_->set_is_light(true); |
257 void BrowserNonClientFrameViewAura::ShowFrameBackground() { | 161 AddChildView(window_icon_); |
258 UpdateFrameBackground(ShouldPaintAsActive()); | 162 window_icon_->Update(); |
259 frame_background_->Show(); | 163 } |
260 } | |
261 | |
262 void BrowserNonClientFrameViewAura::HideFrameBackground() { | |
263 frame_background_->Hide(); | |
264 } | 164 } |
265 | 165 |
266 /////////////////////////////////////////////////////////////////////////////// | 166 /////////////////////////////////////////////////////////////////////////////// |
267 // BrowserNonClientFrameViewAura, private: | |
268 | |
269 int BrowserNonClientFrameViewAura::NonClientHitTestImpl( | |
270 const gfx::Point& point) { | |
271 if (!GetLocalBounds().Contains(point)) | |
272 return HTNOWHERE; | |
273 | |
274 // Window controls get first try because they overlap the client area. | |
275 if (HitVisibleView(maximize_button_, point)) | |
276 return HTMAXBUTTON; | |
277 if (HitVisibleView(close_button_, point)) | |
278 return HTCLOSE; | |
279 | |
280 int frame_component = GetWidget()->client_view()->NonClientHitTest(point); | |
281 if (frame_component != HTNOWHERE) | |
282 return frame_component; | |
283 | |
284 // Test window resize components. | |
285 bool can_resize = GetWidget()->widget_delegate()->CanResize(); | |
286 // TODO(derat): Disallow resizing via the top border in the Aura shell | |
287 // instead of enforcing it here. See http://crbug.com/101830. | |
288 frame_component = GetHTComponentForFrame(point, | |
289 0, | |
290 kResizeBorderThickness, | |
291 kResizeBorderThickness, | |
292 kResizeBorderThickness, | |
293 can_resize); | |
294 if (frame_component != HTNOWHERE) | |
295 return frame_component; | |
296 // Use HTCAPTION as a final fallback. | |
297 return HTCAPTION; | |
298 } | |
299 | |
300 // Pass |active_window| explicitly because deactivating a window causes | |
301 // OnWidgetActivationChanged() to be called before GetWidget()->IsActive() | |
302 // changes state. | |
303 gfx::Rect BrowserNonClientFrameViewAura::GetFrameBackgroundBounds( | |
304 int hittest_code, | |
305 bool active_window) { | |
306 bool show_left = false; | |
307 bool show_top = false; | |
308 bool show_right = false; | |
309 bool show_bottom = false; | |
310 switch (hittest_code) { | |
311 case HTBOTTOM: | |
312 show_bottom = true; | |
313 break; | |
314 case HTBOTTOMLEFT: | |
315 show_bottom = true; | |
316 show_left = true; | |
317 break; | |
318 case HTBOTTOMRIGHT: | |
319 show_bottom = true; | |
320 show_right = true; | |
321 break; | |
322 case HTCAPTION: | |
323 show_top = true; | |
324 break; | |
325 case HTCLOSE: | |
326 show_top = true; | |
327 break; | |
328 case HTLEFT: | |
329 show_left = true; | |
330 break; | |
331 case HTMAXBUTTON: | |
332 show_top = true; | |
333 break; | |
334 case HTRIGHT: | |
335 show_right = true; | |
336 break; | |
337 case HTTOP: | |
338 show_top = true; | |
339 break; | |
340 case HTTOPLEFT: | |
341 show_top = true; | |
342 show_left = true; | |
343 break; | |
344 case HTTOPRIGHT: | |
345 show_top = true; | |
346 show_right = true; | |
347 break; | |
348 default: | |
349 break; | |
350 } | |
351 // Always show top edge for the active window so that you can tell which | |
352 // window has focus. | |
353 if (active_window) | |
354 show_top = true; | |
355 gfx::Rect target = bounds(); | |
356 // Inset the sides that are not showing. | |
357 target.Inset( | |
358 (show_left ? 0 : kResizeBorderThickness - kPersistentBorderThickness), | |
359 (show_top ? 0 : kTopBorderThickness + kFrameBackgroundTopOffset), | |
360 (show_right ? 0 : kResizeBorderThickness - kPersistentBorderThickness), | |
361 (show_bottom ? 0 : kResizeBorderThickness - kPersistentBorderThickness)); | |
362 return target; | |
363 } | |
364 | |
365 void BrowserNonClientFrameViewAura::UpdateFrameBackground(bool active_window) { | |
366 gfx::Rect start_bounds = GetFrameBackgroundBounds(HTNOWHERE, active_window); | |
367 gfx::Rect end_bounds = | |
368 GetFrameBackgroundBounds(last_hittest_code_, active_window); | |
369 frame_background_->Configure(start_bounds, end_bounds); | |
370 } | |
371 | |
372 void BrowserNonClientFrameViewAura::ActiveStateChanged() { | |
373 bool active = ShouldPaintAsActive(); | |
374 // Active windows have different background bounds. | |
375 UpdateFrameBackground(active); | |
376 if (active) | |
377 frame_background_->Show(); | |
378 else | |
379 frame_background_->Hide(); | |
380 } | |
381 | |
382 /////////////////////////////////////////////////////////////////////////////// | |
383 // BrowserNonClientFrameView overrides: | 167 // BrowserNonClientFrameView overrides: |
384 | 168 |
385 gfx::Rect BrowserNonClientFrameViewAura::GetBoundsForTabStrip( | 169 gfx::Rect BrowserNonClientFrameViewAura::GetBoundsForTabStrip( |
386 views::View* tabstrip) const { | 170 views::View* tabstrip) const { |
387 if (!tabstrip) | 171 if (!tabstrip) |
388 return gfx::Rect(); | 172 return gfx::Rect(); |
389 // TODO(jamescook): Avatar icon support. | 173 bool restored = !frame()->IsMaximized(); |
390 // Reserve space on the right for close/maximize buttons. | 174 return gfx::Rect(kTabstripLeftSpacing, |
391 int tabstrip_x = kResizeBorderThickness; | 175 GetHorizontalTabStripVerticalOffset(restored), |
392 int tabstrip_width = maximize_button_->x() - tabstrip_x; | 176 maximize_button_->x() - kTabstripRightSpacing, |
393 return gfx::Rect(tabstrip_x, | |
394 GetHorizontalTabStripVerticalOffset(false), | |
395 tabstrip_width, | |
396 tabstrip->GetPreferredSize().height()); | 177 tabstrip->GetPreferredSize().height()); |
397 | |
398 } | 178 } |
399 | 179 |
400 int BrowserNonClientFrameViewAura::GetHorizontalTabStripVerticalOffset( | 180 int BrowserNonClientFrameViewAura::GetHorizontalTabStripVerticalOffset( |
401 bool restored) const { | 181 bool restored) const { |
402 return kTopBorderThickness; | 182 return NonClientTopBorderHeight(restored); |
403 } | 183 } |
404 | 184 |
405 void BrowserNonClientFrameViewAura::UpdateThrobber(bool running) { | 185 void BrowserNonClientFrameViewAura::UpdateThrobber(bool running) { |
406 // TODO(jamescook): Do we need this? | 186 if (window_icon_) |
| 187 window_icon_->Update(); |
407 } | 188 } |
408 | 189 |
409 /////////////////////////////////////////////////////////////////////////////// | 190 /////////////////////////////////////////////////////////////////////////////// |
410 // views::NonClientFrameView overrides: | 191 // views::NonClientFrameView overrides: |
411 | 192 |
412 gfx::Rect BrowserNonClientFrameViewAura::GetBoundsForClientView() const { | 193 gfx::Rect BrowserNonClientFrameViewAura::GetBoundsForClientView() const { |
413 gfx::Rect bounds = GetLocalBounds(); | 194 int top_height = NonClientTopBorderHeight(false); |
414 bounds.Inset(kResizeBorderThickness, | 195 return gfx::Rect(kBorderThickness, |
415 kTopBorderThickness, | 196 top_height, |
416 kResizeBorderThickness, | 197 std::max(0, width() - (2 * kBorderThickness)), |
417 kResizeBorderThickness); | 198 std::max(0, height() - top_height - kBorderThickness)); |
418 return bounds; | |
419 } | 199 } |
420 | 200 |
421 gfx::Rect BrowserNonClientFrameViewAura::GetWindowBoundsForClientBounds( | 201 gfx::Rect BrowserNonClientFrameViewAura::GetWindowBoundsForClientBounds( |
422 const gfx::Rect& client_bounds) const { | 202 const gfx::Rect& client_bounds) const { |
423 gfx::Rect bounds = client_bounds; | 203 int top_height = NonClientTopBorderHeight(false); |
424 bounds.Inset(-kResizeBorderThickness, | 204 return gfx::Rect(std::max(0, client_bounds.x() - kBorderThickness), |
425 -kTopBorderThickness, | 205 std::max(0, client_bounds.y() - top_height), |
426 -kResizeBorderThickness, | 206 client_bounds.width() + (2 * kBorderThickness), |
427 -kResizeBorderThickness); | 207 client_bounds.height() + top_height + kBorderThickness); |
428 return bounds; | |
429 } | 208 } |
430 | 209 |
431 int BrowserNonClientFrameViewAura::NonClientHitTest(const gfx::Point& point) { | 210 int BrowserNonClientFrameViewAura::NonClientHitTest(const gfx::Point& point) { |
432 last_hittest_code_ = NonClientHitTestImpl(point); | 211 gfx::Rect expanded_bounds = bounds(); |
433 return last_hittest_code_; | 212 expanded_bounds.Inset(-kResizeAreaOutsideBounds, -kResizeAreaOutsideBounds); |
| 213 if (!expanded_bounds.Contains(point)) |
| 214 return HTNOWHERE; |
| 215 |
| 216 // No avatar button for Chrome OS. |
| 217 |
| 218 // Check the client view first, as it overlaps the window caption area. |
| 219 int client_component = frame()->client_view()->NonClientHitTest(point); |
| 220 if (client_component != HTNOWHERE) |
| 221 return client_component; |
| 222 |
| 223 // Then see if the point is within any of the window controls. |
| 224 if (close_button_->visible() && |
| 225 close_button_->GetMirroredBounds().Contains(point)) |
| 226 return HTCLOSE; |
| 227 if (maximize_button_->visible() && |
| 228 maximize_button_->GetMirroredBounds().Contains(point)) |
| 229 return HTMAXBUTTON; |
| 230 |
| 231 bool can_resize = frame()->widget_delegate() ? |
| 232 frame()->widget_delegate()->CanResize() : |
| 233 false; |
| 234 int frame_component = GetHTComponentForFrame(point, |
| 235 kTopThickness, |
| 236 kBorderThickness, |
| 237 kResizeAreaCornerSize, |
| 238 kResizeAreaCornerSize, |
| 239 can_resize); |
| 240 if (frame_component != HTNOWHERE) |
| 241 return frame_component; |
| 242 |
| 243 // Caption is a safe default. |
| 244 return HTCAPTION; |
434 } | 245 } |
435 | 246 |
436 void BrowserNonClientFrameViewAura::GetWindowMask(const gfx::Size& size, | 247 void BrowserNonClientFrameViewAura::GetWindowMask(const gfx::Size& size, |
437 gfx::Path* window_mask) { | 248 gfx::Path* window_mask) { |
438 // Nothing. | 249 // Aura does not use window masks. |
439 } | 250 } |
440 | 251 |
441 void BrowserNonClientFrameViewAura::ResetWindowControls() { | 252 void BrowserNonClientFrameViewAura::ResetWindowControls() { |
442 maximize_button_->SetState(views::CustomButton::BS_NORMAL); | 253 maximize_button_->SetState(views::CustomButton::BS_NORMAL); |
443 // The close button isn't affected by this constraint. | 254 // The close button isn't affected by this constraint. |
444 } | 255 } |
445 | 256 |
446 void BrowserNonClientFrameViewAura::UpdateWindowIcon() { | 257 void BrowserNonClientFrameViewAura::UpdateWindowIcon() { |
447 // TODO(jamescook): We will need this for app frames. | 258 if (window_icon_) |
448 } | 259 window_icon_->SchedulePaint(); |
449 | |
450 void BrowserNonClientFrameViewAura::ShouldPaintAsActiveChanged() { | |
451 ActiveStateChanged(); | |
452 } | 260 } |
453 | 261 |
454 /////////////////////////////////////////////////////////////////////////////// | 262 /////////////////////////////////////////////////////////////////////////////// |
455 // views::View overrides: | 263 // views::View overrides: |
456 | 264 |
457 void BrowserNonClientFrameViewAura::Layout() { | 265 void BrowserNonClientFrameViewAura::OnPaint(gfx::Canvas* canvas) { |
458 // Layout window buttons from right to left. | 266 if (frame()->IsFullscreen()) |
459 int right = width() - kResizeBorderThickness; | 267 return; // Nothing visible, don't paint. |
460 gfx::Size preferred = close_button_->GetPreferredSize(); | 268 PaintHeader(canvas); |
461 close_button_->SetBounds(right - preferred.width(), kTopBorderThickness, | 269 PaintTitleBar(canvas); |
462 preferred.width(), preferred.height()); | 270 // Paint the view hierarchy, which draws the caption buttons. |
463 right -= preferred.width(); // No padding. | 271 BrowserNonClientFrameView::OnPaint(canvas); |
464 preferred = maximize_button_->GetPreferredSize(); | |
465 maximize_button_->SetBounds(right - preferred.width(), kTopBorderThickness, | |
466 preferred.width(), preferred.height()); | |
467 UpdateFrameBackground(ShouldPaintAsActive()); | |
468 } | 272 } |
469 | 273 |
470 views::View* BrowserNonClientFrameViewAura::GetEventHandlerForPoint( | 274 void BrowserNonClientFrameViewAura::Layout() { |
471 const gfx::Point& point) { | 275 // Maximized windows and app/popup windows use shorter buttons. |
472 // Mouse hovers near the resizing edges result in the animation starting and | 276 if (frame()->IsMaximized() || |
473 // stopping as the frame background changes size. Just ignore events | 277 !browser_view()->IsBrowserTypeNormal()) { |
474 // destined for the frame background and handle them at this level. | 278 SetButtonImages(close_button_, |
475 views::View* view = View::GetEventHandlerForPoint(point); | 279 IDR_AURA_WINDOW_MAXIMIZED_CLOSE, |
476 if (view == frame_background_) | 280 IDR_AURA_WINDOW_MAXIMIZED_CLOSE_H, |
477 return this; | 281 IDR_AURA_WINDOW_MAXIMIZED_CLOSE_P); |
478 return view; | 282 SetButtonImages(maximize_button_, |
| 283 IDR_AURA_WINDOW_MAXIMIZED_RESTORE, |
| 284 IDR_AURA_WINDOW_MAXIMIZED_RESTORE_H, |
| 285 IDR_AURA_WINDOW_MAXIMIZED_RESTORE_P); |
| 286 } else { |
| 287 SetButtonImages(close_button_, |
| 288 IDR_AURA_WINDOW_CLOSE, |
| 289 IDR_AURA_WINDOW_CLOSE_H, |
| 290 IDR_AURA_WINDOW_CLOSE_P); |
| 291 SetButtonImages(maximize_button_, |
| 292 IDR_AURA_WINDOW_MAXIMIZE, |
| 293 IDR_AURA_WINDOW_MAXIMIZE_H, |
| 294 IDR_AURA_WINDOW_MAXIMIZE_P); |
| 295 } |
| 296 |
| 297 gfx::Size close_size = close_button_->GetPreferredSize(); |
| 298 close_button_->SetBounds( |
| 299 width() - close_size.width() - kCloseButtonOffsetX, |
| 300 kCloseButtonOffsetY, |
| 301 close_size.width(), |
| 302 close_size.height()); |
| 303 |
| 304 gfx::Size maximize_size = maximize_button_->GetPreferredSize(); |
| 305 maximize_button_->SetBounds( |
| 306 close_button_->x() - button_separator_->width() - maximize_size.width(), |
| 307 close_button_->y(), |
| 308 maximize_size.width(), |
| 309 maximize_size.height()); |
| 310 |
| 311 if (window_icon_) |
| 312 window_icon_->SetBoundsRect( |
| 313 gfx::Rect(kIconOffsetX, kIconOffsetY, kIconSize, kIconSize)); |
| 314 |
| 315 BrowserNonClientFrameView::Layout(); |
479 } | 316 } |
480 | 317 |
481 bool BrowserNonClientFrameViewAura::HitTest(const gfx::Point& p) const { | 318 bool BrowserNonClientFrameViewAura::HitTest(const gfx::Point& l) const { |
482 // Claim all events outside the client area. | 319 // If the point is outside the bounds of the client area, claim it. |
483 bool in_client = GetWidget()->client_view()->bounds().Contains(p); | 320 if (NonClientFrameView::HitTest(l)) |
484 if (!in_client) | |
485 return true; | 321 return true; |
486 // Window controls overlap the client area, so explicitly check for points | 322 |
487 // inside of them. | |
488 if (close_button_->bounds().Contains(p) || | |
489 maximize_button_->bounds().Contains(p)) | |
490 return true; | |
491 // Otherwise claim it only if it's in a non-tab portion of the tabstrip. | 323 // Otherwise claim it only if it's in a non-tab portion of the tabstrip. |
492 if (!browser_view()->tabstrip()) | 324 if (!browser_view()->tabstrip()) |
493 return false; | 325 return false; |
494 gfx::Rect tabstrip_bounds(browser_view()->tabstrip()->bounds()); | 326 gfx::Rect tabstrip_bounds(browser_view()->tabstrip()->bounds()); |
495 gfx::Point tabstrip_origin(tabstrip_bounds.origin()); | 327 gfx::Point tabstrip_origin(tabstrip_bounds.origin()); |
496 View::ConvertPointToView( | 328 View::ConvertPointToView(frame()->client_view(), this, &tabstrip_origin); |
497 frame()->client_view(), this, &tabstrip_origin); | |
498 tabstrip_bounds.set_origin(tabstrip_origin); | 329 tabstrip_bounds.set_origin(tabstrip_origin); |
499 if (p.y() > tabstrip_bounds.bottom()) | 330 if (l.y() > tabstrip_bounds.bottom()) |
500 return false; | 331 return false; |
501 | 332 |
502 // We convert from our parent's coordinates since we assume we fill its bounds | 333 // We convert from our parent's coordinates since we assume we fill its bounds |
503 // completely. We need to do this since we're not a parent of the tabstrip, | 334 // completely. We need to do this since we're not a parent of the tabstrip, |
504 // meaning ConvertPointToView would otherwise return something bogus. | 335 // meaning ConvertPointToView would otherwise return something bogus. |
505 gfx::Point browser_view_point(p); | 336 gfx::Point browser_view_point(l); |
506 View::ConvertPointToView(parent(), browser_view(), &browser_view_point); | 337 View::ConvertPointToView(parent(), browser_view(), &browser_view_point); |
507 return browser_view()->IsPositionInWindowCaption(browser_view_point); | 338 return browser_view()->IsPositionInWindowCaption(browser_view_point); |
508 } | 339 } |
509 | 340 |
510 void BrowserNonClientFrameViewAura::OnMouseMoved( | 341 void BrowserNonClientFrameViewAura::GetAccessibleState( |
511 const views::MouseEvent& event) { | 342 ui::AccessibleViewState* state) { |
512 // We may be hovering over the resize edge. | 343 state->role = ui::AccessibilityTypes::ROLE_TITLEBAR; |
513 ShowFrameBackground(); | |
514 } | |
515 | |
516 void BrowserNonClientFrameViewAura::OnMouseExited( | |
517 const views::MouseEvent& event) { | |
518 // We hovered away from the resize edge. | |
519 HideFrameBackground(); | |
520 } | |
521 | |
522 gfx::NativeCursor BrowserNonClientFrameViewAura::GetCursor( | |
523 const views::MouseEvent& event) { | |
524 switch (last_hittest_code_) { | |
525 case HTBOTTOM: | |
526 return aura::kCursorSouthResize; | |
527 case HTBOTTOMLEFT: | |
528 return aura::kCursorSouthWestResize; | |
529 case HTBOTTOMRIGHT: | |
530 return aura::kCursorSouthEastResize; | |
531 case HTLEFT: | |
532 return aura::kCursorWestResize; | |
533 case HTRIGHT: | |
534 return aura::kCursorEastResize; | |
535 case HTTOP: | |
536 // Resizing from the top edge is not allowed. | |
537 return aura::kCursorNull; | |
538 case HTTOPLEFT: | |
539 return aura::kCursorWestResize; | |
540 case HTTOPRIGHT: | |
541 return aura::kCursorEastResize; | |
542 default: | |
543 return aura::kCursorNull; | |
544 } | |
545 } | 344 } |
546 | 345 |
547 /////////////////////////////////////////////////////////////////////////////// | 346 /////////////////////////////////////////////////////////////////////////////// |
548 // views::ButtonListener overrides: | 347 // views::ButtonListener overrides: |
549 | 348 |
550 void BrowserNonClientFrameViewAura::ButtonPressed(views::Button* sender, | 349 void BrowserNonClientFrameViewAura::ButtonPressed(views::Button* sender, |
551 const views::Event& event) { | 350 const views::Event& event) { |
552 if (sender == close_button_) { | 351 if (sender == maximize_button_) { |
553 frame()->Close(); | |
554 } else if (sender == maximize_button_) { | |
555 if (frame()->IsMaximized()) | 352 if (frame()->IsMaximized()) |
556 frame()->Restore(); | 353 frame()->Restore(); |
557 else | 354 else |
558 frame()->Maximize(); | 355 frame()->Maximize(); |
| 356 // The maximize button may have moved out from under the cursor. |
| 357 ResetWindowControls(); |
| 358 } else if (sender == close_button_) { |
| 359 frame()->Close(); |
559 } | 360 } |
560 } | 361 } |
561 | 362 |
562 /////////////////////////////////////////////////////////////////////////////// | 363 /////////////////////////////////////////////////////////////////////////////// |
563 // views::Widget::Observer overrides: | 364 // TabIconView::TabIconViewModel overrides: |
564 | 365 |
565 void BrowserNonClientFrameViewAura::OnWidgetActivationChanged( | 366 bool BrowserNonClientFrameViewAura::ShouldTabIconViewAnimate() const { |
566 views::Widget* widget, | 367 // This function is queried during the creation of the window as the |
567 bool active) { | 368 // TabIconView we host is initialized, so we need to NULL check the selected |
568 ActiveStateChanged(); | 369 // WebContents because in this condition there is not yet a selected tab. |
| 370 content::WebContents* current_tab = browser_view()->GetSelectedWebContents(); |
| 371 return current_tab ? current_tab->IsLoading() : false; |
| 372 } |
| 373 |
| 374 SkBitmap BrowserNonClientFrameViewAura::GetFaviconForTabIconView() { |
| 375 views::WidgetDelegate* delegate = frame()->widget_delegate(); |
| 376 if (!delegate) |
| 377 return SkBitmap(); |
| 378 return delegate->GetWindowIcon(); |
569 } | 379 } |
570 | 380 |
571 /////////////////////////////////////////////////////////////////////////////// | 381 /////////////////////////////////////////////////////////////////////////////// |
572 // ash::WindowFrame overrides: | 382 // BrowserNonClientFrameViewAura, private: |
573 | 383 |
574 void BrowserNonClientFrameViewAura::OnWindowHoverChanged(bool hovered) { | 384 void BrowserNonClientFrameViewAura::SetButtonImages(views::ImageButton* button, |
575 if (hovered) { | 385 int normal_bitmap_id, |
576 maximize_button_->Show(); | 386 int hot_bitmap_id, |
577 close_button_->Show(); | 387 int pushed_bitmap_id) { |
578 } else { | 388 ui::ThemeProvider* tp = frame()->GetThemeProvider(); |
579 maximize_button_->Hide(); | 389 button->SetImage(views::CustomButton::BS_NORMAL, |
580 close_button_->Hide(); | 390 tp->GetBitmapNamed(normal_bitmap_id)); |
| 391 button->SetImage(views::CustomButton::BS_HOT, |
| 392 tp->GetBitmapNamed(hot_bitmap_id)); |
| 393 button->SetImage(views::CustomButton::BS_PUSHED, |
| 394 tp->GetBitmapNamed(pushed_bitmap_id)); |
| 395 } |
| 396 |
| 397 int BrowserNonClientFrameViewAura::NonClientTopBorderHeight( |
| 398 bool restored) const { |
| 399 if (frame()->widget_delegate() && |
| 400 frame()->widget_delegate()->ShouldShowWindowTitle()) { |
| 401 // For popups ensure we have enough space to see the full window buttons. |
| 402 return kCloseButtonOffsetY + close_button_->height(); |
| 403 } |
| 404 if (restored) |
| 405 return kTabstripTopSpacingRestored; |
| 406 return kTabstripTopSpacingMaximized; |
| 407 } |
| 408 |
| 409 void BrowserNonClientFrameViewAura::PaintHeader(gfx::Canvas* canvas) { |
| 410 // The primary header image changes based on window activation state and |
| 411 // theme, so we look it up for each paint. |
| 412 SkBitmap* theme_frame = GetThemeFrameBitmap(); |
| 413 SkBitmap* theme_frame_overlay = GetThemeFrameOverlayBitmap(); |
| 414 |
| 415 // Draw the header background, clipping the corners to be rounded. |
| 416 const int kCornerRadius = 2; |
| 417 TileRoundRect(canvas, |
| 418 0, 0, width(), theme_frame->height(), |
| 419 *theme_frame, |
| 420 kCornerRadius); |
| 421 |
| 422 // Draw the theme frame overlay, if available. |
| 423 if (theme_frame_overlay) |
| 424 canvas->DrawBitmapInt(*theme_frame_overlay, 0, 0); |
| 425 |
| 426 // Separator between the maximize and close buttons. |
| 427 canvas->DrawBitmapInt(*button_separator_, |
| 428 close_button_->x() - button_separator_->width(), |
| 429 close_button_->y()); |
| 430 |
| 431 // Draw the top corners and edge. |
| 432 int top_left_height = top_left_corner_->height(); |
| 433 canvas->DrawBitmapInt(*top_left_corner_, |
| 434 0, 0, top_left_corner_->width(), top_left_height, |
| 435 0, 0, top_left_corner_->width(), top_left_height, |
| 436 false); |
| 437 canvas->TileImageInt(*top_edge_, |
| 438 top_left_corner_->width(), |
| 439 0, |
| 440 width() - top_left_corner_->width() - top_right_corner_->width(), |
| 441 top_edge_->height()); |
| 442 int top_right_height = top_right_corner_->height(); |
| 443 canvas->DrawBitmapInt(*top_right_corner_, |
| 444 0, 0, |
| 445 top_right_corner_->width(), top_right_height, |
| 446 width() - top_right_corner_->width(), 0, |
| 447 top_right_corner_->width(), top_right_height, |
| 448 false); |
| 449 |
| 450 // Header left edge. |
| 451 int header_left_height = theme_frame->height() - top_left_height; |
| 452 canvas->TileImageInt(*header_left_edge_, |
| 453 0, top_left_height, |
| 454 header_left_edge_->width(), header_left_height); |
| 455 |
| 456 // Header right edge. |
| 457 int header_right_height = theme_frame->height() - top_right_height; |
| 458 canvas->TileImageInt(*header_right_edge_, |
| 459 width() - header_right_edge_->width(), top_right_height, |
| 460 header_right_edge_->width(), header_right_height); |
| 461 |
| 462 // We don't draw edges around the content area. Web content goes flush |
| 463 // to the edge of the window. |
| 464 } |
| 465 |
| 466 void BrowserNonClientFrameViewAura::PaintTitleBar(gfx::Canvas* canvas) { |
| 467 // The window icon is painted by the TabIconView. |
| 468 views::WidgetDelegate* delegate = frame()->widget_delegate(); |
| 469 if (delegate && delegate->ShouldShowWindowTitle()) { |
| 470 int icon_right = window_icon_ ? window_icon_->bounds().right() : 0; |
| 471 gfx::Rect title_bounds( |
| 472 icon_right + kTitleOffsetX, |
| 473 kTitleOffsetY, |
| 474 std::max(0, maximize_button_->x() - kTitleLogoSpacing - icon_right), |
| 475 BrowserFrame::GetTitleFont().GetHeight()); |
| 476 canvas->DrawStringInt(delegate->GetWindowTitle(), |
| 477 BrowserFrame::GetTitleFont(), |
| 478 SK_ColorWHITE, |
| 479 GetMirroredXForRect(title_bounds), |
| 480 title_bounds.y(), |
| 481 title_bounds.width(), |
| 482 title_bounds.height()); |
581 } | 483 } |
582 } | 484 } |
| 485 |
| 486 SkBitmap* BrowserNonClientFrameViewAura::GetThemeFrameBitmap() const { |
| 487 bool is_incognito = browser_view()->IsOffTheRecord(); |
| 488 int resource_id; |
| 489 if (browser_view()->IsBrowserTypeNormal()) { |
| 490 if (ShouldPaintAsActive()) { |
| 491 // Use the standard resource ids to allow users to theme the frames. |
| 492 // TODO(jamescook): If this becomes the only frame we use on Aura, define |
| 493 // the resources to use the standard ids like IDR_THEME_FRAME, etc. |
| 494 if (is_incognito) { |
| 495 return GetCustomBitmap(IDR_THEME_FRAME_INCOGNITO, |
| 496 IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_ACTIVE); |
| 497 } |
| 498 return GetCustomBitmap(IDR_THEME_FRAME, |
| 499 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE); |
| 500 } |
| 501 if (is_incognito) { |
| 502 return GetCustomBitmap(IDR_THEME_FRAME_INCOGNITO_INACTIVE, |
| 503 IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_INACTIVE); |
| 504 } |
| 505 return GetCustomBitmap(IDR_THEME_FRAME_INACTIVE, |
| 506 IDR_AURA_WINDOW_HEADER_BASE_INACTIVE); |
| 507 } |
| 508 // Never theme app and popup windows. |
| 509 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 510 if (ShouldPaintAsActive()) { |
| 511 resource_id = is_incognito ? |
| 512 IDR_THEME_FRAME_INCOGNITO : IDR_FRAME; |
| 513 } else { |
| 514 resource_id = is_incognito ? |
| 515 IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE; |
| 516 } |
| 517 return rb.GetBitmapNamed(resource_id); |
| 518 } |
| 519 |
| 520 SkBitmap* BrowserNonClientFrameViewAura::GetThemeFrameOverlayBitmap() const { |
| 521 ui::ThemeProvider* tp = GetThemeProvider(); |
| 522 if (tp->HasCustomImage(IDR_THEME_FRAME_OVERLAY) && |
| 523 browser_view()->IsBrowserTypeNormal() && |
| 524 !browser_view()->IsOffTheRecord()) { |
| 525 return tp->GetBitmapNamed(ShouldPaintAsActive() ? |
| 526 IDR_THEME_FRAME_OVERLAY : IDR_THEME_FRAME_OVERLAY_INACTIVE); |
| 527 } |
| 528 return NULL; |
| 529 } |
| 530 |
| 531 SkBitmap* BrowserNonClientFrameViewAura::GetCustomBitmap( |
| 532 int bitmap_id, |
| 533 int fallback_bitmap_id) const { |
| 534 ui::ThemeProvider* tp = GetThemeProvider(); |
| 535 if (tp->HasCustomImage(bitmap_id)) |
| 536 return tp->GetBitmapNamed(bitmap_id); |
| 537 return tp->GetBitmapNamed(fallback_bitmap_id); |
| 538 } |
OLD | NEW |