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/app_non_client_frame_view_ash.h" | 5 #include "chrome/browser/ui/views/frame/app_non_client_frame_view_ash.h" |
6 | 6 |
7 #include "ash/wm/caption_buttons/frame_caption_button_container_view.h" | 7 #include "ash/wm/caption_buttons/hideable_caption_button_container.h" |
8 #include "base/i18n/rtl.h" | |
9 #include "chrome/browser/ui/views/frame/browser_frame.h" | |
10 #include "chrome/browser/ui/views/frame/browser_view.h" | |
11 #include "grit/ash_resources.h" | 8 #include "grit/ash_resources.h" |
12 #include "ui/aura/window.h" | |
13 #include "ui/base/hit_test.h" | 9 #include "ui/base/hit_test.h" |
14 #include "ui/base/resource/resource_bundle.h" | |
15 #include "ui/gfx/canvas.h" | |
16 #include "ui/gfx/image/image.h" | |
17 #include "ui/gfx/point.h" | |
18 #include "ui/gfx/rect.h" | |
19 #include "ui/gfx/size.h" | |
20 #include "ui/views/background.h" | |
21 #include "ui/views/border.h" | |
22 #include "ui/views/widget/widget.h" | 10 #include "ui/views/widget/widget.h" |
23 #include "ui/views/window/non_client_view.h" | |
24 | |
25 namespace { | |
26 | |
27 // The size of the shadow around the caption buttons. | |
28 const int kShadowSizeX = 16; | |
29 const int kShadowSizeBottom = 21; | |
30 | |
31 // The border for |control_view_|. | |
32 class ControlViewBorder : public views::Border { | |
33 public: | |
34 ControlViewBorder() { | |
35 int border_id = base::i18n::IsRTL() ? | |
36 IDR_AURA_WINDOW_FULLSCREEN_SHADOW_RTL : | |
37 IDR_AURA_WINDOW_FULLSCREEN_SHADOW; | |
38 border_ = ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
39 border_id).AsImageSkia(); | |
40 } | |
41 | |
42 virtual ~ControlViewBorder() { | |
43 } | |
44 | |
45 private: | |
46 // views::Border overrides: | |
47 virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE { | |
48 canvas->DrawImageInt(border_, 0, view.height() - border_.height()); | |
49 } | |
50 | |
51 virtual gfx::Insets GetInsets() const OVERRIDE { | |
52 return gfx::Insets(0, kShadowSizeX, kShadowSizeBottom, 0); | |
53 } | |
54 | |
55 gfx::ImageSkia border_; | |
56 | |
57 DISALLOW_COPY_AND_ASSIGN(ControlViewBorder); | |
58 }; | |
59 | |
60 // The background for |control_view_|. | |
61 class ControlViewBackground : public views::Background { | |
62 public: | |
63 explicit ControlViewBackground(bool is_incognito) { | |
64 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
65 int control_base_resource_id = is_incognito ? | |
66 IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_ACTIVE : | |
67 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE; | |
68 background_ = rb.GetImageNamed(control_base_resource_id).AsImageSkia(); | |
69 } | |
70 | |
71 virtual ~ControlViewBackground() { | |
72 } | |
73 | |
74 private: | |
75 // views::Background override: | |
76 virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { | |
77 gfx::Rect paint_bounds(view->GetContentsBounds()); | |
78 paint_bounds.set_x(view->GetMirroredXForRect(paint_bounds)); | |
79 canvas->TileImageInt(background_, paint_bounds.x(), paint_bounds.y(), | |
80 paint_bounds.width(), paint_bounds.height()); | |
81 } | |
82 | |
83 gfx::ImageSkia background_; | |
84 | |
85 DISALLOW_COPY_AND_ASSIGN(ControlViewBackground); | |
86 }; | |
87 | |
88 } // namespace | |
89 | |
90 // Observer to detect when the browser frame widget closes so we can clean | |
91 // up our ControlView. Because we can be closed via a keyboard shortcut we | |
92 // are not guaranteed to run AppNonClientFrameView's Close() or Restore(). | |
93 class AppNonClientFrameViewAsh::FrameObserver : public views::WidgetObserver { | |
94 public: | |
95 explicit FrameObserver(AppNonClientFrameViewAsh* owner) : owner_(owner) {} | |
96 virtual ~FrameObserver() {} | |
97 | |
98 // views::WidgetObserver: | |
99 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE { | |
100 owner_->CloseControlWidget(); | |
101 } | |
102 | |
103 private: | |
104 AppNonClientFrameViewAsh* owner_; | |
105 | |
106 DISALLOW_COPY_AND_ASSIGN(FrameObserver); | |
107 }; | |
108 | 11 |
109 // static | 12 // static |
110 const char AppNonClientFrameViewAsh::kViewClassName[] = | 13 const char AppNonClientFrameViewAsh::kViewClassName[] = |
111 "AppNonClientFrameViewAsh"; | 14 "AppNonClientFrameViewAsh"; |
112 // static | |
113 const char AppNonClientFrameViewAsh::kControlWindowName[] = | |
114 "AppNonClientFrameViewAshControls"; | |
115 | 15 |
116 AppNonClientFrameViewAsh::AppNonClientFrameViewAsh( | 16 AppNonClientFrameViewAsh::AppNonClientFrameViewAsh(views::Widget* frame) { |
117 BrowserFrame* frame, BrowserView* browser_view) | 17 container_.reset(new ash::HideableCaptionButtonContainer( |
118 : BrowserNonClientFrameView(frame, browser_view), | 18 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE, frame)); |
119 control_view_(NULL), | 19 container_->ShowButtonWidget(); |
120 control_widget_(NULL), | |
121 frame_observer_(new FrameObserver(this)) { | |
122 control_view_ = new ash::FrameCaptionButtonContainerView(frame, | |
123 ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); | |
124 control_view_->set_header_style( | |
125 ash::FrameCaptionButtonContainerView::HEADER_STYLE_MAXIMIZED_HOSTED_APP); | |
126 control_view_->set_border(new ControlViewBorder()); | |
127 control_view_->set_background(new ControlViewBackground( | |
128 browser_view->IsOffTheRecord())); | |
129 | |
130 // This FrameView is always maximized so we don't want the window to have | |
131 // resize borders. | |
132 frame->GetNativeView()->set_hit_test_bounds_override_inner(gfx::Insets()); | |
pkotwicz
2013/10/02 19:41:49
I removed this call because an empty gfx::Insets()
James Cook
2013/10/02 21:07:55
Are you sure this is safe? I seem to recall we did
pkotwicz
2013/10/03 20:45:35
You are completely right! Thanks for finding this
| |
133 // Watch for frame close so we can clean up the control widget. | |
134 frame->AddObserver(frame_observer_.get()); | |
135 set_background(views::Background::CreateSolidBackground(SK_ColorBLACK)); | |
pkotwicz
2013/10/02 19:41:49
I believe that setting the background is no longer
| |
136 // Create the controls. | |
137 control_widget_ = new views::Widget; | |
138 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); | |
139 params.parent = browser_view->GetNativeWindow(); | |
140 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
141 control_widget_->Init(params); | |
142 control_widget_->SetContentsView(control_view_); | |
143 aura::Window* window = control_widget_->GetNativeView(); | |
144 window->SetName(kControlWindowName); | |
145 | |
146 // Need to exclude the shadow from the active control area. | |
147 gfx::Insets hit_test_insets(control_view_->GetInsets()); | |
148 if (base::i18n::IsRTL()) { | |
149 hit_test_insets = gfx::Insets(hit_test_insets.top(), | |
150 hit_test_insets.right(), | |
151 hit_test_insets.bottom(), | |
152 hit_test_insets.left()); | |
153 } | |
154 window->SetHitTestBoundsOverrideOuter(hit_test_insets, hit_test_insets); | |
155 | |
156 gfx::Rect control_bounds = GetControlBounds(); | |
157 window->SetBounds(control_bounds); | |
158 control_widget_->Show(); | |
159 } | 20 } |
160 | 21 |
161 AppNonClientFrameViewAsh::~AppNonClientFrameViewAsh() { | 22 AppNonClientFrameViewAsh::~AppNonClientFrameViewAsh() { |
162 frame()->RemoveObserver(frame_observer_.get()); | |
163 // This frame view can be replaced (and deleted) if the window is restored | |
164 // via a keyboard shortcut like Alt-[. Ensure we close the control widget. | |
165 CloseControlWidget(); | |
166 } | 23 } |
167 | 24 |
168 gfx::Rect AppNonClientFrameViewAsh::GetBoundsForClientView() const { | 25 gfx::Rect AppNonClientFrameViewAsh::GetBoundsForClientView() const { |
169 return GetLocalBounds(); | 26 return GetLocalBounds(); |
170 } | 27 } |
171 | 28 |
172 gfx::Rect AppNonClientFrameViewAsh::GetWindowBoundsForClientBounds( | 29 gfx::Rect AppNonClientFrameViewAsh::GetWindowBoundsForClientBounds( |
173 const gfx::Rect& client_bounds) const { | 30 const gfx::Rect& client_bounds) const { |
174 return client_bounds; | 31 return client_bounds; |
175 } | 32 } |
176 | 33 |
177 int AppNonClientFrameViewAsh::NonClientHitTest( | 34 int AppNonClientFrameViewAsh::NonClientHitTest( |
178 const gfx::Point& point) { | 35 const gfx::Point& point) { |
179 return HTNOWHERE; | 36 return HTNOWHERE; |
180 } | 37 } |
181 | 38 |
182 void AppNonClientFrameViewAsh::GetWindowMask(const gfx::Size& size, | 39 void AppNonClientFrameViewAsh::GetWindowMask(const gfx::Size& size, |
183 gfx::Path* window_mask) { | 40 gfx::Path* window_mask) { |
184 } | 41 } |
185 | 42 |
186 void AppNonClientFrameViewAsh::ResetWindowControls() { | 43 void AppNonClientFrameViewAsh::ResetWindowControls() { |
187 } | 44 } |
188 | 45 |
189 void AppNonClientFrameViewAsh::UpdateWindowIcon() { | 46 void AppNonClientFrameViewAsh::UpdateWindowIcon() { |
190 } | 47 } |
191 | 48 |
192 void AppNonClientFrameViewAsh::UpdateWindowTitle() { | 49 void AppNonClientFrameViewAsh::UpdateWindowTitle() { |
193 } | 50 } |
194 | 51 |
195 gfx::Rect AppNonClientFrameViewAsh::GetBoundsForTabStrip( | |
196 views::View* tabstrip) const { | |
197 return gfx::Rect(); | |
198 } | |
199 | |
200 BrowserNonClientFrameView::TabStripInsets | |
201 AppNonClientFrameViewAsh::GetTabStripInsets(bool restored) const { | |
202 return TabStripInsets(); | |
203 } | |
204 | |
205 int AppNonClientFrameViewAsh::GetThemeBackgroundXInset() const { | |
206 return 0; | |
207 } | |
208 | |
209 void AppNonClientFrameViewAsh::UpdateThrobber(bool running) { | |
210 } | |
211 | |
212 const char* AppNonClientFrameViewAsh::GetClassName() const { | 52 const char* AppNonClientFrameViewAsh::GetClassName() const { |
213 return kViewClassName; | 53 return kViewClassName; |
214 } | 54 } |
215 | |
216 void AppNonClientFrameViewAsh::OnBoundsChanged( | |
217 const gfx::Rect& previous_bounds) { | |
218 if (control_widget_) | |
219 control_widget_->GetNativeView()->SetBounds(GetControlBounds()); | |
220 } | |
221 | |
222 gfx::Rect AppNonClientFrameViewAsh::GetControlBounds() const { | |
223 if (!control_view_) | |
224 return gfx::Rect(); | |
225 gfx::Size preferred = control_view_->GetPreferredSize(); | |
226 return gfx::Rect( | |
227 base::i18n::IsRTL() ? 0 : (width() - preferred.width()), 0, | |
228 preferred.width(), preferred.height()); | |
229 } | |
230 | |
231 void AppNonClientFrameViewAsh::CloseControlWidget() { | |
232 if (control_widget_) { | |
233 control_widget_->Close(); | |
234 control_widget_ = NULL; | |
235 } | |
236 } | |
OLD | NEW |