Home | History | Annotate | Download | only in wm
      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