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.
5 #ifndef ASH_WM_FRAME_PAINTER_H_
6 #define ASH_WM_FRAME_PAINTER_H_
8 #include "ash/ash_export.h"
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h" // OVERRIDE
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "ui/aura/window_observer.h"
14 #include "ui/base/animation/animation_delegate.h"
15 #include "ui/gfx/rect.h"
33 class NonClientFrameView
;
34 class ToggleImageButton
;
41 // Helper class for painting window frames. Exists to share code between
42 // various implementations of views::NonClientFrameView. Canonical source of
43 // layout constants for Ash window frames.
44 class ASH_EXPORT FramePainter
: public aura::WindowObserver
,
45 public ui::AnimationDelegate
{
47 // Opacity values for the window header in various states, from 0 to 255.
48 static int kActiveWindowOpacity
;
49 static int kInactiveWindowOpacity
;
50 static int kSoloWindowOpacity
;
57 // What happens when the |size_button_| is pressed.
58 enum SizeButtonBehavior
{
59 SIZE_BUTTON_MINIMIZES
,
64 virtual ~FramePainter();
66 // |frame| and buttons are used for layout and are not owned.
67 void Init(views::Widget
* frame
,
68 views::View
* window_icon
,
69 views::ImageButton
* size_button
,
70 views::ImageButton
* close_button
,
71 SizeButtonBehavior behavior
);
73 // Updates the solo-window transparent header appearance for all windows
74 // using frame painters in |root_window|.
75 static void UpdateSoloWindowHeader(aura::RootWindow
* root_window
);
77 // Helpers for views::NonClientFrameView implementations.
78 gfx::Rect
GetBoundsForClientView(int top_height
,
79 const gfx::Rect
& window_bounds
) const;
80 gfx::Rect
GetWindowBoundsForClientBounds(
82 const gfx::Rect
& client_bounds
) const;
83 int NonClientHitTest(views::NonClientFrameView
* view
,
84 const gfx::Point
& point
);
85 gfx::Size
GetMinimumSize(views::NonClientFrameView
* view
);
86 gfx::Size
GetMaximumSize(views::NonClientFrameView
* view
);
88 // Returns the inset from the right edge.
89 int GetRightInset() const;
91 // Returns the amount that the theme background should be inset.
92 int GetThemeBackgroundXInset() const;
94 // Paints the frame header.
95 void PaintHeader(views::NonClientFrameView
* view
,
97 HeaderMode header_mode
,
99 const gfx::ImageSkia
* theme_frame_overlay
);
101 // Paints the header/content separator line. Exists as a separate function
102 // because some windows with complex headers (e.g. browsers with tab strips)
103 // need to draw their own line.
104 void PaintHeaderContentSeparator(views::NonClientFrameView
* view
,
105 gfx::Canvas
* canvas
);
107 // Returns size of the header/content separator line in pixels.
108 int HeaderContentSeparatorSize() const;
110 // Paint the title bar, primarily the title string.
111 void PaintTitleBar(views::NonClientFrameView
* view
,
113 const gfx::Font
& title_font
);
115 // Performs layout for the header based on whether we want the shorter
116 // appearance. |shorter_layout| is typically used for maximized windows, but
118 void LayoutHeader(views::NonClientFrameView
* view
, bool shorter_layout
);
120 // Schedule a re-paint of the entire title.
121 void SchedulePaintForTitle(views::NonClientFrameView
* view
,
122 const gfx::Font
& title_font
);
124 // aura::WindowObserver overrides:
125 virtual void OnWindowPropertyChanged(aura::Window
* window
,
127 intptr_t old
) OVERRIDE
;
128 virtual void OnWindowVisibilityChanged(aura::Window
* window
,
129 bool visible
) OVERRIDE
;
130 virtual void OnWindowDestroying(aura::Window
* window
) OVERRIDE
;
131 virtual void OnWindowBoundsChanged(aura::Window
* window
,
132 const gfx::Rect
& old_bounds
,
133 const gfx::Rect
& new_bounds
) OVERRIDE
;
134 virtual void OnWindowAddedToRootWindow(aura::Window
* window
) OVERRIDE
;
135 virtual void OnWindowRemovingFromRootWindow(aura::Window
* window
) OVERRIDE
;
137 // Overridden from ui::AnimationDelegate
138 virtual void AnimationProgressed(const ui::Animation
* animation
) OVERRIDE
;
141 FRIEND_TEST_ALL_PREFIXES(FramePainterTest
, CreateAndDeleteSingleWindow
);
142 FRIEND_TEST_ALL_PREFIXES(FramePainterTest
, UseSoloWindowHeader
);
143 FRIEND_TEST_ALL_PREFIXES(FramePainterTest
, UseSoloWindowHeaderWithApp
);
144 FRIEND_TEST_ALL_PREFIXES(FramePainterTest
, UseSoloWindowHeaderWithPanel
);
145 FRIEND_TEST_ALL_PREFIXES(FramePainterTest
, UseSoloWindowHeaderConstrained
);
146 FRIEND_TEST_ALL_PREFIXES(FramePainterTest
, UseSoloWindowHeaderMultiDisplay
);
147 FRIEND_TEST_ALL_PREFIXES(FramePainterTest
, GetHeaderOpacity
);
149 // Sets the images for a button based on IDs from the |frame_| theme provider.
150 void SetButtonImages(views::ImageButton
* button
,
153 int pushed_image_id
);
155 // Sets the toggled-state button images for a button based on IDs from the
156 // |frame_| theme provider.
157 void SetToggledButtonImages(views::ToggleImageButton
* button
,
160 int pushed_image_id
);
162 // Returns the offset between window left edge and title string.
163 int GetTitleOffsetX() const;
165 // Returns the opacity value used to paint the header.
166 int GetHeaderOpacity(HeaderMode header_mode
,
168 const gfx::ImageSkia
* theme_frame_overlay
);
170 // Adjust frame operations for left / right maximized modes.
171 int AdjustFrameHitCodeForMaximizedModes(int hit_code
);
173 // Returns true if the user is cycling through workspaces.
174 bool IsCyclingThroughWorkspaces() const;
176 // Returns true if |window_->GetRootWindow()| should be drawing transparent
178 bool UseSoloWindowHeader();
180 // Returns true if |root_window| has exactly one visible, normal-type window.
181 // It ignores |ignore_window| while calculating the number of windows.
182 // Pass NULL for |ignore_window| to consider all windows.
183 static bool UseSoloWindowHeaderInRoot(aura::RootWindow
* root_window
,
184 aura::Window
* ignore_window
);
186 // Updates the solo-window transparent header appearance for all windows in
187 // |root_window|. If |ignore_window| is not NULL it is ignored for when
188 // counting visible windows. This is useful for updates when a window is about
189 // to be closed or is moving to another root. If the solo window status
190 // changes it schedules paints as necessary.
191 static void UpdateSoloWindowInRoot(aura::RootWindow
* root_window
,
192 aura::Window
* ignore_window
);
194 // Schedules a paint for the header. Used when transitioning from no header to
195 // a header (or other way around).
196 void SchedulePaintForHeader();
198 // Get the bounds for the title. The provided |view| and |title_font| are
199 // used to determine the correct dimensions.
200 gfx::Rect
GetTitleBounds(views::NonClientFrameView
* view
,
201 const gfx::Font
& title_font
);
204 views::Widget
* frame_
;
205 views::View
* window_icon_
; // May be NULL.
206 views::ImageButton
* size_button_
;
207 views::ImageButton
* close_button_
;
208 aura::Window
* window_
;
210 // Window frame header/caption parts.
211 const gfx::ImageSkia
* button_separator_
;
212 const gfx::ImageSkia
* top_left_corner_
;
213 const gfx::ImageSkia
* top_edge_
;
214 const gfx::ImageSkia
* top_right_corner_
;
215 const gfx::ImageSkia
* header_left_edge_
;
216 const gfx::ImageSkia
* header_right_edge_
;
218 // Image id and opacity last used for painting header.
219 int previous_theme_frame_id_
;
220 int previous_opacity_
;
222 // Image id and opacity we are crossfading from.
223 int crossfade_theme_frame_id_
;
224 int crossfade_opacity_
;
226 gfx::Rect header_frame_bounds_
;
227 scoped_ptr
<ui::SlideAnimation
> crossfade_animation_
;
229 SizeButtonBehavior size_button_behavior_
;
231 DISALLOW_COPY_AND_ASSIGN(FramePainter
);
236 #endif // ASH_WM_FRAME_PAINTER_H_