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. 4 5 #ifndef ASH_WM_FRAME_PAINTER_H_ 6 #define ASH_WM_FRAME_PAINTER_H_ 7 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" 16 17 namespace aura { 18 class RootWindow; 19 class Window; 20 } 21 namespace gfx { 22 class Canvas; 23 class Font; 24 class ImageSkia; 25 class Point; 26 class Size; 27 } 28 namespace ui { 29 class SlideAnimation; 30 } 31 namespace views { 32 class ImageButton; 33 class NonClientFrameView; 34 class ToggleImageButton; 35 class View; 36 class Widget; 37 } 38 39 namespace ash { 40 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 { 46 public: 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; 51 52 enum HeaderMode { 53 ACTIVE, 54 INACTIVE 55 }; 56 57 enum Themed { 58 THEMED_YES, 59 THEMED_NO 60 }; 61 62 // What happens when the |size_button_| is pressed. 63 enum SizeButtonBehavior { 64 SIZE_BUTTON_MINIMIZES, 65 SIZE_BUTTON_MAXIMIZES 66 }; 67 68 FramePainter(); 69 virtual ~FramePainter(); 70 71 // |frame| and buttons are used for layout and are not owned. 72 void Init(views::Widget* frame, 73 views::View* window_icon, 74 views::ImageButton* size_button, 75 views::ImageButton* close_button, 76 SizeButtonBehavior behavior); 77 78 // Updates the solo-window transparent header appearance for all windows 79 // using frame painters in |root_window|. 80 static void UpdateSoloWindowHeader(aura::RootWindow* root_window); 81 82 // Helpers for views::NonClientFrameView implementations. 83 gfx::Rect GetBoundsForClientView(int top_height, 84 const gfx::Rect& window_bounds) const; 85 gfx::Rect GetWindowBoundsForClientBounds( 86 int top_height, 87 const gfx::Rect& client_bounds) const; 88 int NonClientHitTest(views::NonClientFrameView* view, 89 const gfx::Point& point); 90 gfx::Size GetMinimumSize(views::NonClientFrameView* view); 91 gfx::Size GetMaximumSize(views::NonClientFrameView* view); 92 93 // Returns the inset from the right edge. 94 int GetRightInset() const; 95 96 // Returns the amount that the theme background should be inset. 97 int GetThemeBackgroundXInset() const; 98 99 // Returns true if the header should be painted using a minimalistic style. 100 bool ShouldUseMinimalHeaderStyle(Themed header_themed) const; 101 102 // Paints the frame header. 103 // |theme_frame_overlay_id| is 0 if no overlay image should be used. 104 void PaintHeader(views::NonClientFrameView* view, 105 gfx::Canvas* canvas, 106 HeaderMode header_mode, 107 int theme_frame_id, 108 int theme_frame_overlay_id); 109 110 // Paints the header/content separator line. Exists as a separate function 111 // because some windows with complex headers (e.g. browsers with tab strips) 112 // need to draw their own line. 113 void PaintHeaderContentSeparator(views::NonClientFrameView* view, 114 gfx::Canvas* canvas); 115 116 // Returns size of the header/content separator line in pixels. 117 int HeaderContentSeparatorSize() const; 118 119 // Paint the title bar, primarily the title string. 120 void PaintTitleBar(views::NonClientFrameView* view, 121 gfx::Canvas* canvas, 122 const gfx::Font& title_font); 123 124 // Performs layout for the header based on whether we want the shorter 125 // appearance. |shorter_layout| is typically used for maximized windows, but 126 // not always. 127 void LayoutHeader(views::NonClientFrameView* view, bool shorter_layout); 128 129 // Schedule a re-paint of the entire title. 130 void SchedulePaintForTitle(const gfx::Font& title_font); 131 132 // Called when the browser theme changes. 133 void OnThemeChanged(); 134 135 // aura::WindowObserver overrides: 136 virtual void OnWindowPropertyChanged(aura::Window* window, 137 const void* key, 138 intptr_t old) OVERRIDE; 139 virtual void OnWindowVisibilityChanged(aura::Window* window, 140 bool visible) OVERRIDE; 141 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; 142 virtual void OnWindowBoundsChanged(aura::Window* window, 143 const gfx::Rect& old_bounds, 144 const gfx::Rect& new_bounds) OVERRIDE; 145 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE; 146 virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE; 147 148 // Overridden from ui::AnimationDelegate 149 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; 150 151 private: 152 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, CreateAndDeleteSingleWindow); 153 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeader); 154 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeaderWithApp); 155 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeaderWithPanel); 156 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeaderModal); 157 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeaderConstrained); 158 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeaderNotDrawn); 159 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeaderMultiDisplay); 160 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, GetHeaderOpacity); 161 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, TitleIconAlignment); 162 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, ChildWindowVisibility); 163 FRIEND_TEST_ALL_PREFIXES(FramePainterTest, 164 NoCrashShutdownWithAlwaysOnTopWindow); 165 166 // Sets the images for a button based on IDs from the |frame_| theme provider. 167 void SetButtonImages(views::ImageButton* button, 168 int normal_image_id, 169 int hot_image_id, 170 int pushed_image_id); 171 172 // Sets the toggled-state button images for a button based on IDs from the 173 // |frame_| theme provider. 174 void SetToggledButtonImages(views::ToggleImageButton* button, 175 int normal_image_id, 176 int hot_image_id, 177 int pushed_image_id); 178 179 // Returns the offset between window left edge and title string. 180 int GetTitleOffsetX() const; 181 182 // Returns the vertical center of the close button in window coordinates. 183 int GetCloseButtonCenterY() const; 184 185 // Returns the opacity value used to paint the header. 186 // |theme_frame_overlay_id| is 0 if no overlay image is used. 187 int GetHeaderOpacity(HeaderMode header_mode, 188 int theme_frame_id, 189 int theme_frame_overlay_id) const; 190 191 // Returns the radius of the header's top corners. 192 int GetHeaderCornerRadius() const; 193 194 // Adjust frame operations for left / right maximized modes. 195 int AdjustFrameHitCodeForMaximizedModes(int hit_code); 196 197 // Returns true if |window_->GetRootWindow()| should be drawing transparent 198 // window headers. 199 bool UseSoloWindowHeader() const; 200 201 // Returns true if |root_window| has exactly one visible, normal-type window. 202 // It ignores |ignore_window| while calculating the number of windows. 203 // Pass NULL for |ignore_window| to consider all windows. 204 static bool UseSoloWindowHeaderInRoot(aura::RootWindow* root_window, 205 aura::Window* ignore_window); 206 207 // Updates the solo-window transparent header appearance for all windows in 208 // |root_window|. If |ignore_window| is not NULL it is ignored for when 209 // counting visible windows. This is useful for updates when a window is about 210 // to be closed or is moving to another root. If the solo window status 211 // changes it schedules paints as necessary. 212 static void UpdateSoloWindowInRoot(aura::RootWindow* root_window, 213 aura::Window* ignore_window); 214 215 // Schedules a paint for the header. Used when transitioning from no header to 216 // a header (or other way around). 217 void SchedulePaintForHeader(); 218 219 // Get the bounds for the title. The provided |title_font| is used to 220 // determine the correct dimensions. 221 gfx::Rect GetTitleBounds(const gfx::Font& title_font); 222 223 // Not owned 224 views::Widget* frame_; 225 views::View* window_icon_; // May be NULL. 226 views::ImageButton* size_button_; 227 views::ImageButton* close_button_; 228 aura::Window* window_; 229 230 // Window frame header/caption parts. 231 const gfx::ImageSkia* button_separator_; 232 const gfx::ImageSkia* top_left_corner_; 233 const gfx::ImageSkia* top_edge_; 234 const gfx::ImageSkia* top_right_corner_; 235 const gfx::ImageSkia* header_left_edge_; 236 const gfx::ImageSkia* header_right_edge_; 237 238 // Image ids and opacity last used for painting header. 239 int previous_theme_frame_id_; 240 int previous_theme_frame_overlay_id_; 241 int previous_opacity_; 242 243 // Image ids and opacity we are crossfading from. 244 int crossfade_theme_frame_id_; 245 int crossfade_theme_frame_overlay_id_; 246 int crossfade_opacity_; 247 248 gfx::Rect header_frame_bounds_; 249 scoped_ptr<ui::SlideAnimation> crossfade_animation_; 250 251 SizeButtonBehavior size_button_behavior_; 252 253 DISALLOW_COPY_AND_ASSIGN(FramePainter); 254 }; 255 256 } // namespace ash 257 258 #endif // ASH_WM_FRAME_PAINTER_H_ 259