Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: ash/wm/custom_frame_view_ash.cc

Issue 59043013: Add flag to enable immersive fullscreen for v2 apps (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/custom_frame_view_ash.h" 5 #include "ash/wm/custom_frame_view_ash.h"
6 6
7 #include "ash/wm/caption_buttons/frame_caption_button_container_view.h" 7 #include "ash/wm/caption_buttons/frame_caption_button_container_view.h"
8 #include "ash/wm/caption_buttons/frame_maximize_button.h"
9 #include "ash/wm/caption_buttons/frame_maximize_button_observer.h"
8 #include "ash/wm/frame_border_hit_test_controller.h" 10 #include "ash/wm/frame_border_hit_test_controller.h"
9 #include "ash/wm/header_painter.h" 11 #include "ash/wm/header_painter.h"
12 #include "ash/wm/immersive_fullscreen_controller.h"
10 #include "grit/ash_resources.h" 13 #include "grit/ash_resources.h"
11 #include "ui/gfx/canvas.h" 14 #include "ui/gfx/canvas.h"
12 #include "ui/gfx/font.h" 15 #include "ui/gfx/font.h"
13 #include "ui/gfx/rect.h" 16 #include "ui/gfx/rect.h"
14 #include "ui/gfx/size.h" 17 #include "ui/gfx/size.h"
18 #include "ui/views/view.h"
15 #include "ui/views/widget/native_widget_aura.h" 19 #include "ui/views/widget/native_widget_aura.h"
16 #include "ui/views/widget/widget.h" 20 #include "ui/views/widget/widget.h"
17 #include "ui/views/widget/widget_delegate.h" 21 #include "ui/views/widget/widget_delegate.h"
22 #include "ui/views/widget/widget_deletion_observer.h"
23 #include "ui/views/window/non_client_view.h"
18 24
19 namespace { 25 namespace {
20 26
21 const gfx::Font& GetTitleFont() { 27 const gfx::Font& GetTitleFont() {
22 static gfx::Font* title_font = NULL; 28 static gfx::Font* title_font = NULL;
23 if (!title_font) 29 if (!title_font)
24 title_font = new gfx::Font(views::NativeWidgetAura::GetWindowTitleFont()); 30 title_font = new gfx::Font(views::NativeWidgetAura::GetWindowTitleFont());
25 return *title_font; 31 return *title_font;
26 } 32 }
27 33
28 } // namespace 34 } // namespace
29 35
30 namespace ash { 36 namespace ash {
31 37
32 // static 38 ///////////////////////////////////////////////////////////////////////////////
33 const char CustomFrameViewAsh::kViewClassName[] = "CustomFrameViewAsh"; 39 // CustomFrameViewAsh::HeaderView
34 40
35 //////////////////////////////////////////////////////////////////////////////// 41 // View which paints the header. It slides off and on screen in immersive
36 // CustomFrameViewAsh, public: 42 // fullscreen.
37 CustomFrameViewAsh::CustomFrameViewAsh(views::Widget* frame) 43 class CustomFrameViewAsh::HeaderView
44 : public views::View,
45 public ImmersiveFullscreenController::Delegate,
46 public FrameMaximizeButtonObserver {
47 public:
48 // |frame| is the widget that the caption buttons act on.
49 HeaderView(views::Widget* frame);
oshima 2013/11/07 18:56:13 explicit
50 virtual ~HeaderView();
51
52 // Schedules a repaint for the entire title.
53 void SchedulePaintForTitle();
54
55 // Tells the window controls to reset themselves to the normal state.
56 void ResetWindowControls();
57
58 // Returns the amount of the view's pixels which should be on screen.
59 int GetPreferredOnScreenHeight() const;
60
61 // Returns the view's preferred height.
62 int GetPreferredHeight() const;
63
64 // Returns the view's minimum width.
65 int GetMinimumWidth() const;
66
67 // views::View overrides:
68 virtual void Layout() OVERRIDE;
69 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
70
71 // Sets whether the header should be painted as active.
72 void set_paint_as_active(bool paint_as_active) {
73 paint_as_active_ = paint_as_active;
74 }
75
76 HeaderPainter* header_painter() {
77 return header_painter_.get();
78 }
79
80 private:
81 // ImmersiveFullscreenController::Delegate overrides:
82 virtual void OnImmersiveRevealStarted() OVERRIDE;
83 virtual void OnImmersiveRevealEnded() OVERRIDE;
84 virtual void OnImmersiveFullscreenExited() OVERRIDE;
85 virtual void SetVisibleFraction(double visible_fraction) OVERRIDE;
86 virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE;
87
88 // FrameMaximizeButtonObserver overrides:
89 virtual void OnMaximizeBubbleShown(views::Widget* bubble) OVERRIDE;
90
91 // The widget that the caption buttons act on.
92 views::Widget* frame_;
93
94 // Helper for painting the header.
95 scoped_ptr<HeaderPainter> header_painter_;
96
97 // View which contains the window caption buttons.
98 FrameCaptionButtonContainerView* caption_button_container_;
99
100 // The maximize bubble widget. |maximize_bubble_| may be non-NULL but have
101 // been already destroyed.
102 views::Widget* maximize_bubble_;
103
104 // Keeps track of whether |maximize_bubble_| is still alive.
105 scoped_ptr<views::WidgetDeletionObserver> maximize_bubble_lifetime_observer_;
106
107 // Whether the header should be painted as active.
108 bool paint_as_active_;
109
110 // The fraction of the header's height which is visible while in fullscreen.
111 // This value is meaningless when not in fullscreen.
112 double fullscreen_visible_fraction_;
113
114 DISALLOW_COPY_AND_ASSIGN(HeaderView);
115 };
116
117 CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame)
38 : frame_(frame), 118 : frame_(frame),
119 header_painter_(new ash::HeaderPainter),
39 caption_button_container_(NULL), 120 caption_button_container_(NULL),
40 header_painter_(new ash::HeaderPainter), 121 maximize_bubble_(NULL),
41 frame_border_hit_test_controller_( 122 paint_as_active_(false),
42 new FrameBorderHitTestController(frame_)) { 123 fullscreen_visible_fraction_(0) {
43 // Unfortunately, there is no views::WidgetDelegate::CanMinimize(). Assume 124 // Unfortunately, there is no views::WidgetDelegate::CanMinimize(). Assume
44 // that the window frame can be minimized if it can be maximized. 125 // that the window frame can be minimized if it can be maximized.
45 FrameCaptionButtonContainerView::MinimizeAllowed minimize_allowed = 126 FrameCaptionButtonContainerView::MinimizeAllowed minimize_allowed =
46 frame_->widget_delegate()->CanMaximize() ? 127 frame_->widget_delegate()->CanMaximize() ?
47 FrameCaptionButtonContainerView::MINIMIZE_ALLOWED : 128 FrameCaptionButtonContainerView::MINIMIZE_ALLOWED :
48 FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED; 129 FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED;
49 caption_button_container_ = new FrameCaptionButtonContainerView(frame, 130 caption_button_container_ = new FrameCaptionButtonContainerView(frame_,
50 minimize_allowed); 131 minimize_allowed);
51 AddChildView(caption_button_container_); 132 AddChildView(caption_button_container_);
133 FrameMaximizeButton* frame_maximize_button =
134 caption_button_container_->GetOldStyleSizeButton();
135 if (frame_maximize_button)
136 frame_maximize_button->AddObserver(this);
52 137
53 header_painter_->Init(frame_, this, NULL, caption_button_container_); 138 header_painter_->Init(frame_, this, NULL, caption_button_container_);
54 } 139 }
55 140
141 CustomFrameViewAsh::HeaderView::~HeaderView() {
142 }
143
144 void CustomFrameViewAsh::HeaderView::SchedulePaintForTitle() {
145 header_painter_->SchedulePaintForTitle(GetTitleFont());
146 }
147
148 void CustomFrameViewAsh::HeaderView::ResetWindowControls() {
149 caption_button_container_->ResetWindowControls();
150 }
151
152 int CustomFrameViewAsh::HeaderView::GetPreferredOnScreenHeight() const {
153 if (frame_->IsFullscreen()) {
154 return static_cast<int>(
155 GetPreferredHeight() * fullscreen_visible_fraction_);
156 }
157 return GetPreferredHeight();
158 }
159
160 int CustomFrameViewAsh::HeaderView::GetPreferredHeight() const {
161 // Reserve enough space to see the buttons and the separator line.
162 return caption_button_container_->bounds().bottom() +
163 header_painter_->HeaderContentSeparatorSize();
164 }
165
166 int CustomFrameViewAsh::HeaderView::GetMinimumWidth() const {
167 return header_painter_->GetMinimumHeaderWidth();
168 }
169
170 void CustomFrameViewAsh::HeaderView::Layout() {
171 header_painter_->LayoutHeader(true);
172 header_painter_->set_header_height(GetPreferredHeight());
173 }
174
175 void CustomFrameViewAsh::HeaderView::OnPaint(gfx::Canvas* canvas) {
176 int theme_image_id = 0;
177 if (header_painter_->ShouldUseMinimalHeaderStyle(HeaderPainter::THEMED_NO))
178 theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_MINIMAL;
179 else if (paint_as_active_)
180 theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_ACTIVE;
181 else
182 theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_INACTIVE;
183
184 header_painter_->PaintHeader(
185 canvas,
186 paint_as_active_ ? HeaderPainter::ACTIVE : HeaderPainter::INACTIVE,
187 theme_image_id,
188 0);
189 header_painter_->PaintTitleBar(canvas, GetTitleFont());
190 header_painter_->PaintHeaderContentSeparator(canvas);
191 }
192
193 void CustomFrameViewAsh::HeaderView::OnImmersiveRevealStarted() {
194 fullscreen_visible_fraction_ = 0;
195 SetPaintToLayer(true);
196 parent()->Layout();
197 }
198
199 void CustomFrameViewAsh::HeaderView::OnImmersiveRevealEnded() {
200 fullscreen_visible_fraction_ = 0;
201 SetPaintToLayer(false);
202 parent()->Layout();
203 }
204
205 void CustomFrameViewAsh::HeaderView::OnImmersiveFullscreenExited() {
206 fullscreen_visible_fraction_ = 0;
207 SetPaintToLayer(false);
208 parent()->Layout();
209 }
210
211 void CustomFrameViewAsh::HeaderView::SetVisibleFraction(
212 double visible_fraction) {
213 if (fullscreen_visible_fraction_ != visible_fraction) {
214 fullscreen_visible_fraction_ = visible_fraction;
215 parent()->Layout();
216 }
217 }
218
219 std::vector<gfx::Rect>
220 CustomFrameViewAsh::HeaderView::GetVisibleBoundsInScreen() const {
221 // TODO(pkotwicz): Implement views::View::ConvertRectToScreen().
222 gfx::Rect visible_bounds(GetVisibleBounds());
223 gfx::Point visible_origin_in_screen(
224 visible_bounds.origin());
225 views::View::ConvertPointToScreen(this, &visible_origin_in_screen);
226 std::vector<gfx::Rect> bounds_in_screen;
227 bounds_in_screen.push_back(
228 gfx::Rect(visible_origin_in_screen, visible_bounds.size()));
229 if (maximize_bubble_lifetime_observer_.get() &&
230 maximize_bubble_lifetime_observer_->IsWidgetAlive()) {
231 bounds_in_screen.push_back(maximize_bubble_->GetWindowBoundsInScreen());
232 }
233 return bounds_in_screen;
234 }
235
236 void CustomFrameViewAsh::HeaderView::OnMaximizeBubbleShown(
237 views::Widget* bubble) {
238 maximize_bubble_ = bubble;
239 maximize_bubble_lifetime_observer_.reset(
240 new views::WidgetDeletionObserver(bubble));
241 }
242
243 ///////////////////////////////////////////////////////////////////////////////
244 // CustomFrameViewAsh::OverlayView
245
246 // View which takes up the entire widget and contains the HeaderView. HeaderView
247 // is a child of OverlayView to avoid creating a larger texture than necessary
248 // when painting the HeaderView to its own layer.
249 class CustomFrameViewAsh::OverlayView : public views::View {
250 public:
251 explicit OverlayView(HeaderView* header_view);
252 virtual ~OverlayView();
253
254 // views::View override:
255 virtual void Layout() OVERRIDE;
256
257 private:
258 HeaderView* header_view_;
259
260 DISALLOW_COPY_AND_ASSIGN(OverlayView);
261 };
262
263 CustomFrameViewAsh::OverlayView::OverlayView(HeaderView* header_view)
264 : header_view_(header_view) {
265 AddChildView(header_view);
266 }
267
268 CustomFrameViewAsh::OverlayView::~OverlayView() {
269 }
270
271 void CustomFrameViewAsh::OverlayView::Layout() {
272 int onscreen_height = header_view_->GetPreferredOnScreenHeight();
273 if (onscreen_height == 0) {
274 header_view_->SetVisible(false);
275 } else {
276 int height = header_view_->GetPreferredHeight();
277 header_view_->SetBounds(0, onscreen_height - height, width(), height);
278 header_view_->SetVisible(true);
279 }
280 }
281
282 ////////////////////////////////////////////////////////////////////////////////
283 // CustomFrameViewAsh, public:
284
285 // static
286 const char CustomFrameViewAsh::kViewClassName[] = "CustomFrameViewAsh";
287
288 CustomFrameViewAsh::CustomFrameViewAsh(views::Widget* frame)
289 : frame_(frame),
290 header_view_(new HeaderView(frame)),
291 frame_border_hit_test_controller_(
292 new FrameBorderHitTestController(frame_)) {
293 // |header_view_| is set as the non client view's overlay view so that it can
294 // overlay the web contents in immersive fullscreen.
295 frame->non_client_view()->SetOverlayView(new OverlayView(header_view_));
296 }
297
56 CustomFrameViewAsh::~CustomFrameViewAsh() { 298 CustomFrameViewAsh::~CustomFrameViewAsh() {
57 } 299 }
58 300
301 void CustomFrameViewAsh::InitImmersiveFullscreenControllerForView(
302 ImmersiveFullscreenController* immersive_fullscreen_controller) {
303 immersive_fullscreen_controller->Init(header_view_, frame_, header_view_);
304 }
305
59 //////////////////////////////////////////////////////////////////////////////// 306 ////////////////////////////////////////////////////////////////////////////////
60 // CustomFrameViewAsh, views::NonClientFrameView overrides: 307 // CustomFrameViewAsh, views::NonClientFrameView overrides:
308
61 gfx::Rect CustomFrameViewAsh::GetBoundsForClientView() const { 309 gfx::Rect CustomFrameViewAsh::GetBoundsForClientView() const {
62 int top_height = NonClientTopBorderHeight(); 310 int top_height = NonClientTopBorderHeight();
63 return HeaderPainter::GetBoundsForClientView(top_height, bounds()); 311 return HeaderPainter::GetBoundsForClientView(top_height, bounds());
64 } 312 }
65 313
66 gfx::Rect CustomFrameViewAsh::GetWindowBoundsForClientBounds( 314 gfx::Rect CustomFrameViewAsh::GetWindowBoundsForClientBounds(
67 const gfx::Rect& client_bounds) const { 315 const gfx::Rect& client_bounds) const {
68 int top_height = NonClientTopBorderHeight(); 316 int top_height = NonClientTopBorderHeight();
69 return HeaderPainter::GetWindowBoundsForClientBounds(top_height, 317 return HeaderPainter::GetWindowBoundsForClientBounds(top_height,
70 client_bounds); 318 client_bounds);
71 } 319 }
72 320
73 int CustomFrameViewAsh::NonClientHitTest(const gfx::Point& point) { 321 int CustomFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
74 return FrameBorderHitTestController::NonClientHitTest(this, 322 return FrameBorderHitTestController::NonClientHitTest(this,
75 header_painter_.get(), point); 323 header_view_->header_painter(), point);
76 } 324 }
77 325
78 void CustomFrameViewAsh::GetWindowMask(const gfx::Size& size, 326 void CustomFrameViewAsh::GetWindowMask(const gfx::Size& size,
79 gfx::Path* window_mask) { 327 gfx::Path* window_mask) {
80 // No window masks in Aura. 328 // No window masks in Aura.
81 } 329 }
82 330
83 void CustomFrameViewAsh::ResetWindowControls() { 331 void CustomFrameViewAsh::ResetWindowControls() {
84 caption_button_container_->ResetWindowControls(); 332 header_view_->ResetWindowControls();
85 } 333 }
86 334
87 void CustomFrameViewAsh::UpdateWindowIcon() { 335 void CustomFrameViewAsh::UpdateWindowIcon() {
88 } 336 }
89 337
90 void CustomFrameViewAsh::UpdateWindowTitle() { 338 void CustomFrameViewAsh::UpdateWindowTitle() {
91 header_painter_->SchedulePaintForTitle(GetTitleFont()); 339 header_view_->SchedulePaintForTitle();
340 }
341
342 void CustomFrameViewAsh::ShouldPaintAsActiveChanged() {
343 header_view_->set_paint_as_active(ShouldPaintAsActive());
344 header_view_->SchedulePaint();
92 } 345 }
93 346
94 //////////////////////////////////////////////////////////////////////////////// 347 ////////////////////////////////////////////////////////////////////////////////
95 // CustomFrameViewAsh, views::View overrides: 348 // CustomFrameViewAsh, views::View overrides:
96 349
97 gfx::Size CustomFrameViewAsh::GetPreferredSize() { 350 gfx::Size CustomFrameViewAsh::GetPreferredSize() {
98 gfx::Size pref = frame_->client_view()->GetPreferredSize(); 351 gfx::Size pref = frame_->client_view()->GetPreferredSize();
99 gfx::Rect bounds(0, 0, pref.width(), pref.height()); 352 gfx::Rect bounds(0, 0, pref.width(), pref.height());
100 return frame_->non_client_view()->GetWindowBoundsForClientBounds( 353 return frame_->non_client_view()->GetWindowBoundsForClientBounds(
101 bounds).size(); 354 bounds).size();
102 } 355 }
103 356
104 void CustomFrameViewAsh::Layout() {
105 // Use the shorter maximized layout headers.
106 header_painter_->LayoutHeader(true);
107 header_painter_->set_header_height(NonClientTopBorderHeight());
108 }
109
110 void CustomFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
111 if (frame_->IsFullscreen())
112 return;
113
114 // Prevent bleeding paint onto the client area below the window frame, which
115 // may become visible when the WebContent is transparent.
116 canvas->Save();
117 canvas->ClipRect(gfx::Rect(0, 0, width(), NonClientTopBorderHeight()));
118
119 bool paint_as_active = ShouldPaintAsActive();
120 int theme_image_id = 0;
121 if (header_painter_->ShouldUseMinimalHeaderStyle(HeaderPainter::THEMED_NO))
122 theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_MINIMAL;
123 else if (paint_as_active)
124 theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_ACTIVE;
125 else
126 theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_INACTIVE;
127
128 header_painter_->PaintHeader(
129 canvas,
130 paint_as_active ? HeaderPainter::ACTIVE : HeaderPainter::INACTIVE,
131 theme_image_id,
132 0);
133 header_painter_->PaintTitleBar(canvas, GetTitleFont());
134 header_painter_->PaintHeaderContentSeparator(canvas);
135 canvas->Restore();
136 }
137
138 const char* CustomFrameViewAsh::GetClassName() const { 357 const char* CustomFrameViewAsh::GetClassName() const {
139 return kViewClassName; 358 return kViewClassName;
140 } 359 }
141 360
142 gfx::Size CustomFrameViewAsh::GetMinimumSize() { 361 gfx::Size CustomFrameViewAsh::GetMinimumSize() {
143 gfx::Size min_client_view_size(frame_->client_view()->GetMinimumSize()); 362 gfx::Size min_client_view_size(frame_->client_view()->GetMinimumSize());
144 return gfx::Size( 363 return gfx::Size(
145 std::max(header_painter_->GetMinimumHeaderWidth(), 364 std::max(header_view_->GetMinimumWidth(), min_client_view_size.width()),
146 min_client_view_size.width()),
147 NonClientTopBorderHeight() + min_client_view_size.height()); 365 NonClientTopBorderHeight() + min_client_view_size.height());
148 } 366 }
149 367
150 gfx::Size CustomFrameViewAsh::GetMaximumSize() { 368 gfx::Size CustomFrameViewAsh::GetMaximumSize() {
151 return frame_->client_view()->GetMaximumSize(); 369 return frame_->client_view()->GetMaximumSize();
152 } 370 }
153 371
372 bool CustomFrameViewAsh::HitTestRect(const gfx::Rect& rect) const {
373 // NonClientView hit tests the NonClientFrameView first instead of going in
374 // z-order. Return false so that events get to the OverlayView.
375 return false;
376 }
377
154 //////////////////////////////////////////////////////////////////////////////// 378 ////////////////////////////////////////////////////////////////////////////////
155 // CustomFrameViewAsh, private: 379 // CustomFrameViewAsh, private:
156 380
157 int CustomFrameViewAsh::NonClientTopBorderHeight() const { 381 int CustomFrameViewAsh::NonClientTopBorderHeight() const {
158 if (frame_->IsFullscreen()) 382 return header_view_->GetPreferredOnScreenHeight();
159 return 0;
160
161 // Reserve enough space to see the buttons, including any offset from top and
162 // reserving space for the separator line.
163 return caption_button_container_->bounds().bottom() +
164 header_painter_->HeaderContentSeparatorSize();
165 } 383 }
166 384
167 } // namespace ash 385 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698